import {
  Avatar,
  Box,
  darken,
  Divider,
  Grid2 as Grid,
  IconButton,
  List,
  ListItem,
  ListItemAvatar,
  ListItemSecondaryAction,
  ListItemText,
  ListSubheader,
  Menu,
  MenuItem,
  Theme,
  Typography,
  useTheme
} from "@mui/material";
import { Component } from "models";
import { GetComponentIcon } from "pbHelpers/ComponentType";
import { pond, quack } from "protobuf-ts/pond";
import { useBinAPI, useSnackbar, useGlobalState } from "providers";
import React, { useState, useEffect, useCallback } from "react";
import { getThemeType } from "theme";
import { Plenum } from "models/Plenum";
import { Controller } from "models/Controller";
import { GrainCable } from "models/GrainCable";
import { Pressure } from "models/Pressure";
import { Headspace } from "models/Headspace";
import { MoreVert } from "@mui/icons-material";
import { describeMeasurement } from "pbHelpers/MeasurementDescriber";
import { Ambient } from "models/Ambient";
import { makeStyles } from "@mui/styles";
import { CO2 } from "models/CO2";

const useStyles = makeStyles((theme: Theme) => {
  return ({
    bgItem: {
      background: darken(theme.palette.background.paper, getThemeType() === "light" ? 0.05 : 0.25),
      position: "relative",
      width: "auto",
      borderRadius: theme.spacing(0.5),
      display: "flex",
      flexDirection: "column",
      padding: theme.spacing(0.5)
    },
    avatar: {
      width: theme.spacing(3),
      height: theme.spacing(3),
      marginTop: "auto",
      marginBottom: "auto"
    },
    avatarIcon: {
      background: "transparent",
      width: theme.spacing(3),
      height: theme.spacing(3),
      margin: "auto",
      marginBottom: "auto"
    },
    spacingItem: {
      paddingLeft: theme.spacing(0.75),
      paddingRight: theme.spacing(1),
      display: "flex",
      flexDirection: "row",
      justifyContent: "center"
    },
    pointerLeft: {
      borderBottom: "1px solid",
      borderLeft: "1px solid",
      borderColor: theme.palette.text.primary,
      width: theme.spacing(5.5),
      height: theme.spacing(0.7)
    },
    pointerRight: {
      borderBottom: "1px solid white",
      borderLeft: "1px solid white",
      borderRight: "1px solid white",
      borderColor: theme.palette.text.primary,
      width: theme.spacing(5.5),
      height: theme.spacing(0.7)
    },
    spacer: {
      paddingLeft: theme.spacing(0.25)
    },
    smallFont: {
      fontSize: "10px"
    },
    bigSpacer: {
      paddingLeft: theme.spacing(3.2)
    }
  });
});

interface Props {
  bin: string;
  components: Map<string, Component>;
  preferences: Map<string, pond.BinComponentPreferences>;
  setPreferences: React.Dispatch<
    React.SetStateAction<Map<string, pond.BinComponentPreferences> | undefined>
  >;
  updateBinStatus: (componentKeys: string[], removed?: boolean) => void;
  setComponents: React.Dispatch<React.SetStateAction<Map<string, Component>>>;
}

