import {
  Accordion,
  AccordionDetails,
  AccordionSummary,
  AppBar,
  Box,
  Button,
  Checkbox,
  Collapse,
  DialogActions,
  DialogContent,
  DialogContentText,
  DialogTitle,
  FormControl,
  FormControlLabel,
  FormHelperText,
  FormLabel,
  Grid2 as Grid,
  IconButton,
  InputAdornment,
  MobileStepper,
  Radio,
  RadioGroup,
  Step,
  StepLabel,
  Stepper,
  Switch,
  Tab,
  Tabs,
  TextField,
  Theme,
  Toolbar,
  Tooltip,
  Typography,
  useTheme
} from "@mui/material";
import { Close, ExpandMore, Info, KeyboardArrowLeft, KeyboardArrowRight } from "@mui/icons-material";
// import { getBinModel } from "common/DataImports/BinCables/BinCableImporter";
//import { jsonBin } from "common/DataImports/BinCables/BinCableImporter";
import DeleteButton from "common/DeleteButton";
import OutlinedBox from "common/OutlinedBox";
import ResponsiveDialog from "common/ResponsiveDialog";
import SearchSelect, { Option } from "common/SearchSelect";
import {
  ConeVolume,
  CylinderVolume,
  RadiansToDegrees,
  TriangleOppositeLength
} from "common/TrigFunctions";
import FanPicker from "fans/fanPicker";
import { GrainOptions, ToGrainOption } from "grain";
import GrainDescriber from "grain/GrainDescriber";
import GrainTransaction from "grain/GrainTransaction";
import { GetGrainUseOptions, ToGrainUseOption } from "grain/GrainUse";
import { useMobile, useSnackbar } from "hooks";
import { clone, cloneDeep } from "lodash";
import { Bin } from "models";
import moment from "moment";
import { GetBinShapeDescribers } from "pbHelpers/Bin";
import { pond } from "protobuf-ts/pond";
import { useBinAPI, useBinYardAPI, useGlobalState, useLibraCartProxyAPI } from "providers";
import React, { useCallback, useEffect, useState } from "react";
// import { useHistory } from "react-router";
import { getDistanceUnit, or, getTemperatureUnit, getGrainUnit } from "utils";
import { makeStyles } from "@mui/styles";
import { useNavigate } from "react-router-dom";
import BinSelector from "./BinSelector";
// import BinSelector from "./BinSelector";

const useStyles = makeStyles((theme: Theme) => {
  return ({
    stepper: {
      padding: theme.spacing(0.5)
    },
    secondaryColor: {
      color: theme.palette.secondary.main
    },
    textSecondaryColor: {
      color: theme.palette.text.secondary
    },
    bottomSpacing: {
      marginBottom: theme.spacing(1)
    },
    tabs: {
      width: "100%",
      boxSizing: "border-box",
      flexShrink: 1
    },
    tabSmall: {
      width: "100%",
      boxSizing: "border-box",
      flexShrink: 1,
      minWidth: "48px"
    }
  })
});

type Mode = "add" | "update" | "remove";

interface Props {
  open: boolean;
  onClose: (refresh?: boolean) => void;
  mode?: Mode;
  bin?: Bin;
  canEdit: boolean;
  openedBinYard?: string;
  userID: string;
  coords?: { longitude: number; latitude: number };
  binYards?: pond.BinYardSettings[];
}

interface BinStep {
  label: string;
}

const getSteps = (): BinStep[] => {
  return [{ label: "General" }, { label: "Fan" }, { label: "Inventory" }, { label: "Thresholds" }];
};

interface BinFormExtension {
  capacity: string;
  height: string;
  topConeHeight: string;
  sidewallHeight: string;
  hopperHeight: string;
  diameter: string;
  grainBushels: string;
  grainTonnes: string;
  grainType: Option | null;
  grainUse: Option | null;
  grainSubtype: string;
  customTypeName: string;
  highTemp: number;
  lowTemp: number;
  bushelsPerTonne: string;
  tempTarget: number;
}

