import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/utils/constants/assets.dart';

class CpsOperationalValue {
  final String icon;
  final String description;
  final dynamic value;


  CpsOperationalValue({
    required this.icon,
    required this.description,
    required this.value,

  });
}

abstract class CpsFunctions extends DeviceFunction<CpsOperationalValue> {
  CpsFunctions({
    required super.deviceId,
    required super.deviceName,
    required super.code,
    required super.operationName,
    required super.icon,
    required this.type,
  });

  final String type;

  List<CpsOperationalValue> getOperationalValues();
}

final class CpsRadarSwitchFunction extends CpsFunctions {
  CpsRadarSwitchFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  }) : super(
          code: 'radar_switch',
          operationName: 'Radar Switch',
          icon: Assets.acPower,
        );

  @override
  List<CpsOperationalValue> getOperationalValues() => [
        CpsOperationalValue(
          icon: Assets.assetsAcPower,
          description: "ON",
          value: true,
        ),
        CpsOperationalValue(
          icon: Assets.assetsAcPowerOFF,
          description: "OFF",
          value: false,
        ),
      ];
}

final class CpsSpatialParameterSwitchFunction extends CpsFunctions {
  CpsSpatialParameterSwitchFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  }) : super(
          code: 'space_para_switch',
          operationName: 'Spatial Parameter Switch',
          icon: Assets.acPower,
        );

  @override
  List<CpsOperationalValue> getOperationalValues() => [
        CpsOperationalValue(
          icon: Assets.assetsAcPower,
          description: "ON",
          value: true,
        ),
        CpsOperationalValue(
          icon: Assets.assetsAcPowerOFF,
          description: "OFF",
          value: false,
        ),
      ];
}

final class CpsSensitivityFunction extends CpsFunctions {
  CpsSensitivityFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  })  : min = 1,
        max = 10,
        step = 1,
        super(
          code: 'sensitivity',
          operationName: 'Sensitivity',
          icon: Assets.sensitivity,
        );

  final double min;
  final double max;
  final double step;

  static const _images = <String>[
    Assets.sensitivityFeature1,
    Assets.sensitivityFeature1,
    Assets.sensitivityFeature2,
    Assets.sensitivityFeature3,
    Assets.sensitivityFeature4,
    Assets.sensitivityFeature5,
    Assets.sensitivityFeature6,
    Assets.sensitivityFeature7,
    Assets.sensitivityFeature8,
    Assets.sensitivityFeature9,
    Assets.sensitivityFeature9,
  ];

  @override
  List<CpsOperationalValue> getOperationalValues() {
    final values = <CpsOperationalValue>[];
    for (var value = min; value <= max; value += step.toInt()) {
      values.add(
        CpsOperationalValue(
          icon: _images[value.toInt()],
          description: '$value',
          value: value,
        ),
      );
    }
    return values;
  }
}

final class CpsMovingSpeedFunction extends CpsFunctions {
  CpsMovingSpeedFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  })  : min = 0,
        max = 32,
        step = 1,
        super(
          code: 'moving_speed',
          operationName: 'Moving Speed',
          icon: Assets.speedoMeter,
        );

  final double min;
  final double max;
  final double step;

  @override
  List<CpsOperationalValue> getOperationalValues() {
    return List.generate(
      (max - min) ~/ step + 1,
      (index) => CpsOperationalValue(
        icon: Assets.speedoMeter,
        description: '${min + (index * step)}',
        value: min + (index * step),
      ),
    );
  }
}

final class CpsSpatialStaticValueFunction extends CpsFunctions {
  CpsSpatialStaticValueFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  })  : min = 0,
        max = 255,
        step = 1,
        super(
          code: 'space_static_val',
          operationName: 'Spacial Static Value',
          icon: Assets.spatialStaticValue,
        );

  final double min;
  final double max;
  final double step;

  @override
  List<CpsOperationalValue> getOperationalValues() {
    return List.generate(
      (max - min) ~/ step + 1,
      (index) => CpsOperationalValue(
        icon: Assets.spatialStaticValue,
        description: '${min + (index * step)}',
        value: min + (index * step),
      ),
    );
  }
}

final class CpsSpatialMotionValueFunction extends CpsFunctions {
  CpsSpatialMotionValueFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  })  : min = 0,
        max = 255,
        step = 1,
        super(
          code: 'space_move_val',
          operationName: 'Spatial Motion Value',
          icon: Assets.spatialMotionValue,
        );

  final double min;
  final double max;
  final double step;

  @override
  List<CpsOperationalValue> getOperationalValues() {
    return List.generate(
      (max - min) ~/ step + 1,
      (index) => CpsOperationalValue(
        icon: Assets.spatialMotionValue,
        description: '${min + (index * step)}',
        value: min + (index * step),
      ),
    );
  }
}

final class CpsMaxDistanceOfDetectionFunction extends CpsFunctions {
  CpsMaxDistanceOfDetectionFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  })  : min = 0.0,
        max = 10.0,
        step = 0.5,
        super(
          code: 'moving_max_dis',
          operationName: 'Maximum Distance Of Detection',
          icon: Assets.currentDistanceIcon,
        );

  final double min;
  final double max;
  final double step;

  @override
  List<CpsOperationalValue> getOperationalValues() {
    final count = ((max - min) / step).round() + 1;
    return List.generate(
      count,
      (index) {
        final value = (min + (index * step));
        return CpsOperationalValue(
          icon: Assets.currentDistanceIcon,
          description: '${value.toStringAsFixed(1)} M',
          value: value,
        );
      },
    );
  }
}

final class CpsMaxDistanceOfStaticDetectionFunction extends CpsFunctions {
  CpsMaxDistanceOfStaticDetectionFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  })  : min = 0.0,
        max = 10.0,
        step = 0.5,
        super(
          code: 'static_max_dis',
          operationName: 'Maximum Distance Of Static Detection',
          icon: Assets.currentDistanceIcon,
        );

  final double min;
  final double max;
  final double step;

  @override
  List<CpsOperationalValue> getOperationalValues() {
    final count = ((max - min) / step).round() + 1;
    return List.generate(
      count,
      (index) {
        final value = (min + (index * step));
        return CpsOperationalValue(
          icon: Assets.currentDistanceIcon,
          description: '${value.toStringAsFixed(1)} M',
          value: value,
        );
      },
    );
  }
}

final class CpsDetectionRangeFunction extends CpsFunctions {
  CpsDetectionRangeFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  })  : min = 0.0,
        max = 25.5,
        step = 0.1,
        super(
          code: 'moving_range',
          operationName: 'Detection Range',
          icon: Assets.farDetection,
        );

  final double min;
  final double max;
  final double step;

  @override
  List<CpsOperationalValue> getOperationalValues() {
    final count = ((max - min) / step).round() + 1;
    return List.generate(
      count,
      (index) {
        final value = (min + (index * step));
        return CpsOperationalValue(
          icon: Assets.farDetection,
          description: '${value.toStringAsFixed(1)} M',
          value: value,
        );
      },
    );
  }
}

final class CpsDistanceOfMovingObjectsFunction extends CpsFunctions {
  CpsDistanceOfMovingObjectsFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  })  : min = 0.0,
        max = 25.5,
        step = 0.1,
        super(
          code: 'presence_range',
          operationName: 'Distance Of Moving Objects',
          icon: Assets.currentDistanceIcon,
        );

  final double min;
  final double max;
  final double step;

  @override
  List<CpsOperationalValue> getOperationalValues() {
    final count = ((max - min) / step).round() + 1;
    return List.generate(
      count,
      (index) {
        final value = (min + (index * step));
        return CpsOperationalValue(
          icon: Assets.currentDistanceIcon,
          description: '${value.toStringAsFixed(1)} M',
          value: value,
        );
      },
    );
  }
}

final class CpsPresenceJudgementThrsholdFunction extends CpsFunctions {
  CpsPresenceJudgementThrsholdFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  })  : min = 0,
        max = 255,
        step = 5,
        super(
          code: 'presence_reference',
          operationName: 'Presence Judgement Threshold',
          icon: Assets.presenceJudgementThrshold,
        );

  final double min;
  final double max;
  final double step;

  @override
  List<CpsOperationalValue> getOperationalValues() {
    return List.generate(
      (max - min) ~/ step + 1,
      (index) => CpsOperationalValue(
        icon: Assets.presenceJudgementThrshold,
        description: '${min + (index * step)}',
        value: min + (index * step),
      ),
    );
  }
}

final class CpsMotionAmplitudeTriggerThresholdFunction extends CpsFunctions {
  CpsMotionAmplitudeTriggerThresholdFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  })  : min = 0,
        max = 255,
        step = 5,
        super(
          code: 'moving_reference',
          operationName: 'Motion Amplitude Trigger Threshold',
          icon: Assets.presenceJudgementThrshold,
        );

  final double min;
  final double max;
  final double step;

  @override
  List<CpsOperationalValue> getOperationalValues() {
    return List.generate(
      (max - min) ~/ step + 1,
      (index) => CpsOperationalValue(
        icon: Assets.presenceJudgementThrshold,
        description: '${min + (index * step)}',
        value: min + (index * step),
      ),
    );
  }
}

final class CpsPerpetualBoundaryFunction extends CpsFunctions {
  CpsPerpetualBoundaryFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  })  : min = 0.00,
        max = 5.00,
        step = 0.50,
        super(
          code: 'perceptual_boundary',
          operationName: 'Perpetual Boundary',
          icon: Assets.boundary,
        );

  final double min;
  final double max;
  final double step;

  @override
  List<CpsOperationalValue> getOperationalValues() {
    final count = ((max - min) / step).round() + 1;
    return List.generate(
      count,
      (index) {
        final value = (min + (index * step));
        return CpsOperationalValue(
          icon: Assets.boundary,
          description: '${value.toStringAsFixed(1)}M',
          value: value + 1200,
        );
      },
    );
  }
}

final class CpsMotionTriggerBoundaryFunction extends CpsFunctions {
  CpsMotionTriggerBoundaryFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  })  : min = 0.0,
        max = 5.0,
        step = 0.5,
        super(
          code: 'moving_boundary',
          operationName: 'Motion Trigger Boundary',
          icon: Assets.motionMeter,
        );

  final double min;
  final double max;
  final double step;

  @override
  List<CpsOperationalValue> getOperationalValues() {
    final count = ((max - min) / step).round() + 1;
    return List.generate(
      count,
      (index) {
        final value = (min + (index * step));
        return CpsOperationalValue(
          icon: Assets.motionMeter,
          description: '${value.toStringAsFixed(1)} M',
          value: value,
        );
      },
    );
  }
}

final class CpsMotionTriggerTimeFunction extends CpsFunctions {
  CpsMotionTriggerTimeFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  })  : min = 0.0,
        max = 2.0,
        step = 0.1,
        super(
          code: 'moving_rigger_time',
          operationName: 'Motion Trigger Time',
          icon: Assets.motionMeter,
        );

  final double min;
  final double max;
  final double step;

  @override
  List<CpsOperationalValue> getOperationalValues() {
    final count = ((max - min) / step).round() + 1;
    return List.generate(
      count,
      (index) {
        final value = (min + (index * step));
        return CpsOperationalValue(
          icon: Assets.motionMeter,
          description: '${value.toStringAsFixed(3)} sec',
          value: value,
        );
      },
    );
  }
}

