import {
  ComponentTypeExtension,
  Subtype,
  Summary,
  simpleMeasurements,
  simpleSummaries,
  unitMeasurementSummaries,
  AreaChartData,
  GraphFilters,
  simpleAreaChartData,
  LineChartData,
  simpleLineChartData
} from "pbHelpers/ComponentType";
import HeaterDarkIcon from "assets/components/heaterDark.png";
import HeaterLightIcon from "assets/components/heaterLight.png";
import AerationFanDarkIcon from "assets/components/aerationFanDark.png";
import AerationFanLightIcon from "assets/components/aerationFanLight.png";
import ExhaustFanDarkIcon from "assets/components/exhaustFanDark.png";
import ExhaustFanLightIcon from "assets/components/exhaustFanLight.png";
import { quack } from "protobuf-ts/quack";
import { describeMeasurement } from "pbHelpers/MeasurementDescriber";
import { convertedUnitMeasurement } from "models/UnitMeasurement";
import { pond } from "protobuf-ts/pond";

const determineMinCycleTimeMs = (subtype: number): number => {
  switch (subtype) {
    case 2:
      //Heater
      return 15000;
    case 3:
      //Aeration Fan
      return 30000;
    case 4:
      //Exhaust Fan
      return 15000;
    default:
      return 1000;
  }
};

const subtypes = [
  {
    key: quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_NONE,
    value: "BOOLEAN_OUTPUT_SUBTYPE_NONE",
    friendlyName: "Generic Output"
  } as Subtype,
  {
    key: quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_LED,
    value: "BOOLEAN_OUTPUT_SUBTYPE_LED",
    friendlyName: "LED"
  } as Subtype,
  {
    key: quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_HEATER,
    value: "BOOLEAN_OUTPUT_SUBTYPE_HEATER",
    friendlyName: "Heater"
  } as Subtype,
  {
    key: quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_AERATION_FAN,
    value: "BOOLEAN_OUTPUT_SUBTYPE_FAN",
    friendlyName: "Aeration Fan"
  } as Subtype,
  {
    key: quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_EXHAUST_FAN,
    value: "BOOLEAN_OUTPUT_SUBTYPE_FAN",
    friendlyName: "Exhaust Fan"
  } as Subtype
];

export function OnOffOutput(subtype: number = 0): ComponentTypeExtension {
  let onOff = describeMeasurement(
    quack.MeasurementType.MEASUREMENT_TYPE_BOOLEAN,
    quack.ComponentType.COMPONENT_TYPE_BOOLEAN_OUTPUT,
    subtype
  );

  return {
    type: quack.ComponentType.COMPONENT_TYPE_BOOLEAN_OUTPUT,
    subtypes: subtypes,
    friendlyName: "Controller",
    description: "Controls whether on/off state of an object",
    isController: true,
    isSource: true,
    isCalibratable: false,
    addressTypes: [quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY],
    interactionResultTypes: [
      quack.InteractionResultType.INTERACTION_RESULT_TYPE_TOGGLE,
      quack.InteractionResultType.INTERACTION_RESULT_TYPE_SET,
      quack.InteractionResultType.INTERACTION_RESULT_TYPE_RUN
    ],
    states: onOff.enumerations(),
    measurements: simpleMeasurements(onOff),
    measurementSummary: async function(measurement: quack.Measurement): Promise<Array<Summary>> {
      return simpleSummaries(measurement, onOff);
    },
    unitMeasurementSummary: (
      measurements: convertedUnitMeasurement
    ): Summary[] => {
      return unitMeasurementSummaries(
        measurements,
        quack.ComponentType.COMPONENT_TYPE_BOOLEAN_OUTPUT,
        subtype
      );
    },
    areaChartData: (
      measurement: pond.UnitMeasurementsForComponent,
      smoothingAverages?: number,
      filters?: GraphFilters
    ): AreaChartData => {
      return simpleAreaChartData(measurement, smoothingAverages, filters);
    },
    lineChartData: (
      measurement: pond.UnitMeasurementsForComponent,
      smoothingAverages?: number,
      filters?: GraphFilters
    ): LineChartData => {
      return simpleLineChartData(
        quack.ComponentType.COMPONENT_TYPE_BOOLEAN_OUTPUT,
        measurement,
        smoothingAverages,
        filters
      );
    },
    minMeasurementPeriodMs: 1000,
    minCycleTimeMs: determineMinCycleTimeMs(subtype),
    icon: (theme?: "light" | "dark"): string | undefined => {
      switch (subtype) {
        case 2:
          return theme === "light" ? HeaterDarkIcon : HeaterLightIcon;
        case 3:
          return theme === "light" ? AerationFanDarkIcon : AerationFanLightIcon;
        case 4:
          return theme === "light" ? ExhaustFanDarkIcon : ExhaustFanLightIcon;
        default:
          return undefined;
      }
    }
  };
}