export default function BinSettings(props: Props) {
  const classes = useStyles();
  //the conversion constant to convert cubic feet to bushels
  const conversionConstantFT = 0.7786;
  const isMobile = useMobile();
  const theme = useTheme();
  // const history = useHistory();
  const navigate = useNavigate();
  const binAPI = useBinAPI();
  const binYardAPI = useBinYardAPI();
  const { openSnack } = useSnackbar();
  const { open, bin, onClose, mode, canEdit, openedBinYard, userID, coords } = props;
  const steps = getSteps();
  const [activeStep, setActiveStep] = useState(0);
  const [form, setForm] = useState<pond.BinSettings>(pond.BinSettings.create());
  const [formExtension, setFormExtension] = useState<BinFormExtension>({
    capacity: "",
    height: "",
    topConeHeight: "",
    sidewallHeight: "",
    hopperHeight: "",
    diameter: "",
    grainBushels: "",
    grainTonnes: "",
    grainType: null,
    grainUse: null,
    grainSubtype: "",
    customTypeName: "",
    highTemp: 20,
    lowTemp: 10,
    bushelsPerTonne: "",
    tempTarget: 15
  });
  const [initialized, setInitialized] = useState(false);
  const [removeIsOpen, setRemoveIsOpen] = useState(false);
  const [binYardOptions, setBinYardOptions] = useState<Option[] | null>(null);
  const [selectedBinYard, setSelectedBinYard] = useState<Option | null>(null);
  const grainOptions = GrainOptions();
  const grainUseOptions = GetGrainUseOptions();
  const [inputCapacity, setInputCapacity] = useState<string>("");
  const [{ user, as }] = useGlobalState();
  const [grainDiff, setGrainDiff] = useState(0);
  const [isCustomInventory, setIsCustomInventory] = useState<boolean>(false);
  const [grainUpdate, setGrainUpdate] = useState(false);
  const [inMoistureString, setInMoistureString] = useState("0");
  const [tMoistureString, setTMoistureString] = useState("0");
  const [moistureTargetDeviation, setMoistureTargetDeviation] = useState("0");
  const [autoFillThreshold, setAutoFillThreshold] = useState(0);
  const [validInitial, setValidInitial] = useState(true);
  const [validTarget, setValidTarget] = useState(true);
  const [validDeviation, setValidDeviation] = useState(true);
  const [highTempC, setHighTempC] = useState(20);
  const [lowTempC, setLowTempC] = useState(10);
  const [isCustomBin, setIsCustomBin] = useState(false);
  const [binModelOps, setBinModelOptions] = useState<Option[]>([]);
  const [selectedBinModel, setSelectedBinModel] = useState<Option | null>(null);
  const [modelID, setModelID] = useState(0);
  const [autoTopNode, setAutoTopNode] = useState(false);
  const [inventoryControl, setInventoryControl] = useState<pond.BinInventoryControl>(
    pond.BinInventoryControl.BIN_INVENTORY_CONTROL_UNKNOWN
  );
  const [storageType, setStorageType] = useState<pond.BinStorage>(
    pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN
  );
  //libracart stuff
  const libracartAPI = useLibraCartProxyAPI()
  const [lcDestination, setlcDestination] = useState<Option | null>()
  const [lcDestinationOptions, setlcDestinationOptions] = useState<Option[]>([])

  useEffect(() => {
    if (open) {
      if (bin && bin.settings.specs) {
        setIsCustomBin(true);
        setModelID(bin.settings.specs.modelId);
      }
      let initForm = pond.BinSettings.create(
        bin
          ? bin.settings
          : {
              ...{
                specs: pond.BinSpecs.create({ shape: pond.BinShape.BIN_SHAPE_FLAT_BOTTOM }),
                inventory: pond.BinInventory.create({ grainBushels: 0, targetTemperature: 15 }),
                highTemp: 20,
                lowTemp: 10
              }
            }
      );
      if (mode === "add") {
        initForm.yardKey = or(openedBinYard, "");
      }

      if (initForm.inventory) {
        setInventoryControl(initForm.inventory.inventoryControl);
        //make sure bushels per tonne is set so bins that don't have it in the settings yet can still do it before they get updated properly
        if (!initForm.inventory.bushelsPerTonne) {
          initForm.inventory.bushelsPerTonne = GrainDescriber(
            initForm.inventory.grainType
          ).bushelsPerTonne;
        }
        //if the target temp is not set (older bins) make it the midpoint of the high and low temps assuming they are set otherwise make it 15
        if (!initForm.inventory.targetTemperature || initForm.inventory.targetTemperature) {
          if (initForm.highTemp && initForm.lowTemp) {
            initForm.inventory.targetTemperature = (initForm.lowTemp + initForm.highTemp) / 2;
          } else {
            initForm.inventory.targetTemperature = 15;
          }
        }
      }

      let h = "";
      let d = "";
      let topconeHeight = "";
      let sidewallHeight = "";
      let hopperHeight = "";
      if (initForm.specs) {
        if (getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_FEET) {
          h = (initForm.specs.heightCm * 0.0328).toFixed(2);
          d = (initForm.specs.diameterCm * 0.0328).toFixed(2);
          if (initForm.specs.advancedDimensions) {
            topconeHeight = (initForm.specs.advancedDimensions.topConeHeight * 0.0328).toFixed(2);
            sidewallHeight = (initForm.specs.advancedDimensions.sidewallHeight * 0.0328).toFixed(2);
            hopperHeight = (initForm.specs.advancedDimensions.hopperHeight * 0.0328).toFixed(2);
          }
        } else {
          h = (initForm.specs.heightCm / 100).toFixed(2);
          d = (initForm.specs.diameterCm / 100).toFixed(2);
          if (initForm.specs.advancedDimensions) {
            topconeHeight = (initForm.specs.advancedDimensions.topConeHeight / 100).toFixed(2);
            sidewallHeight = (initForm.specs.advancedDimensions.sidewallHeight / 100).toFixed(2);
            hopperHeight = (initForm.specs.advancedDimensions.hopperHeight / 100).toFixed(2);
          }
        }
      }
      let high = initForm.highTemp ?? 20;
      let low = initForm.lowTemp ?? 10;
      let target = initForm.inventory?.targetTemperature ?? 15;
      if (getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT) {
        high = parseFloat((high * 1.8 + 32).toFixed(2));
        low = parseFloat((low * 1.8 + 32).toFixed(2));
        target = parseFloat((target * 1.8 + 32).toFixed(2));
      }

      let gb =
        initForm.storage === pond.BinStorage.BIN_STORAGE_FERTILIZER
          ? initForm.inventory?.grainBushels
            ? initForm.inventory.grainBushels * 35.239
            : 0
          : initForm.inventory?.grainBushels ?? 0;

      setForm(initForm);
      setHighTempC(initForm.highTemp ?? 20);
      setLowTempC(initForm.lowTemp ?? 10);
      setFormExtension({
        capacity: initForm.specs?.bushelCapacity.toString() ?? "",
        height: h,
        diameter: d,
        grainBushels: gb.toFixed(2),
        grainTonnes: initForm.inventory?.bushelsPerTonne
          ? (gb / initForm.inventory.bushelsPerTonne).toFixed(2)
          : "",
        grainType: initForm.inventory?.grainType
          ? ToGrainOption(initForm.inventory.grainType)
          : null,
        grainUse: initForm.inventory?.grainUse
          ? ToGrainUseOption(initForm.inventory.grainUse)
          : null,
        grainSubtype: initForm.inventory?.grainSubtype ?? "",
        customTypeName: initForm.inventory?.customTypeName ?? "",
        highTemp: high,
        lowTemp: low,
        tempTarget: target,
        hopperHeight: hopperHeight,
        topConeHeight: topconeHeight,
        sidewallHeight: sidewallHeight,
        bushelsPerTonne: initForm.inventory?.bushelsPerTonne.toString() ?? "0"
      });
      setInMoistureString(initForm.inventory?.initialMoisture.toString() ?? "0");
      setTMoistureString(initForm.inventory?.targetMoisture.toString() ?? "0");
      setMoistureTargetDeviation(initForm.inventory?.moistureTargetDeviation.toString() ?? "0");
      setAutoFillThreshold(initForm.inventory?.autoThreshold ?? 0)
      setActiveStep(0);
      if (bin) {
        setAutoTopNode(bin.settings.autoGrainNode);
        setIsCustomInventory(bin.storage() !== pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN);
      }
      setStorageType(initForm.storage);
      setInitialized(true);
    } else {
      setInitialized(false);
    }
  }, [bin, open, mode, openedBinYard]);

  useEffect(() => {
    if (mode === "remove") {
      setRemoveIsOpen(true);
    }
  }, [mode]);

  const loadBinYards = useCallback(() => {
    if (props.binYards) {
      let yards: Option[] = props.binYards.map(yard => {
        let option = { value: yard.key, label: yard.name } as Option;
        if (yard.key === form.yardKey) {
          setSelectedBinYard(option);
        }
        return option;
      });
      let y: Option[] = [];
      y.push({ value: "", label: "No Yard" } as Option);
      y = yards.concat(y);
      setBinYardOptions(y);
    } else {
      binYardAPI
        .listBinYards(350, 0, "desc", as ? as : userID, undefined, undefined, as)
        .then(resp => {
          let data = resp.data.yard ? resp.data.yard : [];
          let yards: Option[] = data.map((yard: pond.BinYard) => {
            let option = { value: yard.settings?.key, label: yard.settings?.name } as Option;
            if (yard.settings?.key === form.yardKey) {
              setSelectedBinYard(option);
            }
            return option;
          });
          let y: Option[] = [];
          y.push({ value: "", label: "No Yard" } as Option);
          y = yards.concat(y);
          setBinYardOptions(y);
        })
        .catch(() => {});
    }
  }, [binYardAPI, form.yardKey, userID, as, props.binYards]);

  const loadLibraCartDestinations = useCallback(()=>{
    if(inventoryControl === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_LIBRACART){
      //load the destinations for the user/team they are viewing as
      let options: Option[] = []
      libracartAPI.listDestinations(0,0,undefined, as)
      .then(resp=>{
        //set the options for the search select
        resp.data.destinations.forEach(d => {
          let newOp: Option = {
            label: d.name,
            value: d.id
          }
          options.push(newOp)
          //set the current option based on the key in the form
          if (d.id === form.libracartDestinationKey){
            setlcDestination(newOp)
          }
        })
        setlcDestinationOptions(options)
      }).catch(()=>{})
    }
  },[libracartAPI, inventoryControl, as, form.libracartDestinationKey])

  useEffect(() => {
    loadBinYards();
    loadLibraCartDestinations();
  }, [loadBinYards, loadLibraCartDestinations]);

  useEffect(() => {
    if (bin?.settings.specs?.bushelCapacity) {
      setInputCapacity(bin.settings.specs.bushelCapacity.toFixed(0));
    }
  }, [bin]);

  const close = (refresh?: boolean) => {
    onClose(refresh);
  };

  const addBin = () => {
    // If initial moisture is updated, so does the timestamp
    if (form.inventory?.initialMoisture !== bin?.settings.inventory?.initialMoisture) {
      if (form.inventory) form.inventory.initialTimestamp = moment().format();
    }
    if (form.inventory?.initialTimestamp === "") {
      form.inventory.initialTimestamp = moment().format();
    }
    if (form.specs) {
      form.specs.bushelCapacity = Number(inputCapacity);
      if (form.specs.useAdvanced && form.specs.advancedDimensions) {
        let adD = form.specs.advancedDimensions;
        form.specs.heightCm = adD.hopperHeight + adD.sidewallHeight + adD.topConeHeight;
      }
    }

    //if coordinates are passed in give the bin a location
    if (coords) {
      form.location = pond.Location.create({
        longitude: coords.longitude,
        latitude: coords.latitude
      });
    }
    form.mode = pond.BinMode.BIN_MODE_STORAGE; //make sure bins are in storage mode when creating new bins
    form.storage = storageType;
    form.highTemp = highTempC;
    form.lowTemp = lowTempC;
    form.autoGrainNode = autoTopNode;
    if (form.inventory) {
      form.inventory.inventoryControl = inventoryControl
      form.inventory.autoThreshold = autoFillThreshold
    }

    binAPI
      .addBin(form, as)
      .then(resp => {
        openSnack("Successfully created bin");
        if (!coords) {
          let binPath: string = "/bins/" + resp.data.bin;
          navigate(binPath);
        }
        close(true);
      })
      .catch((err: any) => {
        openSnack("Failed to create bin");
        close();
      });
  };

  const updateBin = () => {
    // If initial moisture is updated, so does the timestamp
    if (form.inventory?.initialMoisture !== bin?.settings.inventory?.initialMoisture) {
      if (form.inventory) form.inventory.initialTimestamp = moment().format();
    }
    if (form.inventory?.initialTimestamp === "") {
      form.inventory.initialTimestamp = moment().format();
    }
    if (form.specs) {
      form.specs.bushelCapacity = Number(inputCapacity);
      if (form.specs.useAdvanced && form.specs.advancedDimensions) {
        let adD = form.specs.advancedDimensions;
        form.specs.heightCm = adD.hopperHeight + adD.sidewallHeight + adD.topConeHeight;
      }
    }
    if (form.inventory?.grainBushels !== bin?.settings.inventory?.grainBushels) {
      let current = bin?.settings.inventory?.grainBushels ?? 0;
      let newVal = form.inventory?.grainBushels ?? 0;
      setGrainDiff(newVal - current);
      setGrainUpdate(true);
    } else {
      if (bin && bin.key()) {
        form.storage = storageType;
        form.highTemp = highTempC;
        form.lowTemp = lowTempC;
        form.autoGrainNode = autoTopNode;
        if (form.inventory) {
          form.inventory.inventoryControl = inventoryControl
          form.inventory.autoThreshold = autoFillThreshold
        }
        console.log(form)
        binAPI
          .updateBin(bin.key(), form, as)
          .then(response => {
            openSnack("Updated " + bin.name());
            close(true);
          })
          .catch((err: any) => {
            openSnack("Failed to update " + bin.name());
            close();
          });
      }
    }
  };

  const grainInventoryController = () => {
    if (bin) {
      let newBin = clone(bin);
      newBin.settings = cloneDeep(form); //need to make sure to use all the changed settings
      if (newBin.settings.inventory) {
        newBin.settings.inventory.grainBushels = bin.settings.inventory?.grainBushels ?? 0; //but also need to use the old inventory amount so the diff is applied correctly
      }
      return (
        <GrainTransaction
          open={grainUpdate}
          mainObject={newBin}
          grainAdjustment={grainDiff}
          close={() => {
            setGrainUpdate(false);
            setGrainDiff(0);
          }}
          callback={() => {
            close(true);
          }}
        />
      );
    }
  };

  const removeBin = () => {
    if (bin && bin.key()) {
      binAPI
        .removeBin(bin.key(), as)
        .then(response => {
          openSnack(bin.name() + " was removed");
          navigate("/bins");
        })
        .catch(err => {
          openSnack("Failed to remove " + bin.name() + ".");
          setRemoveIsOpen(false);
          close();
        });
    }
  };

  const isFormValid = () => {
    let valid = false;
    if (
      validInitial &&
      validTarget &&
      validDeviation &&
      +formExtension.highTemp > +formExtension.lowTemp &&
      +formExtension.lowTemp <= +formExtension.tempTarget &&
      +formExtension.highTemp >= +formExtension.tempTarget
    ) {
      valid = true;
    }
    return valid;
  };

  const stepComplete = (step: number) => {
    switch (step) {
      case 1:
        let fan = form.fan;
        let fanValid =
          fan && fan.type !== pond.FanType.FAN_TYPE_UNKNOWN
            ? fan.size !== pond.FanHp.FAN_HP_UNKNOWN
            : true;
        return fanValid;
      case 0:
        let specs = form.specs;
        let specsValid =
          specs && Number(inputCapacity) > 0 && specs.diameterCm > 0 && specs.heightCm > 0;
        return specsValid
      default:
        return true;
    }
  };

  const stepNext = () => {
    setActiveStep(activeStep + 1);
  };

  const stepBack = () => {
    setActiveStep(activeStep - 1);
  };

  const updateForm = (
    key: keyof pond.BinSettings,
    value: pond.BinSettings[keyof pond.BinSettings]
  ) => {
    setForm(pond.BinSettings.create({ ...form, [key]: value }));
  };

  const updateFormExtension = (
    key: keyof BinFormExtension,
    value: BinFormExtension[keyof BinFormExtension]
  ) => {
    setFormExtension({ ...formExtension, [key]: value });
  };

  const titleText = () => {
    return mode === "add" ? "Create Bin" : "Update " + (bin ? bin.name() : "Bin");
  };

  const stepper = () => {
    if (mode === "add") {
      return (
        <Stepper
          activeStep={activeStep}
          alternativeLabel
          classes={{
            root: classes.stepper
          }}>
          {steps.map((s, i) => (
            <Step
              key={i}
              onClick={() => {
                const incompleteUpTo = (upTo: number): number => {
                  for (let j = 0; j < i; j++) {
                    if (!stepComplete(j)) {
                      return j;
                    }
                  }
                  return -1;
                };

                if (i <= activeStep || incompleteUpTo(i) === -1) {
                  setActiveStep(i);
                } else {
                  openSnack("Step " + (incompleteUpTo(i) + 1).toString() + " is incomplete");
                }
              }}>
              <StepLabel>{s.label}</StepLabel>
            </Step>
          ))}
        </Stepper>
      );
    }

    return (
      <Box display="flex" justifyContent="center" width="100%">
        <Tabs
          value={activeStep}
          onChange={(_, value) => setActiveStep(value)}
          indicatorColor="primary"
          textColor="primary"
          variant="fullWidth"
          aria-label="bin tabs"
          classes={{ root: classes.tabs }}>
          {steps.map((s, i) => (
            <Tab key={i} label={s.label} aria-label={s.label} />
          ))}
        </Tabs>
      </Box>
    );
  };

  const title = () => {
    if (isMobile) {
      return (
        <AppBar position="relative">
          <Toolbar>
            <IconButton edge="start" color="inherit" onClick={() => close()} aria-label="close">
              <Close />
            </IconButton>
            <Typography variant="h6" style={{ flex: 1 }}>
              {titleText()}
            </Typography>
            {mode === "add" ? (
              <Button
                onClick={() => addBin()}
                disabled={!isFormValid() || activeStep !== steps.length - 1}
                aria-label="create bin"
                color="inherit">
                Create
              </Button>
            ) : (
              <Button
                onClick={() => updateBin()}
                disabled={!canEdit || !isFormValid()}
                aria-label="update bin">
                Update
              </Button>
            )}
          </Toolbar>
          {stepper()}
        </AppBar>
      );
    }

    return (
      <React.Fragment>
        <DialogTitle>{titleText()}</DialogTitle>
        {mode === "update" && (
          <Tabs
            value={activeStep}
            onChange={(_, value) => setActiveStep(value)}
            indicatorColor="primary"
            textColor="primary"
            variant="fullWidth"
            aria-label="bin tabs"
            classes={{ root: classes.tabSmall }}>
            {steps.map((s, i) => (
              <Tab className={classes.tabSmall} key={i} label={s.label} aria-label={s.label} />
            ))}
          </Tabs>
        )}
      </React.Fragment>
    );
  };

  const binYardForm = () => {
    return (
      <Box style={{ marginTop: theme.spacing(1) }}>
        <Typography variant="subtitle2" align="center" color="primary" gutterBottom>
          Bin Yard
        </Typography>

        <Box marginY={1}>
          <SearchSelect
            selected={selectedBinYard}
            changeSelection={(option: Option | null) => {
              let newForm = form;
              newForm.yardKey = option?.value;
              setForm(newForm);
              setSelectedBinYard(option ? option : null);
            }}
            disabled={!canEdit}
            options={binYardOptions ? binYardOptions : []}
            label="Yard"
            loading={false}
          />
        </Box>
      </Box>
    );
  };

  const inventoryControlLabel = (control: pond.BinInventoryControl) => {
    switch(control){
      case pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC_LIDAR:
        return "Auto (lidar)"
      case pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC:
        return "Auto (cable)"
      case pond.BinInventoryControl.BIN_INVENTORY_CONTROL_HYBRID_LIDAR:
        return "Hybrid (lidar)"
      case pond.BinInventoryControl.BIN_INVENTORY_CONTROL_LIBRACART:
        return "Auto (Libra Cart)"
      default:
        return "Manual"
    }
  };

  const inventoryForm = () => {
    const inventory = form.inventory;
    const empty = inventory ? inventory.empty : false;
    const bushPerTonne = formExtension.bushelsPerTonne;
    const binQuantity = formExtension.grainBushels;
    const grainTonnes = formExtension.grainTonnes;
    const grainType = formExtension.grainType;
    const grainSubtype = formExtension.grainSubtype;
    const grainUse = formExtension.grainUse;
    const customTypeName = formExtension.customTypeName;
    return (
      <Box>
        <Typography variant="subtitle2" align="center" color="primary">
          Bin Inventory
        </Typography>

        <Grid container justifyContent="space-between" alignItems="center">
          <Grid>
            <Grid container alignItems="center">
              <Grid>Grain</Grid>
              <Grid>
                <Switch
                  color="default"
                  value={isCustomInventory}
                  checked={isCustomInventory}
                  onChange={(_, checked) => {
                    setIsCustomInventory(checked);
                    if (checked) {
                      setStorageType(pond.BinStorage.BIN_STORAGE_UNSUPPORTED_GRAIN);
                      updateForm(
                        "inventory",
                        pond.BinInventory.create({
                          ...form.inventory,
                          grainType: pond.Grain.GRAIN_CUSTOM,
                          bushelsPerTonne: 0
                        })
                      );
                      updateFormExtension("grainType", null);
                      updateFormExtension("bushelsPerTonne", "");
                    } else {
                      setStorageType(pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN);
                      updateForm(
                        "inventory",
                        pond.BinInventory.create({
                          ...form.inventory,
                          customTypeName: undefined
                        })
                      );
                      updateFormExtension("customTypeName", "");
                    }
                  }}
                  name="storage"
                />
              </Grid>
              <Grid>Custom</Grid>
            </Grid>
          </Grid>
          <Grid>
            <FormControlLabel
              control={
                <Switch
                  checked={empty}
                  onChange={(_, checked) =>
                    updateForm(
                      "inventory",
                      pond.BinInventory.create({
                        ...form.inventory,
                        empty: checked
                      })
                    )
                  }
                  name="empty"
                />
              }
              disabled={!canEdit}
              label="Empty"
              labelPlacement="start"
            />
          </Grid>
        </Grid>
        {isCustomInventory && (
          <RadioGroup
            row
            value={storageType}
            onChange={(_, value) => {
              let storageType = parseFloat(value) as pond.BinStorage;
              setStorageType(storageType);
              if (storageType === pond.BinStorage.BIN_STORAGE_FERTILIZER) {
                formExtension.bushelsPerTonne = "";
                formExtension.grainBushels = (
                  parseFloat(formExtension.grainBushels) * 35.239
                ).toFixed(0);
              } else {
                formExtension.grainBushels = (
                  parseFloat(formExtension.grainBushels) / 35.239
                ).toFixed(0);
              }
            }}>
            <FormControlLabel
              value={pond.BinStorage.BIN_STORAGE_UNSUPPORTED_GRAIN}
              control={<Radio />}
              label={"Grain"}
            />
            <FormControlLabel
              value={pond.BinStorage.BIN_STORAGE_FERTILIZER}
              control={<Radio />}
              label={"Fertilizer"}
            />
          </RadioGroup>
        )}
        <Accordion className={classes.bottomSpacing}>
          <AccordionSummary expandIcon={<ExpandMore />}>
            <Grid
              width={"100%"}
              container
              direction="row"
              alignContent="center"
              alignItems="center"
              justifyContent="space-between">
              <Grid>
                <Typography>Inventory Control</Typography>
              </Grid>
              <Grid>
                <Typography>{inventoryControlLabel(inventoryControl)}</Typography>
              </Grid>
            </Grid>
          </AccordionSummary>
          <AccordionDetails>
            <RadioGroup
              row
              value={inventoryControl}
              onChange={(_, value) => {
                setInventoryControl(+value);
              }}>
              <FormControlLabel
                value={pond.BinInventoryControl.BIN_INVENTORY_CONTROL_MANUAL}
                control={<Radio />}
                label={"Manual"}
              />
              <FormControlLabel
                value={pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC}
                control={<Radio />}
                label={"Auto (Cable)"}
              />
              <FormControlLabel
                value={pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC_LIDAR}
                control={<Radio />}
                label={"Auto (Lidar)"}
              />
              <FormControlLabel
                value={pond.BinInventoryControl.BIN_INVENTORY_CONTROL_HYBRID_LIDAR}
                control={<Radio />}
                label={"Hybrid (Lidar)"}
              />
              {user.hasFeature("libra-cart") &&
                <FormControlLabel
                  value={pond.BinInventoryControl.BIN_INVENTORY_CONTROL_LIBRACART}
                  control={<Radio />}
                  label={"Auto (Libra Cart)"}
                />
              }
            </RadioGroup>
          </AccordionDetails>
          {inventoryControl === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC &&
            !autoTopNode && (
              <Box marginX={2} marginBottom={2}>
                <Typography variant="caption">
                  Auto Top Node must be activated for automatic inventory control
                </Typography>
              </Box>
            )}
          {inventoryControl === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_HYBRID_LIDAR && (
            <Box marginX={2} marginBottom={2}>
              <Typography variant="caption">
                Hybrid control will submit a transaction that must be approved by the user before inventory is changed
              </Typography>
            </Box>
          )}
          {(inventoryControl === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC_LIDAR ||
           inventoryControl === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_HYBRID_LIDAR) &&
            <Box width="100%" padding={2}>
              <TextField 
                fullWidth
                variant="outlined"
                label="Auto Threshold Percent"
                helperText="Fill percent threshold that must be crossed to affect inventory"
                InputProps={{
                  endAdornment: (
                    <InputAdornment position="end">
                      %
                    </InputAdornment>
                  )
                }}
                type="number"
                value={autoFillThreshold}
                onChange={e => {
                  setAutoFillThreshold(+e.target.value)
                }}
              />
            </Box>
          }
          {inventoryControl === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_LIBRACART &&
            <Box width="100%" padding={2}>
              <SearchSelect 
                label="Libra Cart Destination"
                selected={lcDestination}
                changeSelection={option => {
                  let newForm = form;
                  newForm.libracartDestinationKey = option?.value;
                  setForm(newForm);
                  setlcDestination(option ? option : null);
                }}
                disabled={!canEdit}
                options={lcDestinationOptions}
              />
              <Typography variant="caption">
                The linked bins inventory will be adjusted When the Libra Cart Destination data is synced every 6 hours
              </Typography>
            </Box>
          }
        </Accordion>
        {empty ? (
          <Box marginTop={3} display="flex" flexDirection="column" alignItems="center">
            <Typography variant="subtitle1" color="textPrimary">
              Bin is currently empty
            </Typography>
            <Typography variant="body1" color="textSecondary">
              Inventory settings will be ignored
            </Typography>
            <Typography variant="body2" color="textSecondary">
              We may ask for your inventory again in the future
            </Typography>
          </Box>
        ) : (
          <Box>
            {/* <Typography variant="subtitle1" color="textSecondary" gutterBottom>
              {isCustom ? "Custom" : "Grain"}
            </Typography> */}
            <Box>
              {!isCustomInventory && (
                <Box className={classes.bottomSpacing}>
                  <SearchSelect
                    label="Type"
                    selected={grainType}
                    changeSelection={option => {
                      let newGrainType = option
                        ? pond.Grain[option.value as keyof typeof pond.Grain]
                        : pond.Grain.GRAIN_INVALID;
                      updateForm(
                        "inventory",
                        pond.BinInventory.create({
                          ...form.inventory,
                          grainType: newGrainType,
                          bushelsPerTonne: GrainDescriber(newGrainType).bushelsPerTonne
                        })
                      );
                      //doesn't need to update the form extension to display the bushels per tonne as it is not changeable for the supported grain
                      //and is reset whenever the user switches between custom or not
                      updateFormExtension("grainType", option);
                    }}
                    group
                    disabled={!canEdit}
                    options={grainOptions}
                  />
                </Box>
              )}
              {isCustomInventory ? (
                <React.Fragment>
                  <TextField
                    label="Type"
                    value={customTypeName}
                    type="text"
                    onChange={event => {
                      updateForm(
                        "inventory",
                        pond.BinInventory.create({
                          ...form.inventory,
                          customTypeName: event.target.value
                        })
                      );
                      updateFormExtension("customTypeName", event.target.value);
                    }}
                    fullWidth
                    variant="outlined"
                    className={classes.bottomSpacing}
                  />
                  {storageType !== pond.BinStorage.BIN_STORAGE_FERTILIZER && (
                    <TextField
                      label="Bushels Per Tonne"
                      value={bushPerTonne}
                      type="number"
                      onChange={event => {
                        updateForm(
                          "inventory",
                          pond.BinInventory.create({
                            ...form.inventory,
                            bushelsPerTonne: +event.target.value
                          })
                        );
                        updateFormExtension("bushelsPerTonne", event.target.value);
                      }}
                      fullWidth
                      variant="outlined"
                      className={classes.bottomSpacing}
                    />
                  )}
                </React.Fragment>
              ) : (
                <TextField
                  label="Grain Variant"
                  value={grainSubtype}
                  type="text"
                  onChange={event => {
                    updateForm(
                      "inventory",
                      pond.BinInventory.create({
                        ...form.inventory,
                        grainSubtype: event.target.value
                      })
                    );
                    updateFormExtension("grainSubtype", event.target.value);
                  }}
                  fullWidth
                  variant="outlined"
                  disabled={!grainType}
                  className={classes.bottomSpacing}
                />
              )}
              {getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_BUSHELS ||
              storageType === pond.BinStorage.BIN_STORAGE_FERTILIZER ||
              formExtension.bushelsPerTonne === "0" ||
              formExtension.bushelsPerTonne === "" ? (
                <TextField
                  label="Amount"
                  value={binQuantity}
                  type="number"
                  onChange={event => {
                    let capacity =
                      bin?.settings.storage === pond.BinStorage.BIN_STORAGE_FERTILIZER
                        ? +inputCapacity * 35.239
                        : inputCapacity;
                    let value = event?.target.value;
                    let v =
                      value === ""
                        ? 0
                        : isNaN(parseFloat(value))
                        ? 0
                        : parseFloat(value) >= +capacity
                        ? +capacity
                        : parseFloat(value) <= 0
                        ? 0
                        : parseFloat(value);
                    if (bin?.storage() === pond.BinStorage.BIN_STORAGE_FERTILIZER && v) {
                      v = v / 35.239;
                    }
                    //setNewGrainQuantity(v);
                    updateForm(
                      "inventory",
                      pond.BinInventory.create({
                        ...form.inventory,
                        grainBushels: v
                      })
                    );
                    updateFormExtension("grainBushels", value);
                  }}
                  InputProps={{
                    endAdornment: (
                      <InputAdornment position="end">
                        {storageType === pond.BinStorage.BIN_STORAGE_FERTILIZER
                          ? "Litres"
                          : "Bushels"}
                      </InputAdornment>
                    )
                  }}
                  fullWidth
                  variant="outlined"
                  disabled={
                    !canEdit ||
                    inventoryControl === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC
                  }
                  className={classes.bottomSpacing}
                />
              ) : (
                <TextField
                  label="Amount"
                  value={grainTonnes}
                  type="number"
                  onChange={event => {
                    let newWeight = event.target.value;
                    const bushelsPerTonne = +formExtension.bushelsPerTonne;

                    //get the bushel amount
                    if (!isNaN(+newWeight) && !isNaN(+bushelsPerTonne)) {
                      let newBushels = Math.round(+newWeight * +bushelsPerTonne * 100) / 100;
                      updateForm(
                        "inventory",
                        pond.BinInventory.create({
                          ...form.inventory,
                          grainBushels: newBushels
                        })
                      );
                      //updateFormExtension("grainBushels", newBushels.toString())
                      updateFormExtension("grainTonnes", newWeight);
                    }
                  }}
                  fullWidth
                  variant="outlined"
                  disabled={!canEdit}
                  InputProps={{
                    endAdornment: <InputAdornment position="end">mT</InputAdornment>
                  }}
                  className={classes.bottomSpacing}
                />
              )}
              {!isCustomInventory && (
                <SearchSelect
                  label="Use"
                  selected={grainUse}
                  changeSelection={option => {
                    let grainUse = option
                      ? pond.GrainUse[option.value as keyof typeof pond.GrainUse]
                      : pond.GrainUse.GRAIN_USE_UNKNOWN;
                    updateForm(
                      "inventory",
                      pond.BinInventory.create({
                        ...form.inventory,
                        grainUse: grainUse
                      })
                    );
                    updateFormExtension("grainUse", option);
                  }}
                  group
                  disabled={!canEdit}
                  options={grainUseOptions}
                />
              )}
            </Box>

            {/*<Box marginTop={1}>
              <DateTimePicker
                
                disabled={!canEdit}
                renderInput={props => <TextField {...props} helperText=""  />}
                value={time}
                onChange={date =>
                  updateForm(
                    "inventory",
                    pond.BinInventory.create({
                      ...form.inventory,
                      initialTimestamp: moment(date ?? undefined).format()
                    })
                  )
                }
                disableFuture
                label="Start Time"
              />
            </Box>*/}
          </Box>
        )}
      </Box>
    );
  };

  const fanPicker = () => {
    return (
      <FanPicker
        updateFan={(fanId: number) => {
          if (fanId !== undefined) {
            //set the fan id in the bin settings form
            form.fanId = fanId;
            //remove the old fan from the bin
            form.fan = null;
          }
        }}
        fanID={form.fanId}
        useCardView
      />
    );
  };

  const getBushels = (height: number, diameter: number): number => {
    let d = diameter * 3.281;
    let h = height * 3.281;
    return 0.628 * (d * d) * h;
  };

  /**
   * takes in the dimensions of the bin to calculate its bushel capacity
   * @param diameter
   * @param topConeHeight
   * @param sidewallHeight
   * @param hopperHeight
   * @returns the bushel capacity of the bin with given dimensions
   */
  const advancedGrainCalc = (
    diameter: number,
    topConeHeight: number,
    sidewallHeight: number,
    hopperHeight?: number
  ) => {
    //if the units are in meters will need to convert to feet
    let tcH = topConeHeight;
    let sH = sidewallHeight;
    let hH = hopperHeight ?? 0;
    let d = diameter;
    if (getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_METERS) {
      tcH = tcH * 3.281;
      sH = sH * 3.281;
      hH = hH * 3.281;
      d = d * 3.281;
    }
    let topConeBushels = ConeVolume(d / 2, tcH) * conversionConstantFT;
    let sidewallBushels = CylinderVolume(d / 2, sH) * conversionConstantFT;
    let hopperBushels = ConeVolume(d / 2, hH ?? 0) * conversionConstantFT;

    return Math.round(topConeBushels + sidewallBushels + hopperBushels);
  };

  const generalForm = () => {
    const name = form?.name ?? "";
    const shape = form.specs ? form.specs.shape.valueOf() : "";
    const advanced = form.specs ? form.specs.useAdvanced : false;
    const roofAngle =
      form.specs && form.specs.advancedDimensions ? form.specs.advancedDimensions.roofAngle : 0;
    const hopperAngle =
      form.specs && form.specs.advancedDimensions ? form.specs.advancedDimensions.hopperAngle : 0;

    let height = formExtension.height;
    let topConeHeight = formExtension.topConeHeight;
    let sidewallHeight = formExtension.sidewallHeight;
    let hopperHeight = formExtension.hopperHeight;
    let diameter = formExtension.diameter;

    // if (getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_FEET) {
    //   diameterM = (Number(diameterM) * 3.28084).toFixed(2);
    //   heightM = (Number(heightM) * 3.28084).toFixed(2);
    // }
    return (
      <Box>
        <Box width={"100%"}>
          <FormControlLabel
            control={
              <Switch
                value={isCustomBin}
                checked={isCustomBin}
                title="Build Custom Bin"
                onClick={() => {
                  setIsCustomBin(!isCustomBin);
                }}
              />
            }
            label="Build Custom Bin"
            labelPlacement="start"
          />
        </Box>
        <Grid container direction="row" alignItems="center" alignContent="center">
          <Grid >
            <FormControlLabel
              control={
                <Checkbox
                  value={autoTopNode}
                  checked={autoTopNode}
                  onChange={(_, checked) => {
                    setAutoTopNode(checked);
                  }}
                />
              }
              label={"Automatic Top Node"}
            />
          </Grid>
          <Grid >
            <Tooltip
              title={
                <React.Fragment>
                  <Typography>
                    Will run every day using the Day/Night cycle of temperatures on each of the bins
                    cables to determine which nodes are in the grain as opposed to in the air and
                    update its interactions accordingly.
                  </Typography>
                  <Typography>
                    If a bin is determined to be empty it will remove the interactions on its
                    cables.
                  </Typography>
                </React.Fragment>
              }>
              <Info />
            </Tooltip>
          </Grid>
        </Grid>

        <Typography variant="subtitle2" align="center" color="primary" gutterBottom>
          Bin Information
        </Typography>
        <Typography variant="body1" align="center" gutterBottom>
          {/* {modelID !== 0
            ? getBinModel(modelID)?.Manufacturer + " " + getBinModel(modelID)?.Model
            : "Custom"} */}
        </Typography>
        <Box marginTop={1} marginBottom={1}>
          <TextField
            label="Name"
            fullWidth
            variant="outlined"
            value={name}
            disabled={!canEdit}
            onChange={e => updateForm("name", e.target.value)}
          />
        </Box>
        {isCustomBin ? (
          <Box>
            <Box marginTop={1} alignContent="center" justifyContent="center">
              <TextField
                label="Height"
                type="number"
                required
                value={height}
                disabled={!canEdit || advanced}
                onChange={event => {
                  let value = event?.target.value;
                  let d = diameter;
                  let valueM = value;
                  let dM = diameter;
                  if (getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_FEET) {
                    valueM = (Number(value) * 0.3048).toFixed(2);
                    dM = (Number(d) * 0.3048).toFixed(2);
                  }
                  setModelID(0);
                  updateForm(
                    "specs",
                    pond.BinSpecs.create({
                      ...form.specs,
                      modelId: 0,
                      heightCm:
                        valueM === ""
                          ? undefined
                          : isNaN(parseFloat(valueM))
                          ? 0
                          : parseFloat(valueM) * 100
                    })
                  );
                  updateFormExtension("height", value);
                  setInputCapacity(getBushels(Number(valueM), Number(dM)).toFixed(0));
                  //updateFormExtension("capacity", getBushels(Number(value), Number(d)).toFixed(0));
                }}
                InputProps={{
                  endAdornment: (
                    <InputAdornment position="end">
                      {getDistanceUnit() !== pond.DistanceUnit.DISTANCE_UNIT_FEET ? "m" : "ft"}
                    </InputAdornment>
                  )
                }}
                style={{ width: "59%" }}
                variant="outlined"
              />
              <FormControlLabel
                style={{ width: "38%", paddingTop: 5 }}
                control={
                  <Switch
                    disabled={!canEdit}
                    value={advanced}
                    checked={advanced}
                    title="Advanced Dimensions"
                    onChange={(_, checked) => {
                      updateForm(
                        "specs",
                        pond.BinSpecs.create({
                          ...form.specs,
                          useAdvanced: checked
                        })
                      );
                      if (checked) {
                        let ext = cloneDeep(formExtension);
                        let s = isNaN(parseFloat(sidewallHeight)) ? 0 : parseFloat(sidewallHeight);
                        let t = isNaN(parseFloat(topConeHeight)) ? 0 : parseFloat(topConeHeight);
                        let h = isNaN(parseFloat(hopperHeight)) ? 0 : parseFloat(hopperHeight);
                        //change the total height to use the section values
                        ext.height = (s + t + h).toFixed(2);
                        //update the capacity with those dimensions
                        let diameter = isNaN(parseFloat(ext.diameter))
                          ? 0
                          : parseFloat(ext.diameter);
                        let bushelCap = advancedGrainCalc(diameter, t, s, h);

                        setInputCapacity(bushelCap.toFixed(0));
                        ext.capacity = bushelCap.toFixed(0);
                        setFormExtension(ext);
                      }
                    }}
                  />
                }
                label="Advanced"
                labelPlacement="start"
              />
            </Box>
            <Collapse in={advanced}>
              <Box marginTop={1}>
                <Grid container spacing={1}>
                  <Grid size={{ xs: 8 }}>
                    <TextField
                      label="Top Cone Height"
                      type="number"
                      value={topConeHeight}
                      disabled={!canEdit}
                      onChange={event => {
                        let value = event?.target.value;
                        let valueM = value;
                        setModelID(0);
                        if (getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_FEET) {
                          valueM = (Number(value) * 0.3048).toFixed(2);
                        }
                        let coneCM =
                          valueM === ""
                            ? undefined
                            : isNaN(parseFloat(valueM))
                            ? 0
                            : parseFloat(valueM) * 100;

                        //Calculate the roof angle
                        let dCm = form.specs?.diameterCm ?? 0; //get the diameter
                        let angle = RadiansToDegrees(Math.atan((coneCM ?? 0) / (dCm / 2))); //('arcTan(opposite / adjacent))' and convert to degrees
                        angle = Math.round(angle * 100) / 100; // round to 2 digits

                        let ext = cloneDeep(formExtension);
                        //calculate the total height from the parts
                        let s = isNaN(parseFloat(sidewallHeight)) ? 0 : parseFloat(sidewallHeight);
                        let t = isNaN(parseFloat(value)) ? 0 : parseFloat(value);
                        let h = isNaN(parseFloat(hopperHeight)) ? 0 : parseFloat(hopperHeight);

                        //trigger the advanced calculation for capacity
                        let diameter = isNaN(parseFloat(ext.diameter))
                          ? 0
                          : parseFloat(ext.diameter);
                        let bushelCap = advancedGrainCalc(diameter, t, s, h);

                        setInputCapacity(bushelCap.toFixed(0));
                        ext.capacity = bushelCap.toFixed(0);
                        ext.topConeHeight = value; //set the new top cone heigh
                        ext.height = (s + t + h).toFixed(2); // set the new total height

                        //update the extensions with the new values
                        setFormExtension({ ...ext });

                        //need to get the total height in cm
                        let totalHeightCM = s + t + h; //the total height in the users units
                        if(getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_FEET){
                          totalHeightCM = totalHeightCM * 30.48 //convert from feet to cm
                        }else{
                          totalHeightCM = totalHeightCM * 100 //convert from m to cm
                        }

                        //update the form with the new specs
                        updateForm(
                          "specs",
                          pond.BinSpecs.create({
                            ...form.specs,
                            modelId: 0,
                            heightCm: Math.round(totalHeightCM),
                            advancedDimensions: pond.BinAdvancedDimensions.create({
                              ...form.specs?.advancedDimensions,
                              topConeHeight: coneCM,
                              roofAngle: angle
                            })
                          })
                        );
                      }}
                      InputProps={{
                        endAdornment: (
                          <InputAdornment position="end">
                            {getDistanceUnit() !== pond.DistanceUnit.DISTANCE_UNIT_FEET
                              ? "m"
                              : "ft"}
                          </InputAdornment>
                        )
                      }}
                      variant="outlined"
                    />
                  </Grid>
                  <Grid size={{ xs: 4 }}>
                    <TextField
                      label="Roof Angle"
                      type="number"
                      value={roofAngle}
                      disabled={!canEdit}
                      onChange={event => {
                        let value = event.target.value;
                        let angle =
                          value === ""
                            ? undefined
                            : isNaN(parseFloat(value))
                            ? 0
                            : parseFloat(value);
                        let d = form.specs?.diameterCm ?? 0; //get the diameter
                        //calculate the new cone height for the roof angle
                        let coneCM = TriangleOppositeLength(d / 2, angle ?? 0);
                        let newConeHeight =
                          getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_FEET
                            ? (coneCM / 30.48).toFixed(2)
                            : (coneCM / 100).toFixed(2);

                        let ext = cloneDeep(formExtension);
                        let s = isNaN(parseFloat(sidewallHeight)) ? 0 : parseFloat(sidewallHeight);
                        let t = isNaN(parseFloat(newConeHeight)) ? 0 : parseFloat(newConeHeight);
                        let h = isNaN(parseFloat(hopperHeight)) ? 0 : parseFloat(hopperHeight);

                        //trigger the advanced calculation for capacity
                        let diameter = isNaN(parseFloat(ext.diameter))
                          ? 0
                          : parseFloat(ext.diameter);
                        let bushelCap = advancedGrainCalc(diameter, t, s, h);

                        setInputCapacity(bushelCap.toFixed(0));
                        ext.capacity = bushelCap.toFixed(0);
                        ext.topConeHeight = newConeHeight;
                        ext.height = (s + t + h).toFixed(2)
                        
                        setFormExtension(ext);
                        
                        //need to get the total height in cm
                        let totalHeightCM = s + t + h; //the total height in the users units
                        if(getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_FEET){
                          totalHeightCM = totalHeightCM * 30.48 //convert from feet to cm
                        }else{
                          totalHeightCM = totalHeightCM * 100 //convert from m to cm
                        }

                        setModelID(0);
                        //update the form with the new specs
                        updateForm(
                          "specs",
                          pond.BinSpecs.create({
                            ...form.specs,
                            modelId: 0,
                            heightCm: Math.round(totalHeightCM),
                            advancedDimensions: pond.BinAdvancedDimensions.create({
                              ...form.specs?.advancedDimensions,
                              roofAngle: angle ?? 0,
                              topConeHeight: coneCM
                            })
                          })
                        );
                      }}
                      InputProps={{
                        endAdornment: <InputAdornment position="end">°</InputAdornment>
                      }}
                      variant="outlined"
                    />
                  </Grid>
                  <Grid size={{ xs: 8 }}>
                    <TextField
                      label="Sidewall Height"
                      type="number"
                      value={sidewallHeight}
                      disabled={!canEdit}
                      onChange={event => {
                        let value = event?.target.value;
                        let valueM = value;
                        if (getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_FEET) {
                          valueM = (Number(value) * 0.3048).toFixed(2);
                        }
                        let ext = cloneDeep(formExtension);
                        let s = isNaN(parseFloat(value)) ? 0 : parseFloat(value);
                        let t = isNaN(parseFloat(topConeHeight)) ? 0 : parseFloat(topConeHeight);
                        let h = isNaN(parseFloat(hopperHeight)) ? 0 : parseFloat(hopperHeight);

                        //trigger the advanced calculation for capacity
                        let diameter = isNaN(parseFloat(ext.diameter))
                          ? 0
                          : parseFloat(ext.diameter);
                        let bushelCap = advancedGrainCalc(diameter, t, s, h);

                        setInputCapacity(bushelCap.toFixed(0));
                        ext.capacity = bushelCap.toFixed(0);
                        ext.sidewallHeight = value;
                        ext.height = (s + t + h).toFixed(2);

                        setFormExtension({ ...ext });

                        setModelID(0);

                        //need to get the total height in cm
                        let totalHeightCM = s + t + h; //the total height in the users units
                        if(getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_FEET){
                          totalHeightCM = totalHeightCM * 30.48 //convert from feet to cm
                        }else{
                          totalHeightCM = totalHeightCM * 100 //convert from m to cm
                        }

                        updateForm(
                          "specs",
                          pond.BinSpecs.create({
                            ...form.specs,
                            modelId: 0,
                            heightCm: Math.round(totalHeightCM),
                            advancedDimensions: pond.BinAdvancedDimensions.create({
                              ...form.specs?.advancedDimensions,
                              sidewallHeight:
                                valueM === ""
                                  ? undefined
                                  : isNaN(parseFloat(valueM))
                                  ? 0
                                  : parseFloat(valueM) * 100
                            })
                          })
                        );
                      }}
                      InputProps={{
                        endAdornment: (
                          <InputAdornment position="end">
                            {getDistanceUnit() !== pond.DistanceUnit.DISTANCE_UNIT_FEET
                              ? "m"
                              : "ft"}
                          </InputAdornment>
                        )
                      }}
                      variant="outlined"
                    />
                  </Grid>
                  {shape === pond.BinShape.BIN_SHAPE_HOPPER_BOTTOM && (
                    <React.Fragment>
                      <Grid size={{ xs: 4 }}>
                        <TextField
                          label="Hopper Angle"
                          type="number"
                          value={hopperAngle}
                          disabled={!canEdit}
                          onChange={event => {
                            let value = event.target.value;
                            let angle =
                              value === ""
                                ? undefined
                                : isNaN(parseFloat(value))
                                ? 0
                                : parseFloat(value);
                            let d = form.specs?.diameterCm ?? 0; //get the diameter
                            //calculate the new cone height for the roof angle
                            let coneCM = TriangleOppositeLength(d / 2, angle ?? 0);

                            let newHopperHeight =
                              getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_FEET
                                ? (coneCM / 30.48).toFixed(2)
                                : (coneCM / 100).toFixed(2);

                            let ext = cloneDeep(formExtension);
                            let s = isNaN(parseFloat(sidewallHeight))
                              ? 0
                              : parseFloat(sidewallHeight);
                            let t = isNaN(parseFloat(topConeHeight))
                              ? 0
                              : parseFloat(topConeHeight);
                            let h = isNaN(parseFloat(newHopperHeight))
                              ? 0
                              : parseFloat(newHopperHeight);

                            //trigger the advanced calculation for capacity
                            let diameter = isNaN(parseFloat(ext.diameter))
                              ? 0
                              : parseFloat(ext.diameter);
                            let bushelCap = advancedGrainCalc(diameter, t, s, h);

                            setInputCapacity(bushelCap.toFixed(0));
                            ext.capacity = bushelCap.toFixed(0);
                            ext.hopperHeight = newHopperHeight;
                            ext.height = (s + t + h).toFixed(2);

                            setFormExtension(ext);
                            //update the form with the new specs
                            setModelID(0);
                            updateForm(
                              "specs",
                              pond.BinSpecs.create({
                                ...form.specs,
                                modelId: 0,
                                advancedDimensions: pond.BinAdvancedDimensions.create({
                                  ...form.specs?.advancedDimensions,
                                  hopperAngle: angle ?? 0,
                                  hopperHeight: coneCM
                                })
                              })
                            );
                            //need to update the total height with the new height calculated from the angle
                          }}
                          InputProps={{
                            endAdornment: <InputAdornment position="end">°</InputAdornment>
                          }}
                          variant="outlined"
                        />
                      </Grid>
                      <Grid size={{ xs: 8 }}>
                        <TextField
                          label="Hopper Height"
                          type="number"
                          value={hopperHeight}
                          disabled={!canEdit}
                          onChange={event => {
                            let value = event?.target.value;
                            let valueM = value;
                            if (getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_FEET) {
                              valueM = (Number(value) * 0.3048).toFixed(2);
                            }

                            let hopperHeightCM =
                              valueM === ""
                                ? undefined
                                : isNaN(parseFloat(valueM))
                                ? 0
                                : parseFloat(valueM) * 100;

                            //Calculate the hopper angle
                            let d = form.specs?.diameterCm ?? 0; //get the diameter
                            let angle = RadiansToDegrees(
                              Math.atan((hopperHeightCM ?? 0) / (d / 2))
                            ); //('arcTan(opposite / adjacent))' and convert to degrees
                            angle = Math.round(angle * 100) / 100; // round to 2 digits

                            setModelID(0);
                            updateForm(
                              "specs",
                              pond.BinSpecs.create({
                                ...form.specs,
                                modelId: 0,
                                advancedDimensions: pond.BinAdvancedDimensions.create({
                                  ...form.specs?.advancedDimensions,
                                  hopperHeight: hopperHeightCM,
                                  hopperAngle: angle
                                })
                              })
                            );
                            let ext = cloneDeep(formExtension);
                            let s = isNaN(parseFloat(sidewallHeight))
                              ? 0
                              : parseFloat(sidewallHeight);
                            let t = isNaN(parseFloat(topConeHeight))
                              ? 0
                              : parseFloat(topConeHeight);
                            let h = isNaN(parseFloat(value)) ? 0 : parseFloat(value);

                            //trigger the advanced calculation for capacity
                            let diameter = isNaN(parseFloat(ext.diameter))
                              ? 0
                              : parseFloat(ext.diameter);
                            let bushelCap = advancedGrainCalc(diameter, t, s, h);

                            setInputCapacity(bushelCap.toFixed(0));
                            ext.capacity = bushelCap.toFixed(0);
                            ext.hopperHeight = value;
                            ext.height = (s + t + h).toFixed(2);

                            setFormExtension({ ...ext });
                          }}
                          InputProps={{
                            endAdornment: (
                              <InputAdornment position="end">
                                {getDistanceUnit() !== pond.DistanceUnit.DISTANCE_UNIT_FEET
                                  ? "m"
                                  : "ft"}
                              </InputAdornment>
                            )
                          }}
                          variant="outlined"
                        />
                      </Grid>
                    </React.Fragment>
                  )}
                </Grid>
              </Box>
            </Collapse>

            <Box marginTop={1}>
              <TextField
                label="Diameter"
                type="number"
                required
                value={diameter}
                disabled={!canEdit}
                onChange={event => {
                  let value = event?.target.value;
                  let h = height;
                  let valueM = value;
                  let hM = height;
                  if (getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_FEET) {
                    valueM = (Number(value) * 0.3048).toFixed(2);
                    hM = (Number(h) * 0.3048).toFixed(2);
                  }

                  let diameterCM =
                    valueM === ""
                      ? undefined
                      : isNaN(parseFloat(valueM))
                      ? 0
                      : parseFloat(valueM) * 100;

                  //adjust the angles using the new diameter
                  let d = diameterCM ?? 0; //get the diameter
                  //Calculate the hopper angle
                  let hopperAngle = RadiansToDegrees(
                    Math.atan((form.specs?.advancedDimensions?.hopperHeight ?? 0) / (d / 2))
                  ); //('arcTan(opposite / adjacent))' and convert to degrees
                  hopperAngle = Math.round(hopperAngle * 100) / 100; // round to 2 digits
                  //Calculate the roof angle
                  let roofAngle = RadiansToDegrees(
                    Math.atan((form.specs?.advancedDimensions?.topConeHeight ?? 0) / (d / 2))
                  ); //('arcTan(opposite / adjacent))' and convert to degrees
                  roofAngle = Math.round(roofAngle * 100) / 100; // round to 2 digits

                  setModelID(0);
                  updateForm(
                    "specs",
                    pond.BinSpecs.create({
                      ...form.specs,
                      modelId: 0,
                      diameterCm: diameterCM,
                      advancedDimensions: pond.BinAdvancedDimensions.create({
                        ...form.specs?.advancedDimensions,
                        hopperAngle: hopperAngle,
                        roofAngle: roofAngle
                      })
                    })
                  );

                  let ext = cloneDeep(formExtension);
                  ext.diameter = value;

                  if (advanced) {
                    //advanced capacity calc using the 3 sections
                  } else {
                    //basic capcity calc using only height and diameter
                    setInputCapacity(getBushels(Number(hM), Number(valueM)).toFixed(0));
                  }
                  setFormExtension({ ...ext });
                }}
                InputProps={{
                  endAdornment: (
                    <InputAdornment position="end">
                      {getDistanceUnit() !== pond.DistanceUnit.DISTANCE_UNIT_FEET ? "m" : "ft"}
                    </InputAdornment>
                  )
                }}
                fullWidth
                variant="outlined"
              />
            </Box>
            <Box marginTop={1}>
              <TextField
                label="Capacity"
                type="number"
                required
                value={inputCapacity}
                disabled={!canEdit}
                onChange={event => {
                  let value = event?.target.value;
                  value = isNaN(parseFloat(value)) ? "" : parseFloat(value) >= 0 ? value : "";
                  setInputCapacity(value);
                  updateForm(
                    "specs",
                    pond.BinSpecs.create({
                      ...form.specs,
                      bushelCapacity:
                        value === "" ? undefined : isNaN(parseFloat(value)) ? 0 : parseFloat(value)
                    })
                  );
                  updateFormExtension("capacity", value);
                }}
                InputProps={{
                  endAdornment: <InputAdornment position="end">bushels</InputAdornment>
                }}
                fullWidth
                variant="outlined"
              />
            </Box>

            <Box marginTop={2}>
              <FormControl component="fieldset" variant="outlined" fullWidth disabled={!canEdit}>
                {/* <OutlinedBox label={<FormLabel component="legend">Shape</FormLabel>} padding={1}> */}
                  <FormLabel component="legend">Shape</FormLabel>
                  <RadioGroup
                    aria-label="bin shape"
                    name="binShape"
                    value={shape}
                    onChange={(_, value) => {
                      //if user changed from hopper to flat bottom and they are using advanced dimensions
                      if (parseInt(value) === pond.BinShape.BIN_SHAPE_FLAT_BOTTOM && advanced) {
                        let ext = cloneDeep(formExtension);
                        //set the hopper measurements (height/angle) to be 0
                        ext.hopperHeight = "0";

                        //re-calc the total height for the extension, the settings will be done upon saving the bin
                        let s = isNaN(parseFloat(sidewallHeight)) ? 0 : parseFloat(sidewallHeight);
                        let t = isNaN(parseFloat(topConeHeight)) ? 0 : parseFloat(topConeHeight);
                        ext.height = (s + t).toFixed(2);

                        //re-calc the capacity
                        let diameter = isNaN(parseFloat(ext.diameter))
                          ? 0
                          : parseFloat(ext.diameter);
                        let bushelCap = advancedGrainCalc(diameter, t, s);
                        setInputCapacity(bushelCap.toFixed(0));
                        ext.capacity = bushelCap.toFixed(0);

                        //update extension with new values
                        setFormExtension(ext);
                      }

                      updateForm(
                        "specs",
                        pond.BinSpecs.create({
                          ...form.specs,
                          shape: parseInt(value),
                          advancedDimensions: pond.BinAdvancedDimensions.create({
                            ...form.specs?.advancedDimensions,
                            hopperAngle: 0,
                            hopperHeight: 0
                          })
                        })
                      );
                    }}>
                    {GetBinShapeDescribers()
                      .filter(s => s.key !== pond.BinShape.BIN_SHAPE_UNKNOWN)
                      .map(s => (
                        <FormControlLabel
                          key={s.key}
                          value={s.key}
                          control={<Radio />}
                          label={s.label}
                        />
                      ))}
                  </RadioGroup>
                {/* </OutlinedBox> */}
                <FormHelperText>Aeration effectiveness varies with bin shape</FormHelperText>
              </FormControl>
            </Box>
          </Box>
        ) : (
          <Box>
            <BinSelector
              vertical
              optionsChanged={options => {
                let ops: Option[] = [];
                options.forEach(o => {
                  ops.push({
                    label: o.Manufacturer + " - " + o.Model + " - " + o.Bottom,
                    value: o
                  });
                });
                setBinModelOptions(ops);
              }}
            />
            <Box marginTop={1}>
              <SearchSelect
                options={binModelOps}
                selected={selectedBinModel}
                label="Select Bin Model"
                changeSelection={selected => {
                  if (selected) {
                    setSelectedBinModel(selected);
                    let jsonBin = selected.value;
                    setModelID(jsonBin.ID);
                    let bushelCap = 0;
                    //need to set all the form (form is a bin settings object) data according to the bin that was selected
                    if (form.specs) {
                      //json bins lengths are in feet so for the data stored in the backend need to convert it to cm

                      let hopperHeightFt = TriangleOppositeLength(
                        jsonBin.Diameter / 2,
                        jsonBin.HopperAngle
                      );

                      // bushelCap = advancedGrainCalc(jsonBin.Diameter, jsonBin.Peak - jsonBin.Sidewall, jsonBin.Sidewall, hopperHeightFt)
                      // console.log(bushelCap)

                      let topConeBushels =
                        ConeVolume(jsonBin.Diameter / 2, jsonBin.Peak - jsonBin.Sidewall) *
                        conversionConstantFT;
                      let cylinderBushels =
                        CylinderVolume(jsonBin.Diameter / 2, jsonBin.Sidewall) *
                        conversionConstantFT;
                      let hopperBushels =
                        ConeVolume(jsonBin.Diameter / 2, hopperHeightFt) * conversionConstantFT;
                      bushelCap = topConeBushels + cylinderBushels + hopperBushels;

                      //set all the values that would be stored in the backend in bin settings
                      updateForm(
                        "specs",
                        pond.BinSpecs.create({
                          ...form.specs,
                          bushelCapacity: Math.round(bushelCap),
                          heightCm:
                            (jsonBin.Peak +
                              TriangleOppositeLength(jsonBin.Diameter / 2, jsonBin.HopperAngle)) *
                            30.48,
                          diameterCm: jsonBin.Diameter * 30.48,
                          advancedDimensions: pond.BinAdvancedDimensions.create({
                            sidewallHeight: jsonBin.Sidewall * 30.48,
                            topConeHeight: (jsonBin.Peak - jsonBin.Sidewall) * 30.48,
                            hopperHeight: hopperHeightFt * 30.48,
                            roofAngle: jsonBin.RoofAngle,
                            hopperAngle: jsonBin.HopperAngle
                          }),
                          modelId: jsonBin.ID,
                          shape:
                            jsonBin.Bottom === "Hopper Bottom"
                              ? pond.BinShape.BIN_SHAPE_HOPPER_BOTTOM
                              : pond.BinShape.BIN_SHAPE_FLAT_BOTTOM
                        })
                      );
                    }

                    //set the form extensions values that are displayed to the user
                    let hopperHeight = TriangleOppositeLength(
                      jsonBin.Diameter / 2,
                      jsonBin.HopperAngle
                    );

                    let ext = cloneDeep(formExtension);
                    ext.capacity = bushelCap.toFixed(0);
                    setInputCapacity(bushelCap.toFixed(0));

                    //the dimensions for the correct unit defined by user settings
                    let userHeight = jsonBin.Peak + hopperHeight;
                    let userTopCone = jsonBin.Peak - jsonBin.Sidewall;
                    let userSidewall = jsonBin.Sidewall;
                    let userHopperHeight = hopperHeight;
                    let userDiameter = jsonBin.Diameter;
                    //since the jsone data is in feet just check if we need to make it in meters
                    if (getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_METERS) {
                      userHeight = userHeight / 3.281;
                      userDiameter = userDiameter / 3.281;
                      userTopCone = userTopCone / 3.281;
                      userSidewall = userSidewall / 3.281;
                      userHopperHeight = userHopperHeight / 3.281;
                    }
                    ext.height = userHeight.toFixed(2);
                    ext.diameter = userDiameter.toFixed(2);
                    ext.topConeHeight = userTopCone.toFixed(2);
                    ext.sidewallHeight = userSidewall.toFixed(2);
                    ext.hopperHeight = userHopperHeight.toFixed(2);
                    setFormExtension({ ...ext });
                  }
                }}
              />
            </Box>
          </Box>
        )}
        {binYardForm()}
      </Box>
    );
  };

  const targetForm = () => {
    let highTemp = formExtension.highTemp;
    let lowTemp = formExtension.lowTemp;
    let tempTarget = formExtension.tempTarget;
    return (
      <Box>
        <Typography variant="subtitle2" align="center" color="primary" gutterBottom>
          Grain Targets
        </Typography>
        <Typography variant="body1" align="center" gutterBottom>
          Temperature
        </Typography>
        <Box marginTop={1}>
          <TextField
            label="Temperature Target"
            type="number"
            required
            error={
              +formExtension.lowTemp > +formExtension.tempTarget ||
              +formExtension.highTemp < +formExtension.tempTarget
            }
            helperText={
              +formExtension.lowTemp >= +formExtension.highTemp
                ? "Target must be between the lower and upper limits"
                : ""
            }
            value={tempTarget}
            disabled={!canEdit}
            onChange={event => {
              let value = event?.target.value;
              let valueC = value;
              if (getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT) {
                valueC = ((Number(value) - 32) * (5 / 9)).toFixed(2);
              }

              if (form.inventory) {
                form.inventory.targetTemperature = +valueC;
              }
              updateFormExtension("tempTarget", value);
            }}
            InputProps={{
              endAdornment: (
                <InputAdornment position="end">
                  {getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT
                    ? "F"
                    : "C"}
                </InputAdornment>
              )
            }}
            fullWidth
            variant="outlined"
          />
        </Box>
        <Box marginTop={1}>
          <Grid container spacing={1}>
            <Grid size={{ xs: 6 }}>
              <TextField
                label="Lower Limit"
                type="number"
                required
                error={+formExtension.lowTemp >= +formExtension.highTemp}
                helperText={
                  +formExtension.lowTemp >= +formExtension.highTemp
                    ? "Lower Limit must be less than the Upper Limit"
                    : ""
                }
                value={lowTemp}
                disabled={!canEdit}
                onChange={event => {
                  let value = event?.target.value;
                  let valueC = value;
                  if (getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT) {
                    valueC = ((Number(value) - 32) * (5 / 9)).toFixed(2);
                  }
                  setLowTempC(+valueC);
                  updateFormExtension("lowTemp", value);
                }}
                InputProps={{
                  endAdornment: (
                    <InputAdornment position="end">
                      {getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT
                        ? "F"
                        : "C"}
                    </InputAdornment>
                  )
                }}
                fullWidth
                variant="outlined"
              />
            </Grid>
            <Grid size={{ xs: 6 }}>
              <TextField
                label="Upper Limit"
                type="number"
                required
                error={+formExtension.highTemp <= +formExtension.lowTemp}
                helperText={
                  +formExtension.highTemp <= +formExtension.lowTemp
                    ? "Upper Limit must be greater than the Lower Limit"
                    : ""
                }
                value={highTemp}
                disabled={!canEdit}
                onChange={event => {
                  let value = event?.target.value;
                  let valueC = value;
                  if (getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT) {
                    valueC = ((Number(value) - 32) * (5 / 9)).toFixed(2);
                  }
                  setHighTempC(+valueC);
                  updateFormExtension("highTemp", value);
                }}
                InputProps={{
                  endAdornment: (
                    <InputAdornment position="end">
                      {getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT
                        ? "F"
                        : "C"}
                    </InputAdornment>
                  )
                }}
                fullWidth
                variant="outlined"
              />
            </Grid>
          </Grid>
        </Box>
        {!isCustomInventory && (
          <Box marginTop={1}>
            <Typography variant="body1" align="center" gutterBottom>
              Moisture
            </Typography>
            <Box marginTop={1}>
              <TextField
                label="Target EMC"
                InputProps={{
                  endAdornment: <InputAdornment position="end">% EMC</InputAdornment>
                }}
                fullWidth
                value={tMoistureString}
                disabled={!canEdit}
                variant="outlined"
                className={classes.bottomSpacing}
                error={isNaN(+tMoistureString) && tMoistureString !== ""}
                onChange={event => {
                  setTMoistureString(event.target.value);
                  if (!isNaN(+event.target.value)) {
                    setValidTarget(true);
                    updateForm(
                      "inventory",
                      pond.BinInventory.create({
                        ...form.inventory,
                        targetMoisture: +event.target.value
                      })
                    );
                  } else {
                    setValidTarget(false);
                  }
                }}
              />
            </Box>

            <Grid container spacing={1}>
              <Grid size={{ xs: 6 }}>
                <TextField
                  label="Initial"
                  InputProps={{
                    endAdornment: <InputAdornment position="end">% EMC</InputAdornment>
                  }}
                  fullWidth
                  value={inMoistureString}
                  variant="outlined"
                  disabled={!canEdit}
                  className={classes.bottomSpacing}
                  error={isNaN(+inMoistureString) && inMoistureString !== ""}
                  onChange={event => {
                    setInMoistureString(event.target.value);
                    if (!isNaN(+event.target.value)) {
                      setValidInitial(true);
                      updateForm(
                        "inventory",
                        pond.BinInventory.create({
                          ...form.inventory,
                          initialMoisture: +event.target.value
                        })
                      );
                    } else {
                      setValidInitial(false);
                    }
                  }}
                />
              </Grid>
              <Grid size={{ xs: 6 }} >
                <TextField
                  label="Acceptable Deviation"
                  fullWidth
                  InputProps={{
                    endAdornment: <InputAdornment position="end">% EMC</InputAdornment>
                  }}
                  value={moistureTargetDeviation}
                  variant="outlined"
                  disabled={!canEdit}
                  className={classes.bottomSpacing}
                  error={isNaN(+moistureTargetDeviation) && moistureTargetDeviation !== ""}
                  onChange={event => {
                    setMoistureTargetDeviation(event.target.value);
                    if (!isNaN(+event.target.value)) {
                      setValidDeviation(true);
                      updateForm(
                        "inventory",
                        pond.BinInventory.create({
                          ...form.inventory,
                          moistureTargetDeviation: +event.target.value
                        })
                      );
                    } else {
                      setValidDeviation(false);
                    }
                  }}
                />
              </Grid>
            </Grid>
          </Box>
        )}
      </Box>
    );
  };

  const stepContent = (step: number) => {
    switch (step) {
      case 1:
        return fanPicker();
      case 2:
        return inventoryForm();
      case 3:
        return targetForm();
      default:
        return generalForm();
    }
  };

  const content = () => {
    return (
      <DialogContent style={{ padding: 0 }}>
        <Box paddingX={2} paddingY={1}>
          {!isMobile && mode === "add" && stepper()}
          {stepContent(activeStep)}
        </Box>
      </DialogContent>
    );
  };

  const nextButton = () => {
    if (activeStep < 3) {
      return (
        <Button
          size="small"
          aria-label="next"
          onClick={stepNext}
          disabled={activeStep === steps.length - 1 || !stepComplete(activeStep)}>
          Next
          {theme.direction === "rtl" ? <KeyboardArrowLeft /> : <KeyboardArrowRight />}
        </Button>
      );
    }
    return (
      <Button size="small" aria-label="next" onClick={addBin}>
        Create
        {theme.direction === "rtl" ? <KeyboardArrowLeft /> : <KeyboardArrowRight />}
      </Button>
    );
  };

  const actions = () => {
    if (mode === "add" && isMobile) {
      return (
        <MobileStepper
          variant="dots"
          steps={steps.length}
          position="static"
          activeStep={activeStep}
          nextButton={nextButton()}
          backButton={
            <Button size="small" aria-label="back" onClick={stepBack} disabled={activeStep === 0}>
              {theme.direction === "rtl" ? <KeyboardArrowRight /> : <KeyboardArrowLeft />}
              Back
            </Button>
          }
        />
      );
    }
    return (
      <DialogActions>
        <Grid container justifyContent="space-between" direction="row" width="100%">
          <Grid size={{ xs: 5 }}>
            {mode === "add" ? (
              <Button
                disabled={activeStep === 0}
                onClick={stepBack}
                color="primary"
                aria-label="Back">
                Back
              </Button>
            ) : (
              canEdit && <DeleteButton onClick={() => setRemoveIsOpen(true)}>Delete</DeleteButton>
            )}
          </Grid>
          <Grid size={{ xs: 7 }} container justifyContent="flex-end">
            {mode === "add" ? (
              <React.Fragment>
                {!isMobile && (
                  <Button onClick={() => close()} color="primary" aria-label="Cancel">
                    Cancel
                  </Button>
                )}

                {activeStep === steps.length - 1 ? (
                  <Button
                    color="primary"
                    onClick={addBin}
                    disabled={!isFormValid()}
                    aria-label="Submit">
                    Submit
                  </Button>
                ) : (
                  <Button
                    color="primary"
                    onClick={stepNext}
                    disabled={activeStep === steps.length - 1 || !stepComplete(activeStep)}
                    aria-label="Next">
                    Next
                  </Button>
                )}
              </React.Fragment>
            ) : (
              !isMobile && (
                <React.Fragment>
                  <Button onClick={() => close()} color="primary" aria-label="Cancel">
                    Cancel
                  </Button>
                  <Button
                    onClick={updateBin}
                    color="primary"
                    disabled={!canEdit || !isFormValid()}
                    aria-label="Submit">
                    Submit
                  </Button>
                </React.Fragment>
              )
            )}
          </Grid>
        </Grid>
      </DialogActions>
    );
  };

  const removeConfirmation = () => {
    return (
      <ResponsiveDialog
        fullScreen={false}
        open={removeIsOpen}
        onClose={() => setRemoveIsOpen(false)}>
        <DialogTitle>Delete {bin?.name() ?? "Bin"}?</DialogTitle>
        <DialogContent>
          <DialogContentText>
            Anyone that has access to {bin?.name() ?? "this bin"} will no longer be able to see it.
          </DialogContentText>
        </DialogContent>
        <DialogActions>
          <Button onClick={() => setRemoveIsOpen(false)} color="primary">
            Cancel
          </Button>
          <Button onClick={removeBin} color="primary">
            Delete
          </Button>
        </DialogActions>
      </ResponsiveDialog>
    );
  };

  if ((!open || !initialized) && !removeIsOpen) {
    return null;
  }

  return (
    <ResponsiveDialog
      maxWidth={"xs"}
      fullWidth
      fullScreen={isMobile}
      open={open}
      scroll="paper"
      onClose={() => {
        onClose();
        setSelectedBinYard(null);
      }}>
      {title()}
      {content()}
      {actions()}
      {removeConfirmation()}
      {grainInventoryController()}
    </ResponsiveDialog>
  );
}
