import {
  Button,
  Card,
  CardContent,
  CardHeader,
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableRow,
  Theme,
  Typography
} from "@mui/material";
import { Component, Device } from "models";
import moment from "moment";
import { getHumanReadableAddress } from "pbHelpers/AddressType";
import { pond } from "protobuf-ts/pond";
import { quack } from "protobuf-ts/quack";
import { useComponentAPI, useGlobalState } from "providers";
import React, { useEffect, useState } from "react";
// import { getThemeType } from "theme";
import AddCompsFromDiag from "./AddCompsFromDiag";
import { getThemeType } from "theme/themeType";
import { makeStyles } from "@mui/styles";

interface Props {
  component: Component;
  device: Device;
  refreshCallback: () => void;
  //not worrying about permissions for this component as this would only be rendered if the user has write permissions to the device
  //permissions: pond.Permission[]
}

export interface CableInfo {
  id: number;
  subtype: quack.GrainCableSubtype | undefined;
  name: string;
  nodeCount: number;
}

const useStyles = makeStyles((theme: Theme) => {
  return ({
    cardHeader: {
      padding: theme.spacing(1),
      paddingLeft: theme.spacing(2)
    },
    cell: {
      padding: 5
    },
    dark: {
      backgroundColor: getThemeType() === "light" ? "rgb(245, 245, 245)" : "rgb(50, 50, 50)",
      padding: 0
    },
    light: {
      backgroundColor: getThemeType() === "light" ? "rgb(235, 235, 235)" : "rgb(60, 60, 60)",
      padding: 0
    }
  })
});

