import { CheckBox, ExpandMore } from "@mui/icons-material";
import { Accordion, AccordionDetails, AccordionSummary, Autocomplete, Box, Checkbox, FormControlLabel, Grid2, TextField, Typography } from "@mui/material";
import { cloneDeep } from "lodash";
import { Ambient } from "models/Ambient";
import { Controller } from "models/Controller";
import { DevicePreset } from "models/DevicePreset";
import { Plenum } from "models/Plenum";
import { pond } from "protobuf-ts/pond";
import { quack } from "protobuf-ts/quack";
import React, { useEffect, useState } from "react";

export interface ComponentSet {
  sensor: Plenum | Ambient,
  controllers: Controller[]
  selectedPresets: Map<string, DevicePreset>
  combo?: boolean //if the set contains both a heater and a fan
}

interface Option {
  label: string;
  id: number;
  icon?: string;
}

interface Props {
  sensor: Plenum | Ambient
  binMode: pond.BinMode
  heaters?: Controller[]
  fans?: Controller[]
  presets?: DevicePreset[]
  updateSet: (sensorKey: string, componentSet?: ComponentSet) => void
}

export default function PickComponentSet(props: Props) {
  const {sensor, heaters, fans, updateSet, presets, binMode} = props
  const [sensorSelected, setSensorSelected] = useState(false)
  const [currentSet, setCurrentSet] = useState<ComponentSet | undefined>()

  useEffect(()=>{
    if (presets){
      let presetOptions: Option[] = [];
      presets.forEach((devicePreset, i) => {
        //add the preset to the possible options
        if (devicePreset.favorite()) {
          //if it is favorited add it to the front of the array
          presetOptions.unshift({
            label: devicePreset.name,
            id: i
          });
        } else {
          //otherwise add it to the end
          presetOptions.push({
            label: devicePreset.name,
            id: i
          });
        }
        
      });
    }
  },[presets])

  const getOptionsForController = (controllerType: pond.ControllerType) => {
    let validOps: Option[] = []
    if(presets){
      presets.forEach((devicePreset, i) => {
        if(devicePreset.controllerType() === controllerType && devicePreset.compareToBinMode(binMode)){
        //add the preset to the possible options
        if (devicePreset.favorite()) {
          //if it is favorited add it to the front of the array
          validOps.unshift({
            label: devicePreset.name,
            id: i
          });
        } else {
          //otherwise add it to the end
          validOps.push({
            label: devicePreset.name,
            id: i
          });
        }
        }
      })
    }
    return validOps
  }

  const controllerIndex = (key: string) => {
    if(!currentSet) return -1
    let index = -1
    currentSet.controllers.forEach((cont, i) => {
      if(cont.key() === key){
        index = i
      }
    })
    return index
  }

  const comboCheck = (set: ComponentSet) => {
    let heaterFound = false
    let fanFound = false
    set.controllers.forEach(controller => {
      if(controller.subType() === quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_HEATER){
        heaterFound = true
      }
      if(controller.subType() === quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_AERATION_FAN ||
         controller.subType() === quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_EXHAUST_FAN){
        fanFound = true
      }
    })
    return heaterFound && fanFound
  }

  return (
    <Box>
      <FormControlLabel
        control={
          <Checkbox
            value={sensorSelected}
            checked={sensorSelected}
            onChange={(_, checked) => {
              setSensorSelected(checked)
              let newSet: ComponentSet | undefined
              if(checked){
                newSet = {
                  sensor: sensor,
                  controllers: [],
                  selectedPresets: new Map<string, DevicePreset>()
                }
              }
              setCurrentSet(newSet)
              updateSet(sensor.key(), newSet)
            }}
          />
        }
        label={sensor.name()}
      />  
      {sensorSelected && currentSet && 
        <Accordion>
          <AccordionSummary expandIcon={<ExpandMore />}>Controllers Selected: {currentSet.controllers.length}</AccordionSummary>
          <AccordionDetails>
            {heaters && heaters.length > 0 && binMode !== pond.BinMode.BIN_MODE_HYDRATING && 
              <React.Fragment>
                <Typography>Heaters</Typography>
                {heaters.map(heater => (
                  <Grid2 key={heater.key()} container justifyContent="space-between" direction="row" alignContent="center" alignItems="center">
                    <Grid2 size={{xs: 12, sm: 6}}>
                      <FormControlLabel 
                        control={
                          <Checkbox 
                            onChange={(_, checked) => {
                              let set = cloneDeep(currentSet)
                              if(checked){//if checked need to add it to the controllers
                                set.controllers.push(heater)  
                              }else{//will need to make sure it is not in the controllers
                                let index = controllerIndex(heater.key())
                                if (index !== -1){
                                  set.controllers.splice(index, 1)
                                }
                              }
                              set.combo = comboCheck(set)
                              setCurrentSet(set)
                              updateSet(sensor.key(), set)
                            }}
                          />
                        }
                        label={heater.name()}
                      />
                    </Grid2>
                    <Grid2 size={{xs: 12, sm: 6}}>
                      {presets && getOptionsForController(pond.ControllerType.CONTROLLER_TYPE_HEATER).length > 0 &&
                        <Autocomplete
                          disablePortal
                          options={getOptionsForController(pond.ControllerType.CONTROLLER_TYPE_HEATER)}
                          fullWidth
                          getOptionLabel={option => option.label || ""}
                          onChange={(_, newValue) => {
                            if (newValue) {
                              let presetId = newValue.id;
                              if (presets && presets[presetId]) {
                                //setSelectedPreset(presets[presetId]);
                                let set = cloneDeep(currentSet)
                                set.selectedPresets.set(heater.key(), presets[presetId])
                                set.combo = comboCheck(set)
                                setCurrentSet(set)
                                updateSet(sensor.key(), set)
                              }
                            }
                          }}
                          renderInput={params => <TextField {...params} variant="outlined" label="Preset" />}
                        />
                      }
                    </Grid2>
                  </Grid2>
                ))}
              </React.Fragment>
            }
            {fans && fans.length > 0 && 
              <React.Fragment>
                <Typography>Fans</Typography>
                {fans.map(fan => (
                  <Grid2 key={fan.key()} container justifyContent="space-between" direction="row" alignContent="center" alignItems="center">
                    <Grid2 size={{xs: 12, sm: 6}}>
                      <FormControlLabel 
                        control={
                          <Checkbox 
                            onChange={(_, checked) => {
                              let set = cloneDeep(currentSet)
                              if(checked){//if checked need to add it to the controllers
                                set.controllers.push(fan)  
                              }else{//will need to make sure it is not in the controllers
                                let index = controllerIndex(fan.key())
                                if (index !== -1){
                                  set.controllers.splice(index, 1)
                                }
                              }
                              set.combo = comboCheck(set)
                              setCurrentSet(set)
                              updateSet(sensor.key(), set)
                            }}
                          />
                        }
                        label={fan.name()}
                      />
                    </Grid2>
                    <Grid2 size={{xs: 12, sm: 6}}>
                    {presets && getOptionsForController(pond.ControllerType.CONTROLLER_TYPE_FAN).length > 0 &&
                      <Autocomplete
                        disablePortal
                        options={getOptionsForController(pond.ControllerType.CONTROLLER_TYPE_FAN)}
                        fullWidth
                        getOptionLabel={option => option.label || ""}
                        onChange={(_, newValue) => {
                          if (newValue) {
                            let presetId = newValue.id;
                            if (presets && presets[presetId]) {
                              //setSelectedPreset(presets[presetId]);
                              let set = cloneDeep(currentSet)
                              set.selectedPresets.set(fan.key(), presets[presetId])
                              set.combo = comboCheck(set)
                              setCurrentSet(set)
                              updateSet(sensor.key(), set)
                            }
                          }
                        }}
                        renderInput={params => <TextField {...params} variant="outlined" label="Preset" />}
                      />
                    }
                    </Grid2>
                  </Grid2>
                ))}
              </React.Fragment>
            }
          </AccordionDetails>
        </Accordion>
      }
    </Box>
  )
}