import { Avatar, Box, Button, CardHeader, Checkbox, FormControlLabel, Grid2, Theme, Tooltip, Typography } from "@mui/material";
import { useMobile, useThemeType } from "hooks";
import VPDDark from "assets/products/Ag/dryingDark.png";
import VPDLight from "assets/products/Ag/dryingLight.png";
import TrendLight from "assets/products/Ag/trendingLight.png";
import TrendDark from "assets/products/Ag/trendingDark.png";
import { useEffect, useState } from "react";
import { makeStyles } from "@mui/styles";
import moment, { Moment } from "moment";
import { blue, orange, teal } from "@mui/material/colors";
import { GrainDryingPoint } from "charts/GrainDryingChart";
import { GrainCable } from "models/GrainCable";
import { Plenum } from "models/Plenum";
import BinGraphsVPD from "bin/graphs/BinGraphsVPD";
import { UnitMeasurement } from "models/UnitMeasurement";
import { Bin } from "models";
import { useBinAPI, useGlobalState } from "providers";
import TimeBar from "common/time/TimeBar";
import { GetDefaultDateRange } from "common/time/DateRange";
import { ZoomOut } from "@mui/icons-material";
import BinGraphsTrending from "bin/graphs/BinGraphsTrending";
import { DataPoint, TrendPoint } from "charts/TrendingChart";
import WaterLight from "assets/products/Ag/waterContentLight.png";
import WaterDark from "assets/products/Ag/waterContentDark.png";
import { Pressure } from "models/Pressure";
import { DataPoint as WaterPoint } from "charts/WaterLevelChart";
import BinWaterLevel from "bin/graphs/BinWaterLevel";
import { Controller } from "models/Controller";
import { pond } from "protobuf-ts/pond";

interface Props {
    cables: GrainCable[]
    plenums: Plenum[]
    componentDevices: Map<string, number>
    bin: Bin
}

const useStyles = makeStyles((theme: Theme) =>{ 
    return ({
      root: {
        display: "flex",
        flexDirection: "column",
        height: "100%",
        overflow: "hidden",
      },
      toolbar: {
        flexShrink: 0,
      },
      scrollContent: {
        flex: 1,
        minHeight: 0,
        overflowY: "auto",
      },
      card: {
        position: "relative",
        display: "flex",
        height: "100%",
        flexDirection: "column",
        overflow: "visible"
      },
      cardHeader: {
        padding: theme.spacing(1),
        paddingLeft: theme.spacing(2),
        marginRight: 10
      },
      avatarIcon: {
        width: 33,
        height: 33
      }
    })
  });