export default function BinComponentTypes(props: Props) {
  const { bin, components, preferences, setPreferences, updateBinStatus } = props;
  const classes = useStyles();
  const theme = useTheme();
  const binAPI = useBinAPI();
  const snackbar = useSnackbar();
  const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
  //only used to determine what preferences are options for the selected component ie. DHT can be a plenum or a headspace
  const [selectedComponentType, setSelectedComponentType] = useState<
    quack.ComponentType | undefined
  >(undefined);
  const [componentUnassigned, setComponentUnnassigned] = useState(false);
  const [unassigned, setUnassigned] = useState<Component[]>([]);
  const [plenums, setPlenums] = useState<Plenum[]>([]);
  const [ambients, setAmbients] = useState<Ambient[]>([]);
  const [pressures, setPressures] = useState<Pressure[]>([]);
  const [grainCables, setGrainCables] = useState<GrainCable[]>([]);
  const [headspace, setHeadspace] = useState<Headspace[]>([]);
  const [heaters, setHeaters] = useState<Controller[]>([]);
  const [fans, setFans] = useState<Controller[]>([]);
  const [lidars, setLidars] = useState<Component[]>([]);
  const [headspaceCo2s, setHeadspaceCo2s] = useState<CO2[]>([]);
  const [tempUnit, setTempUnit] = useState<pond.TemperatureUnit>();
  const [pressureUnit, setPressureUnit] = useState<pond.PressureUnit>();
  const [selectedComponentKey, setSelectedComponentKey] = useState("");
  const [selectedComponentSubtype, setSelectedComponentSubtype] = useState(0);
  const [selectedComponentTopNode, setSelectedComponentTopNode] = useState(0);
  const [{ user, as }] = useGlobalState();

  useEffect(() => {
    if (user.settings.temperatureUnit) {
      setTempUnit(user.settings.temperatureUnit);
    } else {
      setTempUnit(pond.TemperatureUnit.TEMPERATURE_UNIT_CELSIUS);
    }
    if (user.settings.pressureUnit) {
      setPressureUnit(user.settings.pressureUnit);
    } else {
      setPressureUnit(pond.PressureUnit.PRESSURE_UNIT_INCHES_OF_WATER);
    }
  }, [user]);

  const selectType = useCallback(
    (component: string, type: pond.BinComponent, topNode?: number) => {
      setAnchorEl(null);
      let p = preferences.get(component);
      if (p) {
        p.type = type;
        p.node = topNode ?? 0;
        binAPI
          .updateComponentPreferences(bin, component, p, as)
          .then(() => {
            snackbar.success("Component preferences updated");
            preferences.set(component, p!);
            setPreferences(new Map(preferences));
          })
          .catch(() => {
            snackbar.error("Component preference update failed");
          });
      }
    },
    [bin, binAPI, preferences, setPreferences, snackbar, as]
  );

  useEffect(() => {
    var plenums: Plenum[] = [];
    var grainCables: GrainCable[] = [];
    var heaters: Controller[] = [];
    var fans: Controller[] = [];
    var pressures: Pressure[] = [];
    var headspace: Headspace[] = [];
    var lidar: Component[] = [];
    var unassigned: Component[] = [];
    var ambients: Ambient[] = [];
    var headspaceCo2s: CO2[] = [];
    components.forEach(comp => {
      let pref = preferences.get(comp.key());
      if (pref) {
        if (pref.type) {
          if (pref.type === pond.BinComponent.BIN_COMPONENT_PLENUM)
            plenums.push(Plenum.create(comp));
          if (pref.type === pond.BinComponent.BIN_COMPONENT_AMBIENT)
            ambients.push(Ambient.create(comp));
          if (pref.type === pond.BinComponent.BIN_COMPONENT_GRAIN_CABLE)
            grainCables.push(GrainCable.create(comp));
          if (pref.type === pond.BinComponent.BIN_COMPONENT_HEATER)
            heaters.push(Controller.create(comp));
          if (pref.type === pond.BinComponent.BIN_COMPONENT_FAN) fans.push(Controller.create(comp));
          if (pref.type === pond.BinComponent.BIN_COMPONENT_PRESSURE)
            pressures.push(Pressure.create(comp));
          if (pref.type === pond.BinComponent.BIN_COMPONENT_HEADSPACE) {
            if (comp.type() === quack.ComponentType.COMPONENT_TYPE_DHT) {
              headspace.push(Headspace.create(comp));
            } else if (comp.type() === quack.ComponentType.COMPONENT_TYPE_LIDAR) {
              lidar.push(comp);
            } else if (comp.type() === quack.ComponentType.COMPONENT_TYPE_CO2) {
              let coComp = CO2.create(comp)
              headspaceCo2s.push(coComp);
            }
          }
        } else {
          unassigned.push(comp);
        }
      } else {
        unassigned.push(comp);
      }
    });
    setPlenums(plenums);
    setAmbients(ambients);
    setGrainCables(grainCables);
    setHeaters(heaters);
    setFans(fans);
    setPressures(pressures);
    setHeadspace(headspace);
    setLidars(lidar);
    setHeadspaceCo2s(headspaceCo2s);
    setUnassigned(unassigned);
  }, [components, preferences, setPlenums, setGrainCables, setHeaters, selectType, setPressures]);

  const getOptions = () => {
    let options: JSX.Element[] = [];

    if (!componentUnassigned) {
      options.push(
        <MenuItem
          key="remove"
          onClick={() => {
            selectType(selectedComponentKey, pond.BinComponent.BIN_COMPONENT_UNKNOWN);
            updateBinStatus([selectedComponentKey], true);
          }}>
          Remove
        </MenuItem>
      );
    }
    if (
      selectedComponentType === quack.ComponentType.COMPONENT_TYPE_DHT ||
      selectedComponentType === quack.ComponentType.COMPONENT_TYPE_GRAIN_CABLE
    ) {
      options.push(
        <MenuItem
          key="ambientOption"
          onClick={() => {
            selectType(selectedComponentKey, pond.BinComponent.BIN_COMPONENT_AMBIENT);
          }}>
          Ambient
        </MenuItem>
      );
      options.push(
        <MenuItem
          key="plenumOption"
          onClick={() => {
            selectType(selectedComponentKey, pond.BinComponent.BIN_COMPONENT_PLENUM);
          }}>
          Plenum
        </MenuItem>
      );
    }
    if (
      selectedComponentType === quack.ComponentType.COMPONENT_TYPE_DHT ||
      selectedComponentType === quack.ComponentType.COMPONENT_TYPE_LIDAR ||
      selectedComponentType === quack.ComponentType.COMPONENT_TYPE_CO2
    ) {
      options.push(
        <MenuItem
          key="headspaceOption"
          onClick={() => {
            selectType(selectedComponentKey, pond.BinComponent.BIN_COMPONENT_HEADSPACE);
            updateBinStatus([selectedComponentKey]);
          }}>
          Headspace
        </MenuItem>
      );
    }
    if (
      selectedComponentType === quack.ComponentType.COMPONENT_TYPE_PRESSURE ||
      selectedComponentType === quack.ComponentType.COMPONENT_TYPE_PRESSURE_CABLE
    ) {
      options.push(
        <MenuItem
          key="pressureOption"
          onClick={() => {
            selectType(selectedComponentKey, pond.BinComponent.BIN_COMPONENT_PRESSURE);
          }}>
          Plenum Pressure
        </MenuItem>
      );
    }
    if (selectedComponentType === quack.ComponentType.COMPONENT_TYPE_GRAIN_CABLE) {
      options.push(
        <MenuItem
          key="cableOption"
          onClick={() => {
            selectType(
              selectedComponentKey,
              pond.BinComponent.BIN_COMPONENT_GRAIN_CABLE,
              selectedComponentTopNode
            );
          }}>
          Grain Cable
        </MenuItem>
      );
    }
    if (selectedComponentType === quack.ComponentType.COMPONENT_TYPE_BOOLEAN_OUTPUT) {
      options.push(
        <MenuItem
          key="controlOption"
          onClick={() => {
            if (
              selectedComponentSubtype === quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_HEATER
            ) {
              selectType(selectedComponentKey, pond.BinComponent.BIN_COMPONENT_HEATER);
            } else if (
              selectedComponentSubtype ===
              quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_AERATION_FAN
            ) {
              selectType(selectedComponentKey, pond.BinComponent.BIN_COMPONENT_FAN);
            }
          }}>
          Heaters & Fans
        </MenuItem>
      );
    }

    if (options.length === 0) {
      return <MenuItem>No Available Options</MenuItem>;
    } else {
      return options;
    }
  };

  const assignmentMenu = () => {
    return (
      <Menu
        id="groupMenu"
        anchorEl={anchorEl}
        open={Boolean(anchorEl)}
        onClose={() => setAnchorEl(null)}
        keepMounted
        disableAutoFocusItem>
        {getOptions()}
      </Menu>
    );
  };

  const grainCableList = () => {
    if (grainCables.length < 1) return null;
    return (
      <React.Fragment>
        <ListSubheader component="div" disableGutters>
          Grain Cables
        </ListSubheader>
        <Divider />
        {grainCables.map((cable, index) => {
          let cIcon = GetComponentIcon(
            cable.settings.type,
            cable.settings.subtype,
            theme.palette.mode
          );
          return (
            <ListItem key={index} style={{ height: theme.spacing(8) }}>
              <ListItemAvatar>
                <Avatar
                  variant="square"
                  src={cIcon}
                  alt={cable.name()}
                  style={{ width: theme.spacing(3), height: theme.spacing(3) }}
                />
              </ListItemAvatar>
              <ListItemText inset={cIcon === undefined}>{cable.name()}</ListItemText>
              <ListItemSecondaryAction>
                <Grid container direction="row" alignItems="center">
                  <Grid>
                    <Box className={classes.bgItem}>
                      <Box style={{ display: "flex", flexDirection: "row" }}>
                        <Box>
                          <Typography variant="body2" color="textSecondary">
                            {tempUnit === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT
                              ? "°F"
                              : "°C"}
                          </Typography>
                        </Box>
                        <Box display={"flex"} alignItems="center" textAlign="center">
                          <Typography
                            variant="body2"
                            style={{ color: cable.tempColour(), marginLeft: theme.spacing(1.5) }}>
                            {isFinite(cable.minTemp(tempUnit)) && !isNaN(cable.minTemp(tempUnit))
                              ? cable.minTemp(tempUnit).toFixed(1)
                              : "--"}
                          </Typography>
                          <Typography
                            variant="body2"
                            style={{ color: cable.tempColour(), marginLeft: theme.spacing(1.5) }}>
                            {isFinite(cable.aveTemp(tempUnit)) && !isNaN(cable.aveTemp(tempUnit))
                              ? cable.aveTemp(tempUnit).toFixed(1)
                              : "--"}
                          </Typography>
                          <Typography
                            variant="body2"
                            style={{ color: cable.tempColour(), marginLeft: theme.spacing(1.5) }}>
                            {isFinite(cable.maxTemp(tempUnit)) && !isNaN(cable.maxTemp(tempUnit))
                              ? cable.maxTemp(tempUnit).toFixed(1)
                              : "--"}
                          </Typography>
                        </Box>
                      </Box>
                      <Box marginY={0.25}>
                        <Divider style={{ background: "gold" }} />
                      </Box>
                      <Box style={{ display: "flex", flexDirection: "row" }}>
                        <Box>
                          <Typography
                            variant="body2"
                            color="textSecondary"
                            style={{ marginLeft: theme.spacing(0.4) }}>
                            %
                          </Typography>
                        </Box>
                        <Box display={"flex"} alignItems="center" textAlign="center">
                          <Typography
                            variant="body2"
                            style={{ color: cable.humidColour(), marginLeft: theme.spacing(1.5) }}>
                            {isFinite(cable.minHumidity()) && !isNaN(cable.minHumidity())
                              ? cable.minHumidity().toFixed(1)
                              : "--"}
                          </Typography>
                          <Typography
                            variant="body2"
                            style={{ color: cable.humidColour(), marginLeft: theme.spacing(1.5) }}>
                            {isFinite(cable.aveHumidity()) && !isNaN(cable.aveHumidity())
                              ? cable.aveHumidity().toFixed(1)
                              : "--"}
                          </Typography>
                          <Typography
                            variant="body2"
                            style={{ color: cable.humidColour(), marginLeft: theme.spacing(1.5) }}>
                            {isFinite(cable.maxHumidity()) && !isNaN(cable.maxHumidity())
                              ? cable.maxHumidity().toFixed(1)
                              : "--"}
                          </Typography>
                        </Box>
                      </Box>
                    </Box>
                  </Grid>
                  <Grid >
                    <IconButton
                      onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
                        setComponentUnnassigned(false);
                        setSelectedComponentType(cable.type());
                        setSelectedComponentKey(cable.key());
                        setSelectedComponentTopNode(cable.settings.grainFilledTo);
                        setAnchorEl(event.currentTarget);
                      }}>
                      <MoreVert />
                    </IconButton>
                  </Grid>
                </Grid>
              </ListItemSecondaryAction>
            </ListItem>
          );
        })}
      </React.Fragment>
    );
  };

  const controllerList = (heaters: Controller[], fans: Controller[]) => {
    if (heaters.length < 1 && fans.length < 1) return null;
    let controllers = heaters.concat(fans);
    return (
      <React.Fragment>
        <ListSubheader component="div" disableGutters>
          Heaters & Fans
        </ListSubheader>
        <Divider />
        {controllers.map((controller, index) => {
          let cIcon = GetComponentIcon(
            controller.settings.type,
            controller.settings.subtype,
            theme.palette.mode
          );
          return (
            <ListItem key={index}>
              <ListItemAvatar>
                <Avatar
                  variant="square"
                  src={cIcon}
                  alt={controller.name()}
                  style={{ width: theme.spacing(3), height: theme.spacing(3) }}
                />
              </ListItemAvatar>
              <ListItemText inset={cIcon === undefined}>{controller.name()}</ListItemText>
              <ListItemSecondaryAction>
                <Grid container direction="row" alignItems="center">
                  <Grid >
                    <Box className={classes.bgItem} padding={1}>
                      <div style={{ display: "flex", flexDirection: "row", margin: "auto" }}>
                        <Typography variant="body2" style={{ color: controller.color() }}>
                          {controller.on ? "On" : "Off"}
                        </Typography>
                      </div>
                    </Box>
                  </Grid>
                  <Grid >
                    <IconButton
                      onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
                        setComponentUnnassigned(false);
                        setSelectedComponentType(controller.type());
                        setSelectedComponentSubtype(controller.subType());
                        setSelectedComponentKey(controller.key());
                        setAnchorEl(event.currentTarget);
                      }}>
                      <MoreVert />
                    </IconButton>
                  </Grid>
                </Grid>
              </ListItemSecondaryAction>
            </ListItem>
          );
        })}
      </React.Fragment>
    );
  };

  const pressureList = () => {
    if (pressures.length < 1) return null;
    return (
      <React.Fragment>
        <ListSubheader component="div" disableGutters>
          Plenum Pressure
        </ListSubheader>
        <Divider />
        {pressures.map((component, index) => {
          let cIcon = GetComponentIcon(
            component.settings.type,
            component.settings.subtype,
            theme.palette.mode
          );
          return (
            <ListItem key={index}>
              <ListItemAvatar>
                <Avatar
                  variant="square"
                  src={cIcon}
                  alt={component.name()}
                  style={{ width: theme.spacing(3), height: theme.spacing(3) }}
                />
              </ListItemAvatar>
              <ListItemText inset={cIcon === undefined}>{component.name()}</ListItemText>
              <ListItemSecondaryAction>
                <Grid container direction="row" alignItems="center">
                  <Grid>
                    <Box className={classes.bgItem} padding={1}>
                      <div style={{ display: "flex", flexDirection: "row", margin: "auto" }}>
                        <Typography variant="body2" style={{ color: Pressure.colour() }}>
                          {component.getPressureString(pressureUnit)}
                        </Typography>
                      </div>
                    </Box>
                  </Grid>
                  <Grid>
                    <IconButton
                      onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
                        setComponentUnnassigned(false);
                        setSelectedComponentType(component.type());
                        setSelectedComponentKey(component.key());
                        setAnchorEl(event.currentTarget);
                      }}>
                      <MoreVert />
                    </IconButton>
                  </Grid>
                </Grid>
              </ListItemSecondaryAction>
            </ListItem>
          );
        })}
      </React.Fragment>
    );
  };

  const plenumList = (plenums: Plenum[]) => {
    if (plenums.length < 1) return null;
    return (
      <React.Fragment>
        <ListSubheader component="div" disableGutters>
          Plenums
        </ListSubheader>
        <Divider />
        {plenums.map((component, index) => {
          let cIcon = GetComponentIcon(
            component.settings.type,
            component.settings.subtype,
            theme.palette.mode
          );
          return (
            <ListItem key={index}>
              <ListItemAvatar>
                <Avatar
                  variant="square"
                  src={cIcon}
                  alt={component.name()}
                  style={{ width: theme.spacing(3), height: theme.spacing(3) }}
                />
              </ListItemAvatar>
              <ListItemText inset={cIcon === undefined}>{component.name()}</ListItemText>
              <ListItemSecondaryAction>
                <Grid container direction="row" alignItems="center">
                  <Grid>
                    <Box className={classes.bgItem} padding={1}>
                      <div style={{ display: "flex", flexDirection: "row" }}>
                        <Typography variant="body2" style={{ color: Plenum.tempColour() }}>
                          {component.getTempString(user.settings.temperatureUnit) + ","}
                        </Typography>
                        <Typography
                          variant="body2"
                          style={{
                            color: Plenum.humidColour(),
                            marginLeft: theme.spacing(1)
                          }}>
                          {component.getHumidityString()}
                        </Typography>
                      </div>
                    </Box>
                  </Grid>
                  <Grid>
                    <IconButton
                      onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
                        setComponentUnnassigned(false);
                        setSelectedComponentType(component.type());
                        setSelectedComponentKey(component.key());
                        setAnchorEl(event.currentTarget);
                      }}>
                      <MoreVert />
                    </IconButton>
                  </Grid>
                </Grid>
              </ListItemSecondaryAction>
            </ListItem>
          );
        })}
      </React.Fragment>
    );
  };

  const ambientList = (ambients: Ambient[]) => {
    if (ambients.length < 1) return null;
    return (
      <React.Fragment>
        <ListSubheader component="div" disableGutters>
          Ambient
        </ListSubheader>
        <Divider />
        {ambients.map((component, index) => {
          let cIcon = GetComponentIcon(
            component.settings.type,
            component.settings.subtype,
            theme.palette.mode
          );
          return (
            <ListItem key={index}>
              <ListItemAvatar>
                <Avatar
                  variant="square"
                  src={cIcon}
                  alt={component.name()}
                  style={{ width: theme.spacing(3), height: theme.spacing(3) }}
                />
              </ListItemAvatar>
              <ListItemText inset={cIcon === undefined}>{component.name()}</ListItemText>
              <ListItemSecondaryAction>
                <Grid container direction="row" alignItems="center">
                  <Grid>
                    <Box className={classes.bgItem} padding={1}>
                      <div style={{ display: "flex", flexDirection: "row" }}>
                        <Typography variant="body2" style={{ color: Ambient.tempColour() }}>
                          {component.getTempString(user.settings.temperatureUnit) + ","}
                        </Typography>
                        <Typography
                          variant="body2"
                          style={{
                            color: Ambient.humidColour(),
                            marginLeft: theme.spacing(1)
                          }}>
                          {component.getHumidityString()}
                        </Typography>
                      </div>
                    </Box>
                  </Grid>
                  <Grid>
                    <IconButton
                      onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
                        setComponentUnnassigned(false);
                        setSelectedComponentType(component.type());
                        setSelectedComponentKey(component.key());
                        setAnchorEl(event.currentTarget);
                      }}>
                      <MoreVert />
                    </IconButton>
                  </Grid>
                </Grid>
              </ListItemSecondaryAction>
            </ListItem>
          );
        })}
      </React.Fragment>
    );
  };

  const formatDistance = (distanceCM: number) => {
    if (user.settings.distanceUnit === pond.DistanceUnit.DISTANCE_UNIT_METERS) {
      return distanceCM / 100 + "m";
    } else if (user.settings.distanceUnit === pond.DistanceUnit.DISTANCE_UNIT_FEET) {
      return (distanceCM / 30.48).toFixed(2) + "ft";
    }
    return distanceCM + "cm";
  };

  const headspaceList = (sensors: Headspace[], lidars: Component[], headspaceCo2s: CO2[]) => {
    if (sensors.length < 1 && lidars.length < 1 && headspaceCo2s.length < 1) return null;
    return (
      <React.Fragment>
        <ListSubheader component="div" disableGutters>
          Headspace
        </ListSubheader>
        <Divider />
        {sensors.map((component, index) => {
          let cIcon = GetComponentIcon(
            component.settings.type,
            component.settings.subtype,
            theme.palette.mode
          );
          return (
            <ListItem key={index}>
              <ListItemAvatar>
                <Avatar
                  variant="square"
                  src={cIcon}
                  alt={component.name()}
                  style={{ width: theme.spacing(3), height: theme.spacing(3) }}
                />
              </ListItemAvatar>
              <ListItemText inset={cIcon === undefined}>{component.name()}</ListItemText>

              <ListItemSecondaryAction>
                <Grid container direction="row" alignItems="center">
                  <Grid >
                    <Box className={classes.bgItem} padding={1}>
                      <div style={{ display: "flex", flexDirection: "row" }}>
                        <Typography variant="body2" style={{ color: Plenum.tempColour() }}>
                          {component.getTempString(user.settings.temperatureUnit) + ","}
                        </Typography>
                        <Typography
                          variant="body2"
                          style={{
                            color: Plenum.humidColour(),
                            marginLeft: theme.spacing(1)
                          }}>
                          {component.getHumidityString()}
                        </Typography>
                      </div>
                    </Box>
                  </Grid>
                  <Grid >
                    <IconButton
                      onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
                        setComponentUnnassigned(false);
                        setSelectedComponentType(component.type());
                        setSelectedComponentKey(component.key());
                        setAnchorEl(event.currentTarget);
                      }}>
                      <MoreVert />
                    </IconButton>
                  </Grid>
                </Grid>
              </ListItemSecondaryAction>
            </ListItem>
          );
        })}
        {headspaceCo2s.map((co2, index) => {
          let cIcon = GetComponentIcon(
            co2.settings.type,
            co2.settings.subtype,
            theme.palette.mode
          );

          let colour = "white"; //default colour if there are no measurements to get the type from

          let ppmString = "--";
          if (
            co2.status.measurement[0] &&
            co2.status.measurement[0].values[0] &&
            co2.status.measurement[0].values[0].values[0]
          ) {
            colour = describeMeasurement(
              co2.status.measurement[0].type,
              co2.type(),
              co2.subType()
            ).colour();
            ppmString = co2.status.measurement[0].values[0].values[0] + " ppm";
          }
          return (
            <ListItem key={index}>
              <ListItemAvatar>
                <Avatar
                  variant="square"
                  src={cIcon}
                  alt={co2.name()}
                  style={{ width: theme.spacing(3), height: theme.spacing(3) }}
                />
              </ListItemAvatar>
              <ListItemText inset={cIcon === undefined}>{co2.name()}</ListItemText>

              <ListItemSecondaryAction>
                <Grid container direction="row" alignItems="center">
                  <Grid >
                    <Box className={classes.bgItem} padding={1}>
                      <div style={{ display: "flex", flexDirection: "row" }}>
                        <Typography
                          variant="body2"
                          style={{
                            color: colour
                          }}>
                          {ppmString}
                        </Typography>
                      </div>
                    </Box>
                  </Grid>
                  <Grid >
                    <IconButton
                      onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
                        setComponentUnnassigned(false);
                        setSelectedComponentType(co2.type());
                        setSelectedComponentKey(co2.key());
                        setAnchorEl(event.currentTarget);
                      }}>
                      <MoreVert />
                    </IconButton>
                  </Grid>
                </Grid>
              </ListItemSecondaryAction>
            </ListItem>
          );
        })
        }
        {lidars.map((component, index) => {
          let cIcon = GetComponentIcon(
            component.settings.type,
            component.settings.subtype,
            theme.palette.mode
          );

          let colour = "white"; //default colour if there are no measurements to get the type from

          let dString = "--";
          if (
            component.status.measurement[0] &&
            component.status.measurement[0].values[0] &&
            component.status.measurement[0].values[0].values[0]
          ) {
            colour = describeMeasurement(
              component.status.measurement[0].type,
              component.type(),
              component.subType()
            ).colour();
            dString = formatDistance(component.status.measurement[0].values[0].values[0]);
          }

          return (
            <ListItem key={index}>
              <ListItemAvatar>
                <Avatar
                  variant="square"
                  src={cIcon}
                  alt={component.name()}
                  style={{ width: theme.spacing(3), height: theme.spacing(3) }}
                />
              </ListItemAvatar>
              <ListItemText inset={cIcon === undefined}>{component.name()}</ListItemText>

              <ListItemSecondaryAction>
                <Grid container direction="row" alignItems="center">
                  <Grid >
                    <Box className={classes.bgItem} padding={1}>
                      <div style={{ display: "flex", flexDirection: "row" }}>
                        <Typography
                          variant="body2"
                          style={{
                            color: colour
                          }}>
                          {dString}
                        </Typography>
                      </div>
                    </Box>
                  </Grid>
                  <Grid >
                    <IconButton
                      onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
                        setComponentUnnassigned(false);
                        setSelectedComponentType(component.type());
                        setSelectedComponentKey(component.key());
                        setAnchorEl(event.currentTarget);
                      }}>
                      <MoreVert />
                    </IconButton>
                  </Grid>
                </Grid>
              </ListItemSecondaryAction>
            </ListItem>
          );
        })}
      </React.Fragment>
    );
  };

  const unassignedList = (sensors: Component[]) => {
    if (sensors.length < 1) return null;
    return (
      <React.Fragment>
        <ListSubheader component="div" disableGutters>
          Unassigned Components
        </ListSubheader>
        <Divider />
        {sensors.map((component, index) => {
          let cIcon = GetComponentIcon(
            component.settings.type,
            component.settings.subtype,
            theme.palette.mode
          );
          return (
            <ListItem key={index}>
              <ListItemAvatar>
                <Avatar
                  variant="square"
                  src={cIcon}
                  alt={component.name()}
                  style={{ width: theme.spacing(3), height: theme.spacing(3) }}
                />
              </ListItemAvatar>
              <ListItemText inset={cIcon === undefined}>{component.name()}</ListItemText>
              <ListItemSecondaryAction>
                <IconButton
                  onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
                    setComponentUnnassigned(true);
                    setSelectedComponentType(component.type());
                    setSelectedComponentSubtype(component.subType());
                    setSelectedComponentKey(component.key());
                    setAnchorEl(event.currentTarget);
                  }}>
                  <MoreVert />
                </IconButton>
              </ListItemSecondaryAction>
            </ListItem>
          );
        })}
      </React.Fragment>
    );
  };

  const noComponents = () => {
    return (
      <Box style={{ margin: "auto" }} textAlign="center">
        <Typography variant="subtitle1" color="textSecondary">
          No attached components.
        </Typography>
        <Typography variant="subtitle1" color="textSecondary">
          Go to settings to assign components from your devices.
        </Typography>
      </Box>
    );
  };

  if (components.size < 1) return noComponents();

  return (
    <React.Fragment>
      <List
        //subheader={<ListSubheader>Bin Components</ListSubheader>}
        style={{ padding: theme.spacing(1), width: "100%" }}>
        {plenumList(plenums)}
        {ambientList(ambients)}
        {headspaceList(headspace, lidars, headspaceCo2s)}
        {grainCableList()}
        {controllerList(heaters, fans)}
        {pressureList()}
        {unassignedList(unassigned)}
        {assignmentMenu()}
      </List>
    </React.Fragment>
  );
}
