import {
  Button,
  DialogActions,
  DialogContent,
  DialogTitle,
  Step,
  StepLabel,
  Stepper,
  Grid2 as Grid,
  FormControlLabel,
  Switch,
  Table,
  TableHead,
  TableRow,
  TableCell,
  TableBody,
  Box,
  Typography,
  Checkbox
} from "@mui/material";

import ResponsiveDialog from "common/ResponsiveDialog";
import { Component, Device } from "models";
import { pond, quack } from "protobuf-ts/pond";
import { useComponentAPI, useGlobalState, useSnackbar } from "providers";
import React, { useEffect, useState } from "react";
import { CableInfo } from "./ComponentDiagnostics";
import ComponentForm from "./ComponentForm";
import { getThemeType } from "theme/themeType";
import { makeStyles } from "@mui/styles";

const useStyles = makeStyles(() => {
  return ({
    buttons: {
      marginLeft: 5,
      marginRight: 5
    },
    cell: {
      padding: 5
    },
    dark: {
      backgroundColor: getThemeType() === "light" ? "rgb(245, 245, 245)" : "rgb(50, 50, 50)",
      padding: 0
    },
    light: {
      backgroundColor: getThemeType() === "light" ? "rgb(235, 235, 235)" : "rgb(60, 60, 60)",
      padding: 0
    }
  })
});

interface Props {
  open: boolean;
  closeDialog: () => void;
  port: string;
  diagComponent: Component;
  device: Device;
  cableInfo: CableInfo[];
  refreshCallback: () => void;
}

interface CompStep {
  label: string;
  completed?: boolean;
}