final class CpsMotionToStaticTimeFunction extends CpsFunctions {
  CpsMotionToStaticTimeFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  })  : min = 0.0,
        max = 50.0,
        step = 1.0,
        super(
          code: 'moving_static_time',
          operationName: 'Motion To Static Time',
          icon: Assets.motionMeter,
        );

  final double min;
  final double max;
  final double step;

  @override
  List<CpsOperationalValue> getOperationalValues() {
    final count = ((max - min) / step).round() + 1;
    return List.generate(
      count,
      (index) {
        final value = (min + (index * step));
        return CpsOperationalValue(
          icon: Assets.motionMeter,
          description: '${value.toStringAsFixed(0)} sec',
          value: value,
        );
      },
    );
  }
}

final class CpsEnteringNoBodyStateTimeFunction extends CpsFunctions {
  CpsEnteringNoBodyStateTimeFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  })  : min = 0.0,
        max = 300.0,
        step = 5.0,
        super(
          code: 'none_body_time',
          operationName: 'Entering Nobody State Time',
          icon: Assets.motionMeter,
        );

  final double min;
  final double max;
  final double step;

  @override
  List<CpsOperationalValue> getOperationalValues() {
    final count = ((max - min) / step).round() + 1;
    return List.generate(
      count,
      (index) {
        final value = (min + (index * step));
        return CpsOperationalValue(
          icon: Assets.motionMeter,
          description: '${value.toStringAsFixed(0)} sec',
          value: value,
        );
      },
    );
  }
}

final class CpsSelfTestResultFunctions extends CpsFunctions {
  CpsSelfTestResultFunctions({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  }) : super(
          code: 'checking_result',
          operationName: 'Self-Test Result',
          icon: Assets.selfTestResult,
        );
  @override
  List<CpsOperationalValue> getOperationalValues() {
    return [
      CpsOperationalValue(
        description: 'Self Testing',
        icon: Assets.selfTestResult,
        value: 'check',
      ),
      CpsOperationalValue(
        description: 'Self Testing Success',
        icon: Assets.selfTestingSuccess,
        value: 'check_success',
      ),
      CpsOperationalValue(
        description: 'Self Testing Failure',
        icon: Assets.selfTestingFailure,
        value: 'check_failure',
      ),
      CpsOperationalValue(
        description: 'Self Testing Timeout',
        icon: Assets.selfTestingTimeout,
        value: 'check_timeout',
      ),
      CpsOperationalValue(
        description: 'Communication Fault',
        icon: Assets.communicationFault,
        value: 'communication_fault',
      ),
      CpsOperationalValue(
        description: 'Radar Fault',
        icon: Assets.radarFault,
        value: 'radar_fault',
      ),
    ];
  }
}

final class CpsNobodyTimeFunction extends CpsFunctions {
  CpsNobodyTimeFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  }) : super(
          code: 'nobody_time',
          operationName: 'Entering Nobody Time',
          icon: Assets.assetsNobodyTime,
        );

  @override
  List<CpsOperationalValue> getOperationalValues() {
    return [
      CpsOperationalValue(
        icon: Assets.assetsNobodyTime,
        description: 'None',
        value: 'none',
      ),
      CpsOperationalValue(
        icon: Assets.assetsNobodyTime,
        description: '10sec',
        value: '10s',
      ),
      CpsOperationalValue(
        icon: Assets.assetsNobodyTime,
        description: '30sec',
        value: '30s',
      ),
      CpsOperationalValue(
        icon: Assets.assetsNobodyTime,
        description: '1min',
        value: '1min',
      ),
      CpsOperationalValue(
        icon: Assets.assetsNobodyTime,
        description: '2min',
        value: '2min',
      ),
      CpsOperationalValue(
        icon: Assets.assetsNobodyTime,
        description: '5min',
        value: '5min',
      ),
      CpsOperationalValue(
        icon: Assets.assetsNobodyTime,
        description: '10min',
        value: '10min',
      ),
      CpsOperationalValue(
        icon: Assets.assetsNobodyTime,
        description: '30min',
        value: '30min',
      ),
      CpsOperationalValue(
        icon: Assets.assetsNobodyTime,
        description: '1hour',
        value: '1hr',
      ),
    ];
  }
}

final class CpsMovementFunctions extends CpsFunctions {
  CpsMovementFunctions({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  }) : super(
          code: 'body_movement',
          operationName: 'Movement',
          icon: Assets.motion,
        );
  @override
  List<CpsOperationalValue> getOperationalValues() {
    return [
      CpsOperationalValue(
        description: 'None',
        icon: Assets.nobodyTime,
        value: 'none',
      ),
      CpsOperationalValue(
        description: 'Close To',
        icon: Assets.closeToMotion,
        value: 'close_to',
      ),
      CpsOperationalValue(
        description: 'Far Away',
        icon: Assets.farAwayMotion,
        value: 'far_away',
      ),
    ];
  }
}

final class CpsCustomModeFunction extends CpsFunctions {
  CpsCustomModeFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  }) : super(
          code: 'custom_mode',
          operationName: 'Custom Mode',
          icon: Assets.cpsCustomMode,
        );

  @override
  List<CpsOperationalValue> getOperationalValues() {
    return [
      CpsOperationalValue(
        icon: Assets.cpsMode1,
        description: 'Mode 1',
        value: 'mode1',
      ),
      CpsOperationalValue(
        icon: Assets.cpsMode2,
        description: 'Mode 2',
        value: 'mode2',
      ),
      CpsOperationalValue(
        icon: Assets.cpsMode3,
        description: 'Mode 3',
        value: 'mode3',
      ),
      CpsOperationalValue(
        icon: Assets.cpsMode4,
        description: 'Mode 4',
        value: 'mode4',
      ),
    ];
  }
}

final class CpsSpaceTypeFunctions extends CpsFunctions {
  CpsSpaceTypeFunctions({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  }) : super(
          code: 'scene',
          operationName: 'Space Type',
          icon: Assets.spaceType,
        );
  @override
  List<CpsOperationalValue> getOperationalValues() {
    return [
      CpsOperationalValue(
        description: 'Office',
        icon: Assets.office,
        value: 'office',
      ),
      CpsOperationalValue(
        description: 'Parlour',
        icon: Assets.parlour,
        value: 'parlour',
      ),
      CpsOperationalValue(
        description: 'Bathroom',
        icon: Assets.bathroom,
        value: 'bathroom',
      ),
      CpsOperationalValue(
        description: 'Bedroom',
        icon: Assets.bedroom,
        value: 'bedroom',
      ),
      CpsOperationalValue(
        description: 'DIY',
        icon: Assets.dyi,
        value: 'dyi',
      ),
    ];
  }
}

class CpsPresenceStatusFunctions extends CpsFunctions {
  CpsPresenceStatusFunctions({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  }) : super(
          code: 'presence_state',
          operationName: 'Presence Status',
          icon: Assets.presenceSensor,
        );

  @override
  List<CpsOperationalValue> getOperationalValues() {
    return [
      CpsOperationalValue(
        icon: Assets.nobodyTime,
        description: 'None',
        value: 'none',
      ),
      CpsOperationalValue(
        icon: Assets.presenceState,
        description: 'Presence',
        value: 'presence',
      ),
      CpsOperationalValue(
        icon: Assets.motion,
        description: 'Motion',
        value: 'motion',
      ),
    ];
  }
}

final class CpsSportsParaFunction extends CpsFunctions {
  CpsSportsParaFunction({
    required super.deviceId,
    required super.deviceName,
    required super.type,
  })  : min = 1,
        max = 100,
        step = 1,
        super(
          code: 'sports_para',
          operationName: 'Sports Para',
          icon: Assets.sportsPara,
        );

  final double min;
  final double max;
  final double step;

  @override
  List<CpsOperationalValue> getOperationalValues() {
    final count = ((max - min) / step).round() + 1;
    return List.generate(
      count,
      (index) {
        final value = (min + (index * step));
        return CpsOperationalValue(
          icon: Assets.motionMeter,
          description: value.toStringAsFixed(0),
          value: value,
        );
      },
    );
  }
}
