import {
  Button,
  DialogActions,
  DialogContent,
  DialogTitle,
  Theme,
  Typography
} from "@mui/material";
import { makeStyles } from "@mui/styles";
import ResponsiveDialog from "common/ResponsiveDialog";
import SearchSelect, { Option } from "common/SearchSelect";
import { useBackpackAPI, useDeviceAPI, usePrevious, useSnackbar } from "hooks";
import { Backpack, Device } from "models";
import { backpackOptions } from "pbHelpers/Backpack";
import React, { useCallback, useEffect, useState } from "react";

const useStyles = makeStyles((theme: Theme) => {
  return ({
    contentSpacing: {
      marginTop: theme.spacing(1),
      marginBottom: theme.spacing(1)
    }
  });
});

interface Props {
  isDialogOpen: boolean;
  closeDialogCallback: Function;
  refreshCallback: Function;
  device: Device;
}

export default function LoadDeviceProfile(props: Props) {
  const classes = useStyles();
  const { isDialogOpen, closeDialogCallback, refreshCallback, device } = props;
  const { success, error } = useSnackbar();
  const prevIsDialogOpen = usePrevious(isDialogOpen);
  const backpackAPI = useBackpackAPI();
  const deviceAPI = useDeviceAPI();
  const [loading, setLoading] = useState<boolean>(false);
  const [backpack, setBackpack] = useState<Backpack | undefined>(undefined);
  const [backpacks, setBackpacks] = useState<Backpack[]>([]);

  const setDefaultState = () => {
    setBackpacks([]);
    setBackpack(undefined);
  };

  const load = useCallback(() => {
    setLoading(true);

    backpackAPI
      .listBackpacks()
      .then((response: any) => {
        const rawBackpacks = response.data.backpacks;
        const rBackpacks: Backpack[] = [];
        if (rawBackpacks && rawBackpacks.length > 0) {
          rawBackpacks.forEach((b: any) => {
            rBackpacks.push(Backpack.any(b));
          });
        }
        setBackpacks(rBackpacks);
        setBackpack(undefined);
      })
      .catch((err: any) => {
        setDefaultState();
        error(err ? err : "Error occured while loading device profiles");
      })
      .finally(() => setLoading(false));
  }, [backpackAPI, error]);

  useEffect(() => {
    if (prevIsDialogOpen !== isDialogOpen && isDialogOpen === true) {
      load();
    }
  }, [isDialogOpen, load, prevIsDialogOpen]);

  const close = () => {
    closeDialogCallback();
    setDefaultState();
  };

  const submit = () => {
    const deviceName = device.name();
    const backpackName = backpack ? backpack.name() : "Unknown";
    const backpackID = backpack ? backpack.id() : 0;
    deviceAPI
      .loadBackpack(device.id(), backpackID)
      .then((_response: any) => {
        success("Successfully loaded " + backpackName + " onto " + deviceName + "!");
        refreshCallback();
      })
      .catch(() => {
        error("Error occured while loading " + backpackName + " onto " + deviceName);
      })
      .finally(() => close());
  };

  const changeBackpack = (option: Option | null) => {
    const selectedBackpack = option
      ? backpacks.find(backpack => {
          return backpack.id() === (option.value as number);
        })
      : undefined;

    setBackpack(selectedBackpack);
  };

  const isFormValid = (): boolean => {
    const isDeviceValid = device && device.id() > 0;
    const isBackpackValid = backpack !== undefined;
    return isBackpackValid && isDeviceValid;
  };

  // UI Begins

  const content = () => {
    const selectedBackpack = backpack
      ? ({ label: backpack.name(), value: backpack.id() } as Option)
      : undefined;
    return (
      <SearchSelect
        label="Select a profile to load"
        selected={selectedBackpack}
        options={backpackOptions(backpacks)}
        changeSelection={option => changeBackpack(option)}
        loading={loading}
      />
    );
  };

  const actions = () => {
    return (
      <React.Fragment>
        <Button size="small" color="primary" onClick={close}>
          Cancel
        </Button>
        <Button size="small" disabled={!isFormValid()} color="primary" onClick={submit}>
          Submit
        </Button>
      </React.Fragment>
    );
  };

  return (
    <ResponsiveDialog
      open={isDialogOpen}
      onClose={close}
      aria-labelledby="load-device-profile"
      maxWidth="sm"
      fullWidth>
      <DialogTitle id="load-device-profile-title">
        Load Device Profile
        <Typography variant="body2" color="textSecondary">
          {device.name()}
        </Typography>
      </DialogTitle>
      <DialogContent className={classes.contentSpacing}>{content()}</DialogContent>
      <DialogActions>{actions()}</DialogActions>
    </ResponsiveDialog>
  );
}