export default function ComponentDiagnostics(props: Props) {
  const { component, device, refreshCallback } = props;
  const [{as}] = useGlobalState();
  const [portNumber, setPortNumber] = useState("");
  const compAPI = useComponentAPI();
  const classes = useStyles();
  const [cableInfoList, setCableInfoList] = useState<CableInfo[]>([]);
  const [measurements, setMeasurements] = useState<pond.UnitMeasurementsForComponent[]>([]);
  //const { error, success } = useSnackbar();
  const [loadingMeasurements, setLoadingMeasurements] = useState(false);
  const [openAdd, setOpenAdd] = useState(false);

  useEffect(() => {
    setPortNumber(
      getHumanReadableAddress(
        component.settings.addressType,
        component.settings.type,
        component.settings.address,
        device.settings.product
      )
    );
    //get the last 10 measurements that occured over a 24 hour period
    if (!loadingMeasurements) {
      setLoadingMeasurements(true);
      compAPI
        .listUnitMeasurements(
          device.id(),
          component.key(),
          moment()
            .subtract(1, "hours")
            .toISOString(),
          moment().toISOString(),
          2,
          0,
          "desc",
          undefined,
          undefined,
          undefined,
          undefined,
          undefined,
          as
        )
        .then(resp => {
          setMeasurements(resp.data.measurements);
        })
        .finally(() => {
          setLoadingMeasurements(false);
        });
    }
  }, [component, device, compAPI, as]); //eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    let cableIDs: number[] = [];
    let cableInfo: CableInfo[] = [];

    if (measurements) {
      measurements.forEach(UnitMeasurement => {
        let unitM = pond.UnitMeasurementsForComponent.fromObject(UnitMeasurement);
        if (unitM.type === quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE) {
          if (unitM.values[0] && unitM.values[0].values) {
            cableIDs = unitM.values[0].values;
          }
        } else if (unitM.type === quack.MeasurementType.MEASUREMENT_TYPE_PERCENT) {
          unitM.values.forEach(ValArray => {
            ValArray.values.forEach((hum, i) => {
              if (cableIDs[i]) {
                let newInfo = cableFromHumidity(cableIDs[i], hum);
                if (cableInfo[i] === undefined) {
                  //for the first round just put them in
                  cableInfo.push(newInfo);
                } else {
                  //if something is there do a check to see if they match
                  if (cableInfo[i].subtype !== newInfo.subtype) {
                    //if they dont match determine if the newInfo has priority
                    if (
                      newInfo.subtype === quack.GrainCableSubtype.GRAIN_CABLE_SUBTYPE_NONE ||
                      newInfo.subtype === quack.GrainCableSubtype.GRAIN_CABLE_SUBTYPE_OPI_SHT35
                    ) {
                      //if it does then set the V# to be the cable info otherwise leave it alone
                      cableInfo[i] = newInfo;
                    }
                  }
                }
              }
            });
          });
        }
      });
    }
    setCableInfoList(cableInfo);
  }, [measurements]);

  const cableFromHumidity = (cableID: number, humidity: number) => {
    let nodeCoeff = 0;
    let cableInfo: CableInfo = { id: cableID, subtype: undefined, name: "Unknown", nodeCount: 0 };
    if (humidity >= 1 && humidity <= 16) {
      cableInfo.subtype = quack.GrainCableSubtype.GRAIN_CABLE_SUBTYPE_NONE;
      cableInfo.name = "Moisture Cable";
      nodeCoeff = 0;
    } else if (humidity >= 17 && humidity <= 32) {
      cableInfo.subtype = quack.GrainCableSubtype.GRAIN_CABLE_SUBTYPE_FROG;
      cableInfo.name = "Adaptive Sensor";
      nodeCoeff = 1;
    } else if (humidity >= 33 && humidity <= 48) {
      cableInfo.subtype = quack.GrainCableSubtype.GRAIN_CABLE_SUBTYPE_OPI_TEMP;
      cableInfo.name = "Temp Only Cable";
      nodeCoeff = 2;
    } else if (humidity >= 49) {
      cableInfo.subtype = quack.GrainCableSubtype.GRAIN_CABLE_SUBTYPE_OPI_SHT35;
      cableInfo.name = "Moisture Cable V2";
      nodeCoeff = 3;
    }
    cableInfo.nodeCount = humidity - 16 * nodeCoeff;
    return cableInfo;
  };

  // deprecated: this functionality has moved to the AddCompsFromDiag component
  // const addCablesToDevice = () => {
  //   let componentsToAdd: pond.MultiComponentSettings = pond.MultiComponentSettings.create();
  //   cableInfoList.forEach(cable => {
  //     let settings: pond.ComponentSettings = pond.ComponentSettings.create();
  //     settings.type = quack.ComponentType.COMPONENT_TYPE_GRAIN_CABLE;
  //     settings.subtype = cable.subtype ?? quack.GrainCableSubtype.GRAIN_CABLE_SUBTYPE_NONE;
  //     settings.addressType = cable.id + 8;
  //     settings.address = component.settings.address;
  //     settings.measurementPeriodMs = 3600000; //set the measurement period to 1 hour
  //     settings.reportPeriodMs = 3600000;
  //     settings.name = cable.name;
  //     componentsToAdd.components.push(settings);
  //   });
  //   compAPI
  //     .addMultiComponents(device.id(), componentsToAdd)
  //     .then(resp => {
  //       success("Components added to Device");
  //     })
  //     .catch(err => {
  //       error("One or more component failed to add");
  //     })
  //     .finally(() => {
  //       refreshCallback();
  //     });
  // };

  return (
    <React.Fragment>
      <Card raised>
        <CardHeader
          title={<Typography variant="body1">Port {portNumber} Auto Detection</Typography>}
          className={classes.cardHeader}
        />
        <CardContent style={{ paddingTop: 0 }}>
          {measurements && measurements.length > 0 && (
            <React.Fragment>
              <Table>
                <TableHead>
                  <TableRow>
                    <TableCell align="center" className={classes.cell}>
                      Cable ID
                    </TableCell>
                    <TableCell align="center" className={classes.cell}>
                      Cable Type
                    </TableCell>
                    <TableCell align="center" className={classes.cell}>
                      Nodes
                    </TableCell>
                  </TableRow>
                </TableHead>
                <TableBody>
                  {cableInfoList.map((cable, i) => (
                    <TableRow className={i % 2 === 0 ? classes.light : classes.dark} key={i}>
                      <TableCell align="center" className={classes.cell}>
                        {cable.id}
                      </TableCell>
                      <TableCell align="center" className={classes.cell}>
                        {cable.name}
                      </TableCell>
                      <TableCell align="center" className={classes.cell}>
                        {cable.nodeCount}
                      </TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
              {cableInfoList.length > 0 && (
                <Button
                  style={{ marginTop: 20 }}
                  variant="contained"
                  color="primary"
                  onClick={() => {
                    //addCablesToDevice();
                    setOpenAdd(true);
                  }}>
                  Add to Device
                </Button>
              )}
            </React.Fragment>
          )}
        </CardContent>
      </Card>
      <AddCompsFromDiag
        cableInfo={cableInfoList}
        port={portNumber}
        device={device}
        diagComponent={component}
        open={openAdd}
        closeDialog={() => {
          setOpenAdd(false);
        }}
        refreshCallback={refreshCallback}
      />
    </React.Fragment>
  );
}
