import {
  Box,
  Button,
  Card,
  Grid2 as Grid,
  MenuItem,
  Select,
  ToggleButton,
  ToggleButtonGroup,
  Typography
} from "@mui/material";
import { Component, Device } from "models";
import { Gate } from "models/Gate";
import { pond } from "protobuf-ts/pond";
import { useGlobalState, useGateAPI } from "providers";
import { useEffect, useState } from "react";
import { useMobile, useSnackbar } from "hooks";
import { UnitMeasurement } from "models/UnitMeasurement";
import { quack } from "protobuf-ts/quack";
import GateDeviceInteraction from "./GateDeviceInteraction";
import GateSVG from "./GateSVG";
import GateGraphs from "./GateGraphs";
//import { ToggleButton, ToggleButtonGroup } from "@material-ui/lab";
import { getThemeType } from "theme";
import ButtonGroup from "common/ButtonGroup";
import { cloneDeep } from "lodash";

interface Props {
  gate: Gate;
  comprehensiveDevice: pond.ComprehensiveDevice;
  linkedCompList: Component[];
  drawerView?: boolean;
}



export default function GateDevice(props: Props) {
  const { gate, comprehensiveDevice, linkedCompList, drawerView } = props;
  const [{as}] = useGlobalState();
  const [device, setDevice] = useState<Device>(Device.create());
  const [componentOptions, setComponentOptions] = useState<Map<string, Component>>(
    new Map<string, Component>()
  );
  const gateAPI = useGateAPI();
  const [tempKey, setTempKey] = useState("");
  const [pressureKey, setPressureKey] = useState("");
  const [ambientKey, setAmbientKey] = useState("");
  const [greenLightKey, setGreenLightKey] = useState("");
  const [redLightKey, setRedLightKey] = useState("");
  const { openSnack } = useSnackbar();
  const [{ user }] = useGlobalState();
  const [interactionDialog, setInteractionDialog] = useState(false);
  const [densityTemp, setDensityTemp] = useState(0);
  const isMobile = useMobile();
  // const [pcaState, setPCAState] = useState(false);
  // const [pcaFanOn, setPCAFanOn] = useState(false);
  const [detail, setDetail] = useState<"sensors" | "analytics">("analytics");
  const [lastAmbient, setLastAmbient] = useState(0);
  //const [lastTemps, setLastTemps] = useState({ t1: 0, t2: 0 });
  const [ductTemp, setDuctTemp] = useState<number | undefined>()
  //const [lastPressures, setLastPressures] = useState({ p1: 0, p2: 0 });
  const [ductPressure, setDuctPressure] = useState<number | undefined>()


  useEffect(() => {
    //addresses of controller LEDs on a V1 device
    let redAddr = "3-1-512";
    let greenAddr = "3-1-1024";
    if (comprehensiveDevice.device) {
      setDevice(Device.any(comprehensiveDevice.device));

      //check if the device is a MiPCA V2 device since the lEDs will have different addresses
      let dev = Device.create(comprehensiveDevice.device);
      if (dev.settings.product === pond.DeviceProduct.DEVICE_PRODUCT_MIPCA_V2) {
        redAddr = "3-1-256";
        greenAddr = "3-1-512";
      }
    }
    if (comprehensiveDevice.components) {
      let components: Map<string, Component> = new Map<string, Component>();
      setAmbientKey("");
      setTempKey("");
      setPressureKey("");
      comprehensiveDevice.components.forEach(comp => {
        let c = Component.any(comp);
        if (linkedCompList.some(el => el.key() === c.key())) {
          components.set(c.key(), c);
          //determine the positioned components using the gates preferences for it components
          switch (gate.preferences[c.key()]) {
            case pond.GateComponentType.GATE_COMPONENT_TYPE_AMBIENT:
              setAmbientKey(c.key());
              c.status.measurement.forEach(um => {
                let measurement = UnitMeasurement.any(um, user);
                if (measurement.type === quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE) {
                  if (measurement.values.length > 1 && measurement.values[0].values.length > 0) {
                    setDensityTemp(measurement.values[0].values[0]);
                  }
                }
              });
              break;
            case pond.GateComponentType.GATE_COMPONENT_TYPE_TEMP:
              setTempKey(c.key());
              break;
            case pond.GateComponentType.GATE_COMPONENT_TYPE_PRESSURE:
              setPressureKey(c.key());
              // if (
              //   c.status.measurement[0] &&
              //   c.status.measurement[0].values[0] &&
              //   c.status.measurement[0].values[0].values[1]
              // ) {
              //   setPCAFanOn(c.status.measurement[0].values[0].values[1] > 996); //apx 4 iwg
              // }
              break;
            default:
              // type is unknown, do nothing
              break;
          }
        }
        if (c.locationString() === redAddr && c.subType() === 1) {
          setRedLightKey(c.key());
        } else if (c.locationString() === greenAddr && c.subType() === 1) {
          setGreenLightKey(c.key());
        }
      });
      setComponentOptions(components);
    }
  }, [comprehensiveDevice, gate, linkedCompList, user]);

  const gateComponentUpdate = (oldKey: string, componentKey: string, gateCompType: pond.GateComponentType) => {
    let promises: any[] = []
    if (oldKey !== "") {
      //the promise for removing the pref from the old component
      promises.push(gateAPI
        .updatePrefs(
          gate.key,
          "component",
          device.id() + ":" + oldKey,
          pond.GateComponentType.GATE_COMPONENT_TYPE_UNKNOWN,
          [gate.key],
          ["gate"],
          as
        ))
    }
    if (componentKey !== "") {
      //the promise for adding the pref to the new component
      promises.push(gateAPI
        .updatePrefs(
          gate.key,
          "component",
          device.id() + ":" + componentKey,
          gateCompType,
          [gate.key],
          ["gate"],
          as
        ))
    }
    Promise.all(promises).then(resp => {
        openSnack("Component Prefence Updated");
        let clone = cloneDeep(gate.preferences)
        clone[oldKey] = pond.GateComponentType.GATE_COMPONENT_TYPE_UNKNOWN
        clone[componentKey] = gateCompType
        gate.preferences = clone

      }).catch(
      );
  };

  useEffect(() => {
    let tempComponent = componentOptions.get(tempKey);
    if(tempComponent){
      tempComponent.status.measurement.forEach(um => {
        if(um.type === quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE){
          let clone = cloneDeep(um)
          let measurement = UnitMeasurement.any(clone, user)
          if(measurement.values.length > 0){
            let readings = measurement.values[measurement.values.length -1]
            if(readings.values.length > 0){
              setDuctTemp(readings.values[readings.values.length -1])
            }
          }
        }
      })
    }
  }, [componentOptions, tempKey, user]);

  useEffect(() => {
    let ambientComponent = componentOptions.get(ambientKey);
    let temp = 0;
    if (ambientComponent) {
      ambientComponent.status.measurement.forEach(um => {
        let measurement = UnitMeasurement.any(um, user);
        if (measurement.type === quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE) {
          if (measurement.values.length > 0 && measurement.values[0].values.length > 0) {
            temp = measurement.values[0].values[0];
          }
        }
      });
    }
    setLastAmbient(temp);
  }, [componentOptions, ambientKey, user]);

  useEffect(() => {
    let pressureComponent = componentOptions.get(pressureKey);
    if(pressureComponent){
      pressureComponent.status.measurement.forEach(um => {
        if(um.type === quack.MeasurementType.MEASUREMENT_TYPE_PRESSURE){
          let clone = cloneDeep(um)
          let measurement = UnitMeasurement.any(clone, user)
          if(measurement.values.length > 0){
            let readings = measurement.values[measurement.values.length -1]
            if(readings.values.length > 0){
              setDuctPressure(readings.values[readings.values.length -1])
            }
          }
        }
      })
    }
  }, [componentOptions, pressureKey, user]);

  const ambientSelector = () => {
    return (
      <Select
        id="ambientSelect"
        variant="standard"
        value={ambientKey}
        style={{ fontSize: 8 }}
        onChange={e => {
          var key = e.target.value as string;
          gateComponentUpdate(ambientKey, key, pond.GateComponentType.GATE_COMPONENT_TYPE_AMBIENT);
          setAmbientKey(key);
          if (tempKey === key) {
            setTempKey("");
          }
          if (pressureKey === key) {
            setPressureKey("");
          }
        }}
        displayEmpty>
        <MenuItem value="">
          <em>Select Ambient Sensor</em>
        </MenuItem>
        {Array.from(componentOptions.values()).map(c => {
          return (
            <MenuItem key={c.key()} value={c.key()}>
              {c.name()}
            </MenuItem>
          );
        })}
      </Select>
    );
  };

  const tempSelector = () => {
    return (
      <Select
        id="tempSelect"
        variant="standard"
        value={tempKey}
        style={{ fontSize: 8 }}
        onChange={e => {
          gateComponentUpdate(
            tempKey,
            e.target.value as string,
            pond.GateComponentType.GATE_COMPONENT_TYPE_TEMP
          );
          setTempKey(e.target.value as string);
          if (pressureKey === e.target.value) {
            setPressureKey("");
          }
          if (ambientKey === e.target.value) {
            setAmbientKey("");
          }
        }}
        displayEmpty>
        <MenuItem value="">
          <em>Select Temperature Chain</em>
        </MenuItem>
        {Array.from(componentOptions.values()).map(c => {
          return (
            <MenuItem key={c.key()} value={c.key()}>
              {c.name()}
            </MenuItem>
          );
        })}
      </Select>
    );
  };

  const pressureSelector = () => {
    return (
      <Select
        id="pressureSelect"
        variant="standard"
        value={pressureKey}
        style={{ fontSize: 8 }}
        onChange={e => {
          gateComponentUpdate(
            pressureKey,
            e.target.value as string,
            pond.GateComponentType.GATE_COMPONENT_TYPE_PRESSURE
          );
          setPressureKey(e.target.value as string);
          if (tempKey === e.target.value) {
            setTempKey("");
          }
          if (ambientKey === e.target.value) {
            setAmbientKey("");
          }
        }}
        displayEmpty>
        <MenuItem value="">
          <em>Select Pressure Chain</em>
        </MenuItem>
        {Array.from(componentOptions.values()).map(c => {
          return (
            <MenuItem key={c.key()} value={c.key()}>
              {c.name()}
            </MenuItem>
          );
        })}
      </Select>
    );
  };

  return (
    <Grid
      container
      // direction={(isMobile) ? "column" : "row"}
      width="100%"
      //alignItems="center"
      >
      <Grid width={"100%"} size={{ sm: 12, lg: isMobile || drawerView ? 12 : 4}} style={{ padding: 10 }}>
        <Box
          display="flex"
          justifyContent="space-between"
          alignItems="center"
          marginBottom={2}>
          <Typography style={{ fontWeight: 650, fontSize: 20 }}>{device.name()}</Typography>
          <ButtonGroup 
            toggle
            buttons={[
              {
                title: "Analysis",
                function: () => setDetail("analytics")
              },
              {
                title: "Sensors",
                function: () => setDetail("sensors")
              }
            ]}
          />
        </Box>
        <Card>
          <GateSVG
            finalTemp={
              gate.gateMutations[device.id().toString()] &&
              !isNaN(gate.gateMutations[device.id().toString()].temp)
                ? gate.gateMutations[device.id().toString()].temp
                : 0
            }
            ambientTemp={lastAmbient}
            //innerTemps={lastTemps}
            //innerPressures={lastPressures}
            ductTemp={ductTemp}
            ductPressure={ductPressure}
            ambientSelector={ambientSelector}
            tempChainSelector={tempSelector}
            pressureChainSelector={pressureSelector}
            pcaState={gate.status.pcaState}
            // pcaFanState={pcaFanOn}
            checkInTime={device.status.lastActive}
          />
          <Button
            variant="contained"
            color="primary"
            fullWidth
            onClick={() => {
              setInteractionDialog(true);
            }}>
            Set Interactions
          </Button>
        </Card>
        <GateDeviceInteraction
          open={interactionDialog}
          gate={gate}
          compDevice={comprehensiveDevice}
          densityTemp={densityTemp}
          close={canceled => {
            setInteractionDialog(false);
          }}
        />
      </Grid>
      <Grid size={{ sm: 12, lg: isMobile || drawerView ? 12 : 8}} style={{ padding: 10 }}>
        <GateGraphs
          gate={gate}
          display={detail}
          compMap={componentOptions}
          ambient={ambientKey}
          pressure={pressureKey}
          tempChain={tempKey}
          redKey={redLightKey}
          greenKey={greenLightKey}
          device={device.id()}
        />
      </Grid>
    </Grid>
  );
}