export default function AddCompsFromDiag(props: Props) {
  const { diagComponent, port, cableInfo, open, closeDialog, device, refreshCallback } = props;
  const [steps, setSteps] = useState<CompStep[]>([]);
  const [{as}] = useGlobalState();
  const classes = useStyles();
  const [currentStep, setCurrentStep] = useState(0);
  const [components, setComponents] = useState<Component[]>([]);
  const { error, success } = useSnackbar();
  //const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false)
  const compAPI = useComponentAPI();
  const [componentsToAdd, setComponentsToAdd] = useState<Component[]>([]);
  const [settingsValid, setSettingsValid] = useState(false);
  const [useAdvanced, setUseAdvanced] = useState(false);

  useEffect(() => {
    let components: Component[] = [];
    let steps: CompStep[] = [];
    cableInfo.forEach(cable => {
      let settings: pond.ComponentSettings = pond.ComponentSettings.create();
      settings.type = quack.ComponentType.COMPONENT_TYPE_GRAIN_CABLE;
      settings.subtype = cable.subtype ?? quack.GrainCableSubtype.GRAIN_CABLE_SUBTYPE_NONE;
      settings.addressType = cable.id + 8;
      settings.address = diagComponent.settings.address;
      settings.measurementPeriodMs = 3600000; //set the measurement/report period to 1 hour
      settings.reportPeriodMs = 3600000;
      settings.name = cable.name;
      components.push(Component.create(pond.Component.create({ settings: settings })));
      steps.push({ label: "Cable ID: " + cable.id });
    });
    setComponents(components);
    setSteps(steps);
  }, [cableInfo, diagComponent]);

  const stepper = () => {
    return (
      <Stepper nonLinear activeStep={currentStep} style={{ width: "100%" }}>
        {steps.map(compStep => {
          const labelProps: {
            optional?: React.ReactNode;
          } = {};
          return (
            <Step key={compStep.label} completed={compStep.completed}>
              <StepLabel {...labelProps}>{compStep.label}</StepLabel>
            </Step>
          );
        })}
      </Stepper>
    );
  };

  const close = () => {
    closeDialog();
    setUseAdvanced(false);
    setComponentsToAdd([]);
  };

  const addComponents = () => {
    let c: pond.MultiComponentSettings = pond.MultiComponentSettings.create();
    componentsToAdd.forEach(component => {
      c.components.push(component.settings);
    });
    compAPI
      .addMultiComponents(device.id(), c, as)
      .then(resp => {
        success("Components added to Device");
      })
      .catch(err => {
        error("One or more component failed to add");
      })
      .finally(() => {
        refreshCallback();
      });
  };

  const resetSteps = () => {
    steps.forEach(step => {
      step.completed = false;
    });
  };

  const simpleActions = () => {
    return (
      <DialogActions>
        <Grid container direction="row" justifyContent="space-between">
          <Grid>
            <Button
              variant="contained"
              color="primary"
              onClick={() => {
                close();
              }}>
              Cancel
            </Button>
          </Grid>
          <Grid>
            <Button
              className={classes.buttons}
              variant="contained"
              color="primary"
              onClick={() => {
                addComponents();
              }}>
              Confirm
            </Button>
          </Grid>
        </Grid>
      </DialogActions>
    );
  };

  const advancedActions = () => {
    return (
      <DialogActions>
        <Grid container direction="row" justifyContent="space-between">
          <Grid>
            <Button
              variant="contained"
              color="primary"
              onClick={() => {
                close();
              }}>
              Cancel
            </Button>
          </Grid>
          <Grid>
            {currentStep !== 0 && (
              <Button
                className={classes.buttons}
                variant="contained"
                color="primary"
                onClick={() => {
                  setCurrentStep(currentStep - 1);
                }}>
                Back
              </Button>
            )}
            {currentStep !== steps.length - 1 && (
              <React.Fragment>
                <Button
                  className={classes.buttons}
                  variant="contained"
                  color="primary"
                  onClick={() => {
                    setCurrentStep(currentStep + 1);
                  }}>
                  Next
                </Button>
              </React.Fragment>
            )}
            {steps[currentStep] && !steps[currentStep].completed && (
              <Button
                className={classes.buttons}
                variant="contained"
                color="primary"
                disabled={!settingsValid}
                onClick={() => {
                  //if not on the last step
                  if (currentStep !== steps.length - 1) {
                    setCurrentStep(currentStep + 1);
                  }
                  steps[currentStep].completed = true;
                  setSteps([...steps]);
                  let c = componentsToAdd;
                  c.push(components[currentStep]);
                  setComponentsToAdd([...c]);
                }}>
                Add
              </Button>
            )}
            <Button
              className={classes.buttons}
              variant="contained"
              color="primary"
              onClick={() => {
                //setConfirmationDialogOpen(true)
                addComponents();
              }}>
              Confirm
            </Button>
          </Grid>
        </Grid>
      </DialogActions>
    );
  };

  const simpleContent = () => {
    return (
      <DialogContent>
        <Box>
          <Typography>Select the Components to add to the device</Typography>
          <Typography>Components will have their measurement interval set to 1 hour</Typography>
        </Box>
        <Table>
          <TableHead>
            <TableRow>
              <TableCell align="center" className={classes.cell}>
                Add Component
              </TableCell>
              <TableCell align="center" className={classes.cell}>
                Cable ID
              </TableCell>
              <TableCell align="center" className={classes.cell}>
                Component Name
              </TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {components.map((comp, i) => (
              <TableRow className={i % 2 === 0 ? classes.light : classes.dark} key={i}>
                <TableCell align="center" className={classes.cell}>
                  <Checkbox
                    onChange={(e, checked) => {
                      if (checked) {
                        let c = componentsToAdd;
                        c.push(comp);
                        setComponentsToAdd([...c]);
                      } else {
                        let c = componentsToAdd;
                        if (c.includes(comp)) {
                          c.splice(c.indexOf(comp), 1);
                        }
                      }
                    }}
                  />
                </TableCell>
                <TableCell align="center" className={classes.cell}>
                  {comp.settings.addressType - 8}
                </TableCell>
                <TableCell align="center" className={classes.cell}>
                  {comp.name()}
                </TableCell>
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </DialogContent>
    );
  };

  const advancedContent = () => {
    return (
      <DialogContent>
        {stepper()}
        <ComponentForm
          component={components[currentStep]}
          canEdit
          device={device}
          componentChanged={(component, isValid) => {
            components[currentStep].settings = component.settings;
            setSettingsValid(isValid);
          }}
        />
      </DialogContent>
    );
  };

  const componentsDialog = () => {
    return (
      <ResponsiveDialog
        open={open}
        onClose={() => {
          close();
        }}>
        <DialogTitle>
          <Grid container direction="row" justifyContent="space-between">
            <Grid >Port {port} Components</Grid>
            <Grid >
              <FormControlLabel
                control={
                  <Switch
                    value={useAdvanced}
                    title="Advanced"
                    onClick={() => {
                      setUseAdvanced(!useAdvanced);
                      setComponentsToAdd([]);
                      setCurrentStep(0);
                      resetSteps();
                    }}
                  />
                }
                label="Advanced"
                labelPlacement="start"
              />
            </Grid>
          </Grid>
        </DialogTitle>
        {useAdvanced ? advancedContent() : simpleContent()}
        {useAdvanced ? advancedActions() : simpleActions()}
      </ResponsiveDialog>
    );
  };

  return <React.Fragment>{componentsDialog()}</React.Fragment>;
}