export default function BinAnalysisGraphs(props: Props){
    const {cables, plenums, componentDevices, bin} = props
    const themeType = useThemeType()
    const classes = useStyles()
    const [{user, as, showErrors}, dispatch] = useGlobalState()
    const isMobile = useMobile()
    const [xDomain, setXDomain] = useState<string[] | number[]>(["dataMin", "dataMax"]);
    const [zoomed, setZoomed] = useState(false);
    const [recentVPD, setRecentVPD] = useState<GrainDryingPoint | undefined>();
    const [loading, setLoading] = useState(false)
    // map using the component key and the unitmeasurements for that component
    const [compMeasurements, setCompMeasurements] = useState<Map<string, UnitMeasurement[]>>(
      new Map<string, UnitMeasurement[]>()
    );
    const binAPI = useBinAPI()
    const defaultDateRange = GetDefaultDateRange()
    const [startDate, setStartDate] = useState<Moment>(defaultDateRange.start);
    const [endDate, setEndDate] = useState<Moment>(defaultDateRange.end);
    const [recentPlenumTrend, setRecentPlenumTrend] = useState<TrendPoint | undefined>();
    const [recentCableTrend, setRecentCableTrend] = useState<DataPoint | undefined>();
    const [recentWaterContent, setRecentWaterContent] = useState<WaterPoint | undefined>();

    useEffect(() => {
      let measurementMap: Map<string, UnitMeasurement[]> = new Map<string, UnitMeasurement[]>();
      if (!loading) {
        setLoading(true);
        //check if the bin has a fan to use the cfm in the drying graph
        // if (bin.settings.fan?.type !== pond.FanType.FAN_TYPE_UNKNOWN) {
        //   setIncludeCFM(true);
        // }
        binAPI
          .listBinComponentsMeasurements(
            bin.key(),
            startDate.toISOString(),
            endDate.toISOString(),
            showErrors,
            showErrors,
            as
          )
          .then(resp => {
            resp.data.measurements.forEach((um: any) => {
              let unitMeasurement = UnitMeasurement.any(um, user);
              let entry = measurementMap.get(unitMeasurement.componentId);
              if (entry) {
                entry.push(unitMeasurement);
              } else {
                measurementMap.set(unitMeasurement.componentId, [unitMeasurement]);
              }
            });
            setCompMeasurements(measurementMap);
            setLoading(false);
          });
      }
    }, [bin, binAPI, startDate, endDate, user, as]); // eslint-disable-line react-hooks/exhaustive-deps

    const zoomOut = () => {
      setXDomain(["dataMin", "dataMax"]);
      setZoomed(false);
    };

    const zoomIn = (domain: string[] | number[]) => {
      if (!isMobile) {
        setXDomain(domain);
        setZoomed(true);
      }
    };

    const updateDateRange = (newStartDate: any, newEndDate: any) => {
      let range = GetDefaultDateRange();
      range.start = newStartDate;
      range.end = newEndDate;
      setStartDate(newStartDate);
      setEndDate(newEndDate);
    };

    //this uses the components found in the bins status
    const waterGraph = () => {
        let moistureCables: pond.GrainCable[] = [];
        bin.status.grainCables.forEach(cable => {
          if (cable.relativeHumidity.length > 0) {
            moistureCables.push(cable);
          }
        });
        if (bin.status.plenums[0] && moistureCables[0] && bin.status.pressures[0] && bin.supportedGrain()) {
          return (
            <Box>
              <BinWaterLevel
                bin={bin}
                // range={{ start: startDate, end: endDate }}
                start={startDate.toISOString()}
                end={endDate.toISOString()}
                plenumKey={componentDevices.get(bin.status.plenums[0].key) + ":" + bin.status.plenums[0].key}
                cableKey={componentDevices.get(moistureCables[0].key) + ":" + moistureCables[0].key}
                pressureKey={componentDevices.get(bin.status.pressures[0].key) + ":" + bin.status.pressures[0].key}
                fanKey={
                  bin.status.fans.length > 0
                    ? componentDevices.get(bin.status.fans[0].key) + ":" + bin.status.fans[0].key
                    : undefined
                }
                newXDomain={xDomain}
                multiGraphZoom={zoomIn}
                multiGraphZoomOut
                returnLast={lastWater => {
                  setRecentWaterContent(lastWater);
                }}
              />
            </Box>
          );
        } else {
          return (
            <Box minHeight={100} display="flex" justifyContent="center" alignItems="center">
              <Typography style={{ fontWeight: 650 }}>
                Plenum with pressure and moisture cable as well as an initial moisture and supported
                grain type set in the bin settings required to calculate Water Content
              </Typography>
            </Box>
          );
        }
      };

    return (
      <Box className={classes.root}>
        <Box className={classes.toolbar} display="flex" justifyContent="space-between">
            <Box>
                <TimeBar startDate={startDate} endDate={endDate} updateDateRange={updateDateRange}/>
            </Box>
            <Box>
            {zoomed && (
              <Tooltip title="Zoom Out Graphs">
                <Button variant="outlined" onClick={zoomOut}>
                  <ZoomOut />
                </Button>
              </Tooltip>
            )}
          <FormControlLabel
            label="Show Errors"
            control={
              <Checkbox
                checked={showErrors}
                onChange={() => {
                  //setShowErrors(!showErrors);
                  dispatch({ key: "showErrors", value: !showErrors });
                }}
              />
            }
          />
            </Box>
        </Box>
        <Box className={classes.scrollContent}>
          <CardHeader
            avatar={
              <Avatar
                variant="square"
                src={themeType === "light" ? VPDDark : VPDLight}
                className={classes.avatarIcon}
                alt={"Drying Score"}
              />
            }
            title={
              <Grid2 container direction="row" justifyContent="space-between">
                <Grid2 >
                  <Typography style={{ fontSize: 25, fontWeight: 650 }}>
                    Drying vs. Hydrating
                  </Typography>
                </Grid2>
              </Grid2>
            }
            subheader={
              recentVPD ? (
                <Grid2 container>
                  <Grid2 size={{ xs: 12 }}>
                    <span>
                      <span style={{ color: recentVPD.dryScore > 0 ? orange[500] : blue[500] }}>
                        {recentVPD.dryScore > 0 ? "drying" : "hydrating"}
                      </span>
                      <span>{" : "}</span>
                      <span
                        style={{
                          color: recentVPD.dryScore > 0 ? orange[500] : blue[500],
                          fontWeight: 500
                        }}>
                        {recentVPD.dryScore.toFixed(2)}
                      </span>
                      <br />
                    </span>
                  </Grid2>
                  <Grid2 size={{ xs: 12 }}>
                    <Typography color="textSecondary" variant={"caption"}>
                      {moment(recentVPD.timestamp).fromNow()}
                    </Typography>
                  </Grid2>
                </Grid2>
              ) : (
                <Typography variant="body1" color="textPrimary">
                  No Data
                </Typography>
              )
            }
          />
          <Box padding={1}>
            {cables.length > 0 && plenums.length > 0 ? (
                <BinGraphsVPD
                cables={cables}
                plenums={plenums}
                measurementMap={compMeasurements}
                newXDomain={xDomain}
                multiGraphZoom={zoomIn}
                multiGraphZoomOut
                //perBushelCFM={includeCFM ? bin.status.cfmPerBushel : undefined}
                returnLastVPD={lastVPD => {
                  setRecentVPD(lastVPD);
                }}
                />
              ) : (
              <Box minHeight={100} display="flex" justifyContent="center" alignItems="center">
                <Typography style={{ fontWeight: 650 }}>
                  Plenum and moisture cable required to calculate VPD
                </Typography>
              </Box>
            )}
          </Box>
          <CardHeader
            avatar={
              <Avatar
                variant="square"
                src={themeType === "light" ? TrendDark : TrendLight}
                className={classes.avatarIcon}
                alt={"VPD"}
              />
            }
            title={
              <Typography style={{ fontSize: 25, fontWeight: 650 }}>Moisture Trending</Typography>
            }
            subheader={
              recentPlenumTrend && recentCableTrend ? (
                <Grid2 container>
                  <Grid2 size={{ xs: 12 }}>
                    <span>
                      {"Plenum Moisture: "}
                      <span style={{ color: orange[500], fontWeight: 500 }}>
                        {recentPlenumTrend.trend.toFixed(2)}
                      </span>
                      <br />
                    </span>
                    <span>
                      {"Grain Moisture: "}
                      <span style={{ color: teal[500], fontWeight: 500 }}>
                        {recentCableTrend.moisture.toString()}
                      </span>
                      <br />
                    </span>
                  </Grid2>
                  <Grid2 size={{ xs: 12 }}>
                    <Typography color="textSecondary" variant={"caption"}>
                      {recentPlenumTrend.timestamp > recentCableTrend.timestamp
                        ? moment(recentPlenumTrend.timestamp).fromNow()
                        : moment(recentCableTrend.timestamp).fromNow()}
                    </Typography>
                  </Grid2>
                </Grid2>
              ) : (
                <Typography variant="body1" color="textPrimary">
                  No Data
                </Typography>
              )
            }
          />
          <Box padding={1}>
            {cables.length > 0 && plenums.length > 0 ? (
              <BinGraphsTrending
                cables={cables}
                plenums={plenums}
                measurementMap={compMeasurements}
                bin={bin}
                newXDomain={xDomain}
                multiGraphZoom={zoomIn}
                multiGraphZoomOut
                returnLastMeasurements={(lastData, lastTrend) => {
                  setRecentCableTrend(lastData);
                  setRecentPlenumTrend(lastTrend);
                }}
              />
            ) : (
              <Box minHeight={100} display="flex" justifyContent="center" alignItems="center">
                <Typography style={{ fontWeight: 650 }}>
                  Plenum and moisture cable required to calculate trending data
                </Typography>
              </Box>
            )}
          </Box>
          <CardHeader
            avatar={
              <Avatar
                variant="square"
                src={themeType === "light" ? WaterDark : WaterLight}
                className={classes.avatarIcon}
                alt={"VPD"}
              />
            }
            title={
              <Typography style={{ fontSize: 25, fontWeight: 650 }}>Grain Water Content</Typography>
            }
            subheader={
              recentWaterContent &&
              bin.settings.inventory &&
              bin.settings.inventory.initialMoisture > 0 ? (
                <Grid2 container>
                  <Grid2 size={{ xs: 12 }}>
                    <span>
                      {"Water Content: "}
                      <span style={{ color: blue[500], fontWeight: 500 }}>
                        {recentWaterContent.liters && !isNaN(recentWaterContent.liters)
                          ? recentWaterContent.liters.toFixed(2)
                          : ""}
                      </span>
                      <br />
                    </span>
                  </Grid2>
                  <Grid2 size={{ xs: 12 }}>
                    <Typography color="textSecondary" variant={"caption"}>
                      {moment(recentWaterContent.timestamp).fromNow()}
                    </Typography>
                  </Grid2>
                </Grid2>
              ) : (
                <Typography variant="body1" color="textPrimary">
                  No Data
                </Typography>
              )
            }
          />
          <Box padding={1}>
            {waterGraph()}
          </Box>
        </Box>
      </Box>
    )
}