import {
  Accordion,
  AccordionDetails,
  AccordionSummary,
  Box,
  Button,
  Checkbox,
  Chip,
  darken,
  DialogActions,
  DialogContent,
  DialogTitle,
  Divider,
  FormControl,
  FormControlLabel,
  Grid2 as Grid,
  IconButton,
  ImageList,
  ImageListItem,
  InputLabel,
  lighten,
  ListItemIcon,
  ListItemText,
  Menu,
  MenuItem,
  Select,
  Skeleton,
  Theme,
  ToggleButton,
  ToggleButtonGroup,
  Typography,
  useTheme,
} from "@mui/material";
import {
  ArrowBackIos,
  ArrowForwardIos,
  ExpandMore,
  LibraryAdd,
  MoreVert,
  ViewComfy,
  ViewList
} from "@mui/icons-material";
import BinsFansStatusTable from "bin/BinFansStatusTable";
// import BinSettings from "bin/BinSettings";
import BinsList from "bin/BinsList";
// import BinYard from "bin/BinYard";
import BinInventoryChart, { GrainAmount } from "charts/BinInventoryChart";
import BinUtilizationChart from "charts/BinUtilizationChart";
// import QrCodeGenerator, { QrCodeKey } from "common/QrCodeGenerator";
import GrainDescriber, { grainName } from "grain/GrainDescriber";
// import GrainBagList from "grainBag/grainBagList";
// import GrainBagSettings from "grainBag/grainBagSettings";
import { useMobile, useWidth } from "hooks";
import { Dictionary } from "lodash";
// import { Bin, Interaction, BinYard as BinYardModel } from "models";
import { Bin, Interaction, BinYard as BinYardModel } from "models";
// import { GrainBag } from "models/GrainBag";
import { pond, quack } from "protobuf-ts/pond";
import {
  useBinAPI,
  // useBinYardAPI,
  useGlobalState,
  useInteractionsAPI,
  useSnackbar
} from "providers";
import React, { SetStateAction, useCallback, useEffect, useState } from "react";
// import { getThemeType } from "theme";
import { getGrainUnit, stringToMaterialColour } from "utils";
//import InfiniteScroll from "react-infinite-scroller";
import PageContainer from "./PageContainer";
import ObjectTable from "objects/ObjectTable";
import ResponsiveDialog from "common/ResponsiveDialog";
import { describeMeasurement } from "pbHelpers/MeasurementDescriber";
import { green, yellow } from "@mui/material/colors";
import { makeStyles, styled } from "@mui/styles";
import { useNavigate } from "react-router-dom";
import BinSettings from "bin/BinSettings";
import AddBinFab from "bin/AddBinFab";
import { GrainBag } from "models/GrainBag";
import { getThemeType } from "theme/themeType";
import GrainBagSettings from "grainBag/grainBagSettings";
import GrainBagList from "grainBag/grainBagList";
import BinYards from "bin/BinYards";
// import { useHistory } from "react-router";

const useStyles = makeStyles((theme: Theme) => {
  const themeType = getThemeType();
  const accordionBg = themeType === "light" ? theme.palette.background.paper : darken(theme.palette.background.paper, 0.2)
  return ({
    "@keyframes pulsate": {
      to: {
        boxShadow: "0 0 0 16px" + yellow["500"] + "00"
      }
    },
    green: {
      color: green["500"],
      "&:hover": {
        color: green["600"]
      }
    },
    gridList: {
      width: "100%",
      flexWrap: "nowrap",
      transform: "translateZ(0)"
    },
    pulse: {
      boxShadow: "0 0 0 0 " + yellow["500"] + "75",
      animation: "$pulsate 1.75s infinite cubic-bezier(0.66, 0.33, 0, 1)"
    },
    icon: {
      padding: 6,
      width: 36,
      height: 36,
      borderRadius: "18px",
      background: "rgba(0,0,0,0)",
      "&:hover": {
        background:
          "radial-gradient(closest-side, rgba(150, 150, 150, 0.5) 50%, rgba(150, 150, 150, 0.5))"
      }
    },
    accordion: {
      background: accordionBg
    }
  });
});

interface PaginatedBins {
  bins: Bin[];
  binsOffset: number;
  binsTotal: number;
}

interface Props {
  yardFilter?: string;
  yards?: pond.BinYardSettings[];
  insert?: boolean;
}

export default function Bins(props: Props) {
  const classes = useStyles();
  const isMobile = useMobile();
  const binAPI = useBinAPI();
  // const binyardAPI = useBinYardAPI();
  const interactionsAPI = useInteractionsAPI();
  const [{ user, as }] = useGlobalState();
  const [allLoading, setAllLoading] = useState(false);
  const [binsLoading, setBinsLoading] = useState(false);
  const [addBinOpen, setAddBinOpen] = useState(false);
  const [paginatedBins, setPaginatedBins] = useState<PaginatedBins>({
    bins: [],
    binsOffset: 0,
    binsTotal: 0
  });
  const [binMetrics, setBinMetrics] = useState<pond.BinMetrics>();
  const [binMenuAnchorEl, setBinMenuAnchorEl] = useState<Element | null>(null);
  const [menuAnchorEl, setMenuAnchorEl] = useState<Element | null>(null);
  const [contentFilter, setContentFilter] = useState<string>("");
  const [yardFilter, setYardFilter] = useState<string>("");
  const [order, setOrder] = useState<"asc" | "desc">("asc");
  const [orderBy, setOrderBy] = useState<string>("name");
  const binsLimit = 40;
  const theme = useTheme();
  const width = useWidth();
  const [yards, setYards] = useState<pond.BinYardSettings[]>(props.yards ?? []);
  const [yardPermissions, setYardPermissions] = useState<Dictionary<pond.Permission[]>>({});
  const [loadingAs, setLoadingAs] = useState(as);
  const [loadingFilter, setLoadingFilter] = useState("init");
  const [displayGrain, setDisplayGrain] = useState(true);
  const [displayFert, setDisplayFert] = useState(false);
  const [displayEmpty, setDisplayEmpty] = useState(false);
  const [grainBins, setGrainBins] = useState<Bin[]>([]);
  const [fertilizerBins, setFertilizerBins] = useState<Bin[]>([]);
  const [emptyBins, setEmptyBins] = useState<Bin[]>([]);
  const [grainBags, setGrainBags] = useState<GrainBag[]>([]);
  const [displayedInventory, setDisplayedInventory] = useState<GrainAmount[]>([]);
  const [displayedFertilizer, setDisplayedFertilizer] = useState<GrainAmount[]>([]);
  const [carouselIndex, setCarouselIndex] = useState(0);
  const [addBagOpen, setAddBagOpen] = useState(false);
  const [showing, setShowing] = useState<"all" | "bins" | "bags">("all");
  //const [binGridView, setBinGridView] = useState(false);
  const [binView, setBinView] = useState<"grid" | "scroll" | "list">("grid");
  const [bagView, setBagView] = useState<"grid" | "scroll" | "list">("grid");
  const [expandTotal, setExpandTotal] = useState(false);
  const [expandUtilization, setExpandUtilization] = useState(false);
  const [expandFanTable, setExpandFanTable] = useState(false);
  const [openQrGenerator, setOpenQrGenerator] = useState(false);
  // const [qrKeyList, setQrKeyList] = useState<QrCodeKey[]>([]);
  const [totalFanControllers, setTotalFanControllers] = useState(0);
  const [totalFanControllersOn, setTotalFanControllersOn] = useState(0);
  const [yardsLoading, setYardsLoading] = useState(false);
  const [openAddAlerts, setOpenAddAlerts] = useState(false);
  const [alertBins, setAlertBins] = useState<Bin[]>([]);
  const { openSnack } = useSnackbar();
  // const history = useHistory();
  const navigate = useNavigate()
  const [cardValDisplay, setCardValDisplay] = useState<"high" | "low" | "average">("average");
  // const [scrollTranslations, setScrollTranslations] = useState({
  //   bins: 0,
  //   empty: 0,
  //   fertilizer: 0
  // });

  const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }: { theme: Theme }) => ({
    '& .MuiToggleButtonGroup-grouped': {
      // border: 'none' replaces the old 'grouped' border: "none"
      border: 'none',
      padding: theme.spacing(1),
      // Middle buttons
      '&:not(:first-child):not(:last-child)': {
        borderRadius: 24,
        marginRight: theme.spacing(0.5),
        marginLeft: theme.spacing(0.5),
      },
      // First button
      '&:first-child': {
        borderRadius: 24,
        marginLeft: theme.spacing(0.25),
      },
      // Last button
      '&:last-child': {
        borderRadius: 24,
        marginRight: theme.spacing(0.25),
      },
    },
    // Root styles
    backgroundColor: darken(
      theme.palette.background.paper,
      getThemeType() === 'light' ? 0.05 : 0.25
    ),
    borderRadius: 24,
    boxSizing: 'content-box', // Fixed 'content: "border-box"' typo from original
  }));

  const StyledToggle = styled(ToggleButton)(({ theme }: { theme: Theme }) => ({
    root: {
      backgroundColor: "transparent",
      overflow: "visible",
      content: "content-box",
      "&$selected": {
        backgroundColor: "gold",
        color: "black",
        borderRadius: 24,
        fontWeight: "bold"
      },
      "&$selected:hover": {
        backgroundColor: "rgb(255, 255, 0)",
        color: "black",
        borderRadius: 24
      }
    },
    selected: {}
  }));

  useEffect(() => {
    let ebt = sessionStorage.getItem("expandBinTotal");
    if (ebt === "true") {
      setExpandTotal(true);
    } else {
      setExpandTotal(false);
    }

    let ebu = sessionStorage.getItem("expandBinUtilization");
    if (ebu === "true") {
      setExpandUtilization(true);
    } else {
      setExpandUtilization(false);
    }

    let binsView = sessionStorage.getItem("binsView");
    if (binsView === "scroll") {
      setBinView("scroll");
    } else {
      setBinView("grid");
    }

    let bagsView = sessionStorage.getItem("bagsView");
    if (bagsView === "scroll") {
      setBagView("scroll");
    } else {
      setBagView("grid");
    }

    let fanTable = sessionStorage.getItem("expandFanTable");
    if (fanTable === "true") {
      setExpandFanTable(true);
    } else {
      setExpandFanTable(false);
    }
  }, []);

  useEffect(() => {
    if (props.yardFilter) {
      setYardFilter(props.yardFilter);
    }
  }, [props.yardFilter]);

  const loadBins = useCallback(() => {
    //let filter = grainFilter;
    let filter = yardFilter;
    if (as === loadingAs && loadingFilter === filter) {
      return;
    }
    setLoadingAs(as);
    setLoadingFilter(filter);
    setAllLoading(true);
    setBinsLoading(true);
    setDisplayEmpty(false);
    setDisplayFert(false);

    binAPI
      .listBinsAndData(binsLimit, 0, order, orderBy, filter, as, false)
      .then(resp => {
        let grain: Bin[] = [];
        let empty: Bin[] = [];
        let fert: Bin[] = [];
        // let qr: QrCodeKey[] = [];
        let b = resp.data.bins.map(b => Bin.any(b));
        b.forEach(bin => {
          if (bin.empty()) {
            empty.push(bin);
          } else if (bin.storage() === pond.BinStorage.BIN_STORAGE_FERTILIZER) {
            fert.push(bin);
          } else {
            grain.push(bin);
          }
          //build qr keys here
          // qr.push({
          //   key: bin.key(),
          //   name: bin.name()
          // });
        });
        // setQrKeyList(qr);
        setGrainBins(grain);
        if (fert.length > 0) {
          setDisplayFert(true);
        }
        if (empty.length > 0) {
          setDisplayEmpty(true);
        }
        setFertilizerBins(fert);
        setEmptyBins(empty);
        setPaginatedBins({
          bins: b,
          binsOffset: resp.data.nextOffset,
          binsTotal: resp.data.total
        });
        let metrics = pond.BinMetrics.fromObject(resp.data.metrics ?? {});
        let inventory: GrainAmount[] = [];
        let fertInventory: GrainAmount[] = [];
        if (metrics) {
          metrics.grainInventory.forEach(grain => {
            inventory.push({
              grain: grain.grainType,
              bushelAmount: grain.bushelAmount,
              grainName: grainName(grain.grainType)
            });
          });
          metrics.customInventory.forEach(invObject => {
            if (invObject.storageType === pond.BinStorage.BIN_STORAGE_UNSUPPORTED_GRAIN) {
              inventory.push({
                grain: pond.Grain.GRAIN_CUSTOM,
                bushelAmount: invObject.amount,
                grainName: invObject.name
              });
            } else if (invObject.storageType === pond.BinStorage.BIN_STORAGE_FERTILIZER) {
              fertInventory.push({
                grain: pond.Grain.GRAIN_CUSTOM,
                bushelAmount: invObject.amount * 35.239,
                grainName: invObject.name
              });
            }
          });
        }
        setBinMetrics(metrics);
        setDisplayedInventory(inventory);
        setDisplayedFertilizer(fertInventory);
        if (yards.length === 0) {
          let y: pond.BinYardSettings[] = [];
          let p: Dictionary<pond.Permission[]> = {};
          let sortedYards = resp.data.binYards.sort((a, b) => {
            let yard1 = BinYardModel.create(a);
            let yard2 = BinYardModel.create(b);
            return (
              yard1.settings.userSort[as ?? user.id()] - yard2.settings.userSort[as ?? user.id()]
            );
          });
          sortedYards.forEach(yard => {
            let newYard = pond.BinYard.fromObject(yard ?? {});
            if (newYard.settings) {
              y.push(newYard.settings);
              p[newYard.settings.key] = newYard.yardPermissions;
            }
          });
          setYardPermissions(p);
          setYards(y);
        }

        //move load of grain bags into this api call
        const bags = resp.data.bags.map(b => GrainBag.create(b));
        setGrainBags(bags);
      })
      .catch(err => {
        setPaginatedBins({ bins: [], binsOffset: 0, binsTotal: 0 });
        setBinMetrics(pond.BinMetrics.create());
        setYards([]);
      })
      .finally(() => {
        setAllLoading(false);
        setBinsLoading(false);
      });
  }, [binAPI, yardFilter, order, orderBy, as, loadingAs, loadingFilter]); // eslint-disable-line react-hooks/exhaustive-deps

  //made this a seperate function because we only need to load the bins themselves, we do not need to load all the metric data again
  const loadMoreBins = (filter: string, offset?: number, limit?: number) => {
    setBinsLoading(true);
    let binFilter = filter;
    binFilter = binFilter + " " + yardFilter;
    binAPI
      .listBins(limit ?? binsLimit, offset ?? 0, order, orderBy, binFilter, as)
      .then(resp => {
        const newBins = resp.data.bins.map(b => Bin.any(b));
        setPaginatedBins({
          //the offset being passed in means to load more rather than a new set so combine the loaded bins with the existing ones rather than replace them
          bins: offset ? paginatedBins.bins.concat(newBins) : newBins,
          binsOffset: resp.data.nextOffset,
          binsTotal: resp.data.total
        });
        let empty: Bin[] = offset ? emptyBins : [];
        let fert: Bin[] = offset ? fertilizerBins : [];
        let grain: Bin[] = offset ? grainBins : [];
        // let newKeyList: QrCodeKey[] = qrKeyList;
        newBins.forEach(bin => {
          if (bin.empty()) {
            empty.push(bin);
          } else if (bin.storage() === pond.BinStorage.BIN_STORAGE_FERTILIZER) {
            fert.push(bin);
          } else {
            grain.push(bin);
          }
          // newKeyList.push({
          //   key: bin.key(),
          //   name: bin.name()
          // });
        });
        if (fert.length > 0) {
          setDisplayFert(true);
        }
        if (empty.length > 0) {
          setDisplayEmpty(true);
        }
        setGrainBins([...grain]);
        setEmptyBins([...empty]);
        setFertilizerBins([...fert]);
        // setQrKeyList([...newKeyList]);
      })
      .catch(err => {
        setPaginatedBins({ bins: [], binsOffset: 0, binsTotal: 0 });
      })
      .finally(() => {
        setBinsLoading(false);
      });
  };

  const searchYards = (
    search?: string,
    limit?: number,
    offset?: number,
    order?: "asc" | "desc"
  ) => {
    setYardsLoading(true);
    // binyardAPI.listBinYards(limit ?? binsLimit, offset ?? 0, order, "name", search).then(resp => {
    //   let y: pond.BinYardSettings[] = [];
    //   let p: Dictionary<pond.Permission[]> = {};
    //   //sort the yards after loading
    //   let sortedYards = resp.data.yard.sort((a, b) => {
    //     let yard1 = BinYardModel.create(a);
    //     let yard2 = BinYardModel.create(b);
    //     return yard1.settings.userSort[as ?? user.id()] - yard2.settings.userSort[as ?? user.id()];
    //   });
    //   //loop through the sorted yards
    //   sortedYards.forEach(yard => {
    //     let newYard = pond.BinYard.fromObject(yard ?? {});
    //     if (newYard.settings) {
    //       y.push(newYard.settings);
    //       p[newYard.settings.key] = newYard.yardPermissions;
    //     }
    //   });
    //   if (y.length > 0) {
    //     //dont set the yards if it came back with nothing
    //     setYardPermissions(p);
    //     setYards(y);
    //   }
    //   setYardsLoading(false);
    // });
  };

  useEffect(() => {
    loadBins();
    //if it is a drawer only show the bins, bags are only shown on the all tab so should not show up on the yard drawers
    if (props.insert) {
      setShowing("bins");
    }
  }, [loadBins, props.insert, contentFilter]);

  const duplicateBin = (bin: Bin) => {
    binAPI.addBin(bin.settings).then(resp => {
      loadBins();
    });
  };

  const addAlertsToCables = (bins: Bin[]) => {
    let alertList: pond.AlertData[] = [];
    bins.forEach(bin => {
      //for each of the cable in the bin create alert data
      bin.status.grainCables.forEach(cable => {
        //split the location into its three parts
        let locationParts = cable.address.split("-");
        if (locationParts[0] && locationParts[1] && locationParts[2]) {
          //build the alert based on the bin
          alertList.push(
            pond.AlertData.create({
              device: cable.device,
              nodeOne: cable.topNode,
              interactionSubtype: Interaction.upToSubtype(cable.topNode),
              condition: pond.InteractionCondition.create({
                measurementType: quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE,
                comparison: quack.RelationalOperator.RELATIONAL_OPERATOR_GREATER_THAN,
                value: describeMeasurement(
                  quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE
                ).toStored(bin.settings.highTemp)
              }),
              componentLocation: quack.ComponentID.create({
                type: parseInt(locationParts[0]),
                addressType: parseInt(locationParts[1]),
                address: parseInt(locationParts[2])
              })
            })
          );
        }
      });
    });
    interactionsAPI
      .setAlertInteractions(alertList)
      .then(resp => {
        openSnack("Successfully added " + resp.data.numAlertsSet + " alerts");
      })
      .catch(err => {
        console.log("errors found");
      });
  };

  const addALertsDialog = () => {
    return (
      <ResponsiveDialog open={openAddAlerts} onClose={() => setOpenAddAlerts(false)}>
        <DialogTitle>Add Alert to Bin Cables</DialogTitle>
        <DialogContent>
          This action will add an interaction to notify if the temp of any cable node in grain rises
          above the high temp warning for all selected bins
        </DialogContent>
        <DialogActions>
          <Button onClick={() => setOpenAddAlerts(false)}>Close</Button>
          <Button
            onClick={() => {
              addAlertsToCables(alertBins);
              setOpenAddAlerts(false);
            }}
            variant="contained"
            color="primary">
            Confirm
          </Button>
        </DialogActions>
      </ResponsiveDialog>
    );
  };

  const binsContent = () => {
    const { binsTotal } = paginatedBins;

    if (!allLoading && binsTotal <= 0) {
      return (
        <Box textAlign="center" marginTop={1}>
          <Typography variant="subtitle1">No bins found</Typography>
          <Typography variant="body1" color="textSecondary">
            Create a bin and it will appear here
          </Typography>
        </Box>
      );
    }

    if (binView === "list") {
      return (
        <ObjectTable
          startingObject={pond.ObjectType.OBJECT_TYPE_BIN}
          preLoadedData={paginatedBins.bins}
          rowClickFunction={data => {
            let bin = data as Bin;
            let path = "/bins/" + bin.key();
            navigate(path, { state: { bin: bin }});
          }}
          customButtons={[
            {
              label: "Set High Temp Notifications",
              function: objects => {
                setAlertBins(objects as Bin[]);
                setOpenAddAlerts(true);
              }
            }
          ]}
        />
      );
    }

    return (
      <React.Fragment>
        <Grid container>
          {displayGrain && (
            <React.Fragment>
              <Grid size={{ xs: 12 }}>
                <Divider />
              </Grid>
              <Grid size={{ xs: 12 }}>
                <BinsList
                  valDisplay={cardValDisplay}
                  gridView={binView === "grid"}
                  bins={grainBins}
                  duplicateBin={duplicateBin}
                  title={"Grain Bins"}
                  //startingTranslate={scrollTranslations.bins}
                  loadMore={() => {
                    if (paginatedBins.bins.length < paginatedBins.binsTotal) {
                      loadMoreBins(contentFilter, paginatedBins.binsOffset);
                    }
                  }}
                />
              </Grid>
            </React.Fragment>
          )}
          {displayFert && (
            <React.Fragment>
              <Grid size={{ xs: 12 }}>
                <Divider />
              </Grid>
              <Grid size={{ xs: 12 }}>
                <BinsList
                  valDisplay={cardValDisplay}
                  gridView={binView === "grid"}
                  bins={fertilizerBins}
                  duplicateBin={duplicateBin}
                  title={"Fertilizer Bins"}
                  //startingTranslate={scrollTranslations.fertilizer}
                  loadMore={() => {
                    if (paginatedBins.bins.length < paginatedBins.binsTotal) {
                      loadMoreBins(contentFilter, paginatedBins.binsOffset);
                      //setScrollTranslations({ ...scrollTranslations, fertilizer: newTranslation });
                    }
                  }}
                />
              </Grid>
            </React.Fragment>
          )}
          {displayEmpty && (
            <React.Fragment>
              <Grid size={{ xs: 12 }}>
                <Divider />
              </Grid>
              <Grid size={{ xs: 12 }}>
                <BinsList
                  valDisplay={cardValDisplay}
                  gridView={binView === "grid"}
                  bins={emptyBins}
                  duplicateBin={duplicateBin}
                  title={"Empty Bins"}
                  //startingTranslate={scrollTranslations.empty}
                  loadMore={() => {
                    if (paginatedBins.bins.length < paginatedBins.binsTotal) {
                      loadMoreBins(contentFilter, paginatedBins.binsOffset);
                      //setScrollTranslations({ ...scrollTranslations, empty: newTranslation });
                    }
                  }}
                />
              </Grid>
            </React.Fragment>
          )}
        </Grid>
      </React.Fragment>
    );
  };

  const grainBagsContent = () => {
    if (!allLoading && grainBags.length <= 0) {
      return (
        <Box textAlign="center" marginTop={1}>
          <Typography variant="subtitle1">No bags found</Typography>
          <Typography variant="body1" color="textSecondary">
            Create a grain bag and it will appear here
          </Typography>
        </Box>
      );
    }

    // if (bagView === "list") {
    //   return (
    //     <ObjectTable
    //       startingObject={pond.ObjectType.OBJECT_TYPE_GRAIN_BAG}
    //       preLoadedData={grainBags}
    //       rowClickFunction={data => {
    //         let bag = data as GrainBag;
    //         let path = "/grainbags/" + bag.key();
    //         history.push(path);
    //       }}
    //     />
    //   );
    // }

    return (
      <React.Fragment>
        <Grid container>
          <React.Fragment>
            <Grid size={{ xs: 12 }}>
              <Divider />
            </Grid>
            <Grid size={{ xs: 12 }}>
              <GrainBagList
                gridView={bagView === "grid"}
                grainBags={grainBags}
                title={"Grain Bags"}
              />
            </Grid>
          </React.Fragment>
        </Grid>
      </React.Fragment>
    );
  };

  const binMenu = () => {
    return (
      <Menu
        id="binMenu"
        anchorEl={menuAnchorEl ? menuAnchorEl : null}
        open={menuAnchorEl !== null}
        onClose={() => {
          setMenuAnchorEl(null);
          setAddBinOpen(false);
        }}
        disableAutoFocusItem>
        <MenuItem onClick={() => setAddBinOpen(true)} aria-label="Create Bin" dense>
          <ListItemIcon>
            <LibraryAdd className={classes.green} />
          </ListItemIcon>
          <ListItemText secondary="Create Bin" />
        </MenuItem>
      </Menu>
    );
  };

  const mobileViewCarousel = () => {
    let length = 2;
    let charts: JSX.Element[] = [
      <BinInventoryChart
        customLabel="Grain"
        inventory={displayedInventory}
        onClick={(grain: pond.Grain, grainName: string) => {
          let filter = "";
          if (grain !== pond.Grain.GRAIN_NONE && grain !== pond.Grain.GRAIN_CUSTOM) {
            filter = pond.Grain[grain];
          } else {
            filter = grainName;
          }
          setContentFilter(filter);
          loadMoreBins(filter);
        }}
        //activeGrain={grainFilter}
      />,
      <BinInventoryChart
        customLabel="Fertilizer"
        inventory={displayedFertilizer}
        onClick={(grain: pond.Grain, grainName: string) => {
          let filter = "";
          if (grain !== pond.Grain.GRAIN_NONE && grain !== pond.Grain.GRAIN_CUSTOM) {
            filter = pond.Grain[grain];
          } else {
            filter = grainName;
          }
          setContentFilter(filter);
          loadMoreBins(filter);
        }}
        customUnit={"L"}
        //activeGrain={grainFilter}
      />
    ];
    return (
      <React.Fragment>
        <Grid container direction="row" alignContent="center" alignItems="center">
          <Grid size={{ xs: 2 }}>
            <Button
              style={{ height: 160 }}
              onClick={() => {
                const newIndex = carouselIndex - 1;
                setCarouselIndex(newIndex < 0 ? length - 1 : newIndex);
              }}>
              <ArrowBackIos />
            </Button>
          </Grid>
          <Grid size={{ xs: 8 }}>
            <Box height={"180px"} flexDirection="row" display="flex">
              {charts[carouselIndex]}
            </Box>
          </Grid>
          <Grid size={{ xs: 2 }}>
            <Button
              style={{ height: 160 }}
              onClick={() => {
                const newIndex = carouselIndex + 1;
                setCarouselIndex(newIndex >= length ? 0 : newIndex);
              }}>
              <ArrowForwardIos />
            </Button>
          </Grid>
        </Grid>
      </React.Fragment>
    );
  };

  const desktopInventory = () => {
    return (
      <React.Fragment>
        <Grid container direction="row" alignContent="center" alignItems="center">
          <Grid style={{ height: "200px" }} size={{ xs: 6 }}>
            <BinInventoryChart
              customLabel="Grain"
              inventory={displayedInventory}
              onClick={(grain: pond.Grain, grainName: string) => {
                let filter = "";
                if (grain !== pond.Grain.GRAIN_NONE && grain !== pond.Grain.GRAIN_CUSTOM) {
                  filter = pond.Grain[grain];
                } else {
                  filter = grainName;
                }
                setContentFilter(filter);
                loadMoreBins(filter);
              }}
              //activeGrain={grainFilter}
            />
          </Grid>
          <Grid style={{ height: "200px" }} size={{ xs: 6 }}>
            <BinInventoryChart
              customLabel="Fertilizer"
              inventory={displayedFertilizer}
              onClick={(grain: pond.Grain, grainName: string) => {
                let filter = "";
                if (grain !== pond.Grain.GRAIN_NONE && grain !== pond.Grain.GRAIN_CUSTOM) {
                  filter = pond.Grain[grain];
                } else {
                  filter = grainName;
                }
                setContentFilter(filter);
                loadMoreBins(filter);
              }}
              customUnit={"L"}
              // activeGrain={grainFilter}
            />
          </Grid>
        </Grid>
      </React.Fragment>
    );
  };

  const totalInventory = () => {
    return (
      <Accordion
        className={classes.accordion}
        expanded={expandTotal}
        onChange={(_, expanded) => {
          setExpandTotal(expanded);
          sessionStorage.setItem("expandBinTotal", expanded.toString());
        }}>
        <AccordionSummary expandIcon={<ExpandMore />}>
          <Typography variant="h6" style={{ fontWeight: 650 }}>
            Total Inventory
          </Typography>
        </AccordionSummary>
        <AccordionDetails>{isMobile ? mobileViewCarousel() : desktopInventory()}</AccordionDetails>
      </Accordion>
    );
  };

  const binUtilizationList = () => {
    const hasInventory = binMetrics && binMetrics.grainInventory.length > 0;
    const useWeight = getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT;
    return (
      <Accordion
        className={classes.accordion}
        style={{ marginTop: 5 }}
        expanded={expandUtilization}
        onChange={(_, expanded) => {
          setExpandUtilization(expanded);
          sessionStorage.setItem("expandBinUtilization", expanded.toString());
        }}>
        <AccordionSummary expandIcon={<ExpandMore />}>
          <Typography variant="h6" style={{ fontWeight: 650 }}>
            Bin Utilization
          </Typography>
        </AccordionSummary>
        <AccordionDetails>
          {hasInventory ? (
            <Box width={"100%"}>
              <Typography variant="caption" color="textSecondary">
                Click a chart to filter bins by grain
              </Typography>
              <ImageList
                className={classes.gridList}
                cols={
                  props.insert && !isMobile
                    ? 3
                    : width === "xs"
                    ? 3
                    : width === "sm"
                    ? 5
                    : width === "md"
                    ? 6
                    : width === "lg"
                    ? 7
                    : 8
                  }
                >
                {binMetrics &&
                  binMetrics.grainInventory.map((inv, key) => (
                    <ImageListItem key={key}>
                      <BinUtilizationChart
                        grain={inv.grainType}
                        customUnit={useWeight ? " mT" : " bu"}
                        bushelAmount={
                          useWeight
                            ? inv.bushelAmount / GrainDescriber(inv.grainType).bushelsPerTonne
                            : inv.bushelAmount
                        }
                        bushelCapacity={
                          useWeight
                            ? inv.bushelCapacity / GrainDescriber(inv.grainType).bushelsPerTonne
                            : inv.bushelCapacity
                        }
                        onClick={() => {
                          setContentFilter(pond.Grain[inv.grainType]);
                          loadMoreBins(pond.Grain[inv.grainType]);
                        }}
                        grainActive={contentFilter === pond.Grain[inv.grainType]}
                      />
                    </ImageListItem>
                  ))}
                {binMetrics &&
                  binMetrics.customInventory.map((inv, key) => {
                    //default to bushel values
                    let amount = inv.amount;
                    let cap = inv.capacity;
                    let unit = " bu";
                    if (inv.storageType === pond.BinStorage.BIN_STORAGE_FERTILIZER) {
                      amount = amount * 35.239;
                      cap = cap * 35.239;
                      unit = " L";
                    }
                    if (useWeight && inv.bushelsPerTonne > 1) {
                      amount = amount / inv.bushelsPerTonne;
                      cap = cap / inv.bushelsPerTonne;
                      unit = " mT";
                    }

                    return (
                      <ImageListItem key={key}>
                        <BinUtilizationChart
                          grain={pond.Grain.GRAIN_CUSTOM}
                          bushelAmount={amount}
                          bushelCapacity={cap}
                          customUnit={unit}
                          onClick={() => {
                            setContentFilter(inv.name);
                            loadMoreBins(inv.name);
                          }}
                          grainActive={contentFilter === inv.name}
                          customLabel={inv.name}
                          customColour={stringToMaterialColour(inv.name)}
                        />
                      </ImageListItem>
                    );
                  })}
              </ImageList>
            </Box>
          ) : (
            <Typography color="textSecondary" style={{ margin: "2rem", marginTop: "0rem" }}>
              No active bins
            </Typography>
          )}
        </AccordionDetails>
      </Accordion>
    );
  };

  const binFanTable = () => {
    return (
      <Accordion
        className={classes.accordion}
        expanded={expandFanTable}
        style={{ marginTop: 5 }}
        onChange={(_, expanded) => {
          setExpandFanTable(expanded);
          sessionStorage.setItem("expandFanTable", expanded.toString());
        }}>
        <AccordionSummary expandIcon={<ExpandMore />}>
          <Typography variant="h6" style={{ fontWeight: 650 }}>
            Fan Status{" "}
            {totalFanControllers > 0 && !isMobile
              ? " - " + totalFanControllersOn + " of " + totalFanControllers + " controllers on"
              : ""}
          </Typography>
        </AccordionSummary>
        <AccordionDetails>
          <BinsFansStatusTable
            bins={paginatedBins.bins}
            isLoading={binsLoading}
            getControllerInfo={(total, on) => {
              setTotalFanControllers(total);
              setTotalFanControllersOn(on);
            }}
          />
        </AccordionDetails>
      </Accordion>
    );
  };

  const binsHeader = () => {
    return (
      <Menu
        id="yardMenu"
        anchorEl={binMenuAnchorEl ? binMenuAnchorEl : null}
        open={binMenuAnchorEl !== null}
        onClose={() => {
          setBinMenuAnchorEl(null);
        }}
        disableAutoFocusItem>
        <MenuItem>
          <FormControl style={{ marginLeft: theme.spacing(2) }}>
            <InputLabel id="demo-simple-select-label">Order</InputLabel>
            <Select
              labelId="demo-simple-select-label"
              id="demo-simple-select"
              value={order}
              onChange={event => setOrder(event.target.value as SetStateAction<"asc" | "desc">)}>
              <MenuItem value={"asc"}>Ascending</MenuItem>
              <MenuItem value={"desc"}>Descending</MenuItem>
            </Select>
          </FormControl>
        </MenuItem>
        <MenuItem>
          <FormControl style={{ marginLeft: theme.spacing(2) }}>
            <InputLabel id="demo-simple-select-label">Order By</InputLabel>
            <Select
              labelId="demo-simple-select-label"
              id="demo-simple-select"
              value={orderBy}
              onChange={event => setOrderBy(event.target.value as SetStateAction<string>)}>
              <MenuItem value={"name"}>Name</MenuItem>
              <MenuItem value={"timestamp"}>Timestamp</MenuItem>
            </Select>
          </FormControl>
        </MenuItem>
        <Divider />
        <MenuItem>
          <FormControlLabel
            control={
              <Checkbox
                checked={displayGrain}
                onChange={(e, checked) => {
                  setDisplayGrain(checked);
                }}
              />
            }
            label={<Typography>Grain</Typography>}
          />
        </MenuItem>
        <MenuItem>
          <FormControlLabel
            control={
              <Checkbox
                checked={displayFert}
                onChange={(e, checked) => {
                  setDisplayFert(checked);
                }}
              />
            }
            label={<Typography>Fertilizer</Typography>}
          />
        </MenuItem>
        <MenuItem>
          <FormControlLabel
            control={
              <Checkbox
                checked={displayEmpty}
                onChange={(e, checked) => {
                  setDisplayEmpty(checked);
                }}
              />
            }
            label={<Typography>Empty Bins</Typography>}
          />
        </MenuItem>
        <MenuItem
          onClick={() => {
            setOpenQrGenerator(true);
          }}>
          <Typography>Generate QR Codes</Typography>
        </MenuItem>
      </Menu>
    );
  };

  const binsByGrainType = () => {
    return (
      <Box width={1} marginBottom={1}>
        <Grid
          container
          direction="row"
          alignContent="center"
          alignItems="center"
          justifyContent="space-between">
          <Grid >
            <Box display="flex" paddingY={1} alignContent="center" alignItems="center">
              <Typography variant="h6" style={{ fontWeight: 650 }}>
                Bins - ({paginatedBins.bins.length} of {paginatedBins.binsTotal})
              </Typography>
              {contentFilter && (
                <Box marginLeft={1}>
                  <Chip
                    size="small"
                    onDelete={() => {
                      setContentFilter("");
                      loadMoreBins("");
                    }}
                    label={contentFilter}
                  />
                </Box>
              )}
              {(binView === "grid" || binView === "list") &&
                paginatedBins.bins.length < paginatedBins.binsTotal && (
                  <Button
                    style={{ marginLeft: 10 }}
                    variant="contained"
                    color="primary"
                    onClick={() => {
                      loadMoreBins(
                        contentFilter,
                        paginatedBins.binsOffset,
                        paginatedBins.binsTotal - paginatedBins.bins.length
                      );
                    }}>
                    Load All
                  </Button>
                )}
              <StyledToggleButtonGroup
                id="cardValueDisplay"
                value={cardValDisplay}
                exclusive
                size="small"
                aria-label="card detail">
                <StyledToggle
                  value={"low"}
                  aria-label="low"
                  onClick={() => {
                    setCardValDisplay("low");
                  }}>
                  Low
                </StyledToggle>
                <StyledToggle
                  value={"average"}
                  aria-label="average"
                  onClick={() => {
                    setCardValDisplay("average");
                  }}>
                  Average
                </StyledToggle>
                <StyledToggle
                  value={"high"}
                  aria-label="high"
                  onClick={() => {
                    setCardValDisplay("high");
                  }}>
                  High
                </StyledToggle>
              </StyledToggleButtonGroup>
            </Box>
          </Grid>
          <Grid >
            <Box display="flex" paddingY={1} alignContent="center" alignItems="center">
              <StyledToggleButtonGroup
                id="tour-graph-tabs"
                value={binView}
                exclusive
                size="small"
                aria-label="detail">
                <StyledToggle
                  value={"grid"}
                  aria-label="grid view"
                  onClick={() => {
                    setBinView("grid");
                    sessionStorage.setItem("binsView", "grid");
                  }}>
                  <ViewComfy />
                </StyledToggle>
                {/* hidden at dustins request so that grid view and list are the only two */}
                {/* <StyledToggle
                  value={"scroll"}
                  aria-label="scroll view"
                  onClick={() => {
                    setBinView("scroll");
                    sessionStorage.setItem("binsView", "scroll");
                  }}>
                  <ViewColumn />
                </StyledToggle> */}
                <StyledToggle
                  value={"list"}
                  aria-label="list view"
                  onClick={() => {
                    setBinView("list");
                    sessionStorage.setItem("binsView", "list");
                  }}>
                  <ViewList />
                </StyledToggle>
              </StyledToggleButtonGroup>
              <MoreVert
                className={classes.icon}
                onClick={event => {
                  let target = event.currentTarget;
                  setBinMenuAnchorEl(target);
                }}
              />
            </Box>
          </Grid>
        </Grid>
        {binsLoading ? <Skeleton variant="rectangular" height="200px" /> : binsContent()}
        {binsHeader()}
      </Box>
    );
  };

  const grainBagDisplay = () => {
    return (
      <Box width={1} marginBottom={1}>
        <Grid
          container
          direction="row"
          alignContent="center"
          alignItems="center"
          justifyContent="space-between">
          <Grid size={{ xs: 12 }}>
            <Divider />
          </Grid>
          <Grid >
            <Box display="flex" paddingY={1} alignContent="center" alignItems="center">
              <Typography variant="h6" style={{ fontWeight: 650 }}>
                Bags
              </Typography>
            </Box>
          </Grid>
          <Grid >
            <Box display="flex" paddingY={1} alignContent="center" alignItems="center">
              <StyledToggleButtonGroup
                id="tour-graph-tabs"
                value={bagView}
                exclusive
                size="small"
                aria-label="detail">
                <StyledToggle
                  value={"grid"}
                  aria-label="grid view"
                  onClick={() => {
                    setBagView("grid");
                    sessionStorage.setItem("bagsView", "grid");
                  }}>
                  <ViewComfy />
                </StyledToggle>
                {/* hidden at dustins request so that grid view and list are the only two */}
                {/* <StyledToggle
                  value={"scroll"}
                  aria-label="scroll view"
                  onClick={() => {
                    setBagView("scroll");
                    sessionStorage.setItem("bagsView", "scroll");
                  }}>
                  <ViewColumn />
                </StyledToggle> */}
                <StyledToggle
                  value={"list"}
                  aria-label="list view"
                  onClick={() => {
                    setBagView("list");
                    sessionStorage.setItem("bagsView", "list");
                  }}>
                  <ViewList />
                </StyledToggle>
              </StyledToggleButtonGroup>
              <IconButton
                className={classes.icon}
                onClick={() => {
                  setAddBagOpen(true);
                }}>
                +
              </IconButton>
            </Box>
          </Grid>
        </Grid>
        {allLoading ? <Skeleton variant="rectangular" height="200px" /> : grainBagsContent()}
      </Box>
    );
  };

  const { binsTotal } = paginatedBins;

  const page = () => {
    return (
      <Box>
        {addALertsDialog()}
        <BinYards
          yards={yards}
          yardsLoading={yardsLoading}
          yardPerms={yardPermissions}
          showTabs={!props.insert}
          setYardFilter={setYardFilter}
          bins={paginatedBins.bins}
          loadBins={loadBins}
          loadYards={(search, limit, offset) => {
            searchYards(search, limit, offset);
          }}
          grainBags={grainBags}
          setShowing={(val: "all" | "bins" | "bags") => {
            setShowing(val);
          }}
        />
        <Box height={1}>
          <Box
            paddingY={isMobile || props.insert ? 0.5 : 1}
            paddingX={isMobile || props.insert ? 1 : 2}>
            <Grid container>
              {(showing === "all" || showing === "bins") && (
                <Grid size={{ xs: 12 }}>
                  {binsByGrainType()}
                </Grid>
              )}
              <Grid size={{ xs: 12 }}>
                {allLoading ? <Skeleton variant="rectangular" height="200px" /> : totalInventory()}
              </Grid>
              <Grid size={{ xs: 12 }}>
                <Divider />
              </Grid>
              <Grid size={{ xs: 12 }}>
                {allLoading ? <Skeleton variant="rectangular" height="200px" /> : binUtilizationList()}
              </Grid>
              <Grid size={{ xs: 12 }}>
                <Divider />
              </Grid>
              <Grid size={{ xs: 12 }}>
                {allLoading ? <Skeleton variant="rectangular" height="200px" /> : binFanTable()}
              </Grid>
              <Grid size={{ xs: 12 }}>
                <Divider />
              </Grid>

              {(showing === "all" || showing === "bags") && (
                <Grid size={{ xs: 12 }}>
                  {grainBagDisplay()}
                </Grid>
              )}
            </Grid>
          </Box>
        </Box>
        <BinSettings
          mode="add"
          canEdit={true}
          open={addBinOpen}
          userID={user.id()}
          openedBinYard={yardFilter}
          binYards={yards}
          onClose={refresh => {
            setAddBinOpen(false);
            if (refresh) {
              loadBins();
            }
          }}
        />
        <GrainBagSettings
          open={addBagOpen}
          close={() => {
            setAddBagOpen(false);
          }}
        />
        {/* <QrCodeGenerator
          open={openQrGenerator}
          close={() => {
            setOpenQrGenerator(false);
          }}
          keyList={qrKeyList}
          requiredUrlAffix={"bins"}
        /> */}
        {binMenu()}
        <AddBinFab onClick={() => setAddBinOpen(true)} pulse={binsTotal < 1 && !allLoading} />
      </Box>
    );
  };

  return !props.insert ? <PageContainer padding={-1}>{page()}</PageContainer> : page();
}
