import {
  Tab,
  Tabs,
  Button,
  Theme,
  useTheme,
  Menu,
  MenuItem,
  ListItemIcon,
  ListItemText,
  DialogTitle,
  DialogContent,
  DialogActions
} from "@mui/material";
import { Terminal } from "models";
import { useTerminalAPI, useGlobalState } from "providers";
import React, { useCallback, useEffect, useState } from "react";
import PageContainer from "./PageContainer";
import AddIcon from "@mui/icons-material/Add";
import TerminalSettings from "terminal/TerminalSettings";
import { Delete, MoreVert, ExitToApp as RemoveSelfIcon } from "@mui/icons-material";
import EditIcon from "@mui/icons-material/Edit";
import { blue, green, red } from "@mui/material/colors";
import ResponsiveDialog from "common/ResponsiveDialog";
import { useSnackbar, useUserAPI } from "hooks";
import GateList from "gate/GateList";
import { Scope } from "models";
import { pond } from "protobuf-ts/pond";
import ObjectUsers from "user/ObjectUsers";
import ObjectTeams from "teams/ObjectTeams";
import ObjectUsersIcon from "@mui/icons-material/AccountCircle";
import ObjectTeamsIcon from "@mui/icons-material/SupervisedUserCircle";
import ShareObject from "user/ShareObject";
import RemoveSelfFromObject from "user/RemoveSelfFromObject";
import { makeStyles } from "@mui/styles";

const parentTab = {
  "&": {
    margin: "0px",
    marginTop: "4px",
    marginLeft: "4px",
    animationDuration: "10s",
    background: "rgba(150, 150, 150, 0)",

    borderRadius: "-5px",
    borderTopLeftRadius: "6px",
    borderTopRightRadius: "6px"
  },
  "&:hover": {
    background: "linear-gradient(rgba(150, 150, 150, 0.2), rgba(150, 150, 150, 0))"
  }
};

const useStyles = makeStyles((theme: Theme) => ({
    tab: {
      ...parentTab,
      minWidth: theme.spacing(25),
      left: 0,
      height: "100%",
      background: theme.palette.background.paper
    },
    smallTab: {
      ...parentTab,
      width: theme.spacing(8),
      minWidth: theme.spacing(8),
      background: theme.palette.background.paper
    },
    selectedTab: {
      borderRadius: "-5px",
      borderTopLeftRadius: "6px",
      borderTopRightRadius: "6px",
      background: theme.palette.background.default,
      "&:hover": {
        background:
          "linear-gradient(rgba(150, 150, 150, 0.3)," + theme.palette.background.default + " 80%)"
      }
    },
    tabText: {
      position: "absolute",
      left: theme.spacing(2),
      color: "transparent",
      textAlign: "left",
      width: "80%",
      backgroundImage: "linear-gradient(to right, white 70%, rgba(200, 200, 200, 0) 87.5%)",
      backgroundClip: "text",
      WebkitBackgroundClip: "text",
      overflowX: "hidden",
      whiteSpace: "nowrap",
      top: 12
    },
    icon: {
      display: "flex",
      position: "absolute",
      right: 0,
      top: 6,
      padding: 6,
      marginRight: "2px",
      width: 36,
      height: 36,
      borderRadius: "18px",
      background: "rgba(0,0,0,0)",
      "&:hover": {
        background:
          "radial-gradient(closest-side, rgba(150, 150, 150, 0.5) 50%, rgba(150, 150, 150, 0.5))"
      }
    },
    green: {
      marginRight: 0,
      paddingRight: 0,
      color: green["500"],
      "&:hover": {
        color: green["600"]
      }
    },
    red: {
      marginRight: 0,
      paddingRight: 0,
      color: red["500"],
      "&:hover": {
        color: red["600"]
      }
    },
    blueIcon: {
      color: blue["500"],
      "&:hover": {
        color: blue["600"]
      }
    },
    addGate: {
      position: "absolute",
      bottom: 20,
      right: 20,
      backgroundColor: theme.palette.primary.main
    }
}));

interface Props {
  terminal?: Terminal;
}

export default function Terminals(props: Props) {
  const terminalAPI = useTerminalAPI();
  const [value, setValue] = useState(0);
  const [terminals, setTerminals] = useState<Terminal[]>([]);
  const classes = useStyles();
  const theme = useTheme();
  const [addTerminal, setAddTerminal] = useState(false);
  const [menuAnchorEl, setMenuAnchorEl] = useState<Element | null>(null);
  const [currentTerminal, setCurrentTerminal] = useState<Terminal>();
  const [removeTerminal, setRemoveTerminal] = useState(false);
  const { openSnack } = useSnackbar();
  const [{ user, as }] = useGlobalState();
  const userAPI = useUserAPI();
  const [permissions, setPermissions] = useState<pond.Permission[]>([]);
  const [userSharing, setUserSharing] = useState(false);
  const [teamSharing, setTeamSharing] = useState(false);
  const [baseShareDialog, setBaseShareDialog] = useState(false);
  const [removeSelfDialog, setRemoveSelfDialog] = useState(false);
  const [loading, setLoading] = useState(false)

  useEffect(() => {
    if (currentTerminal) {
      let key = currentTerminal?.key;
      let kind = "terminal";
      if (as) {
        key = as;
        kind = "team";
      }
      userAPI.getUser(user.id(), { key: key, kind: kind } as Scope).then(resp => {
        setPermissions(resp.permissions);
      });
    }
  }, [as, userAPI, user, currentTerminal]);

  useEffect(() => {
    if (props.terminal) {
      setCurrentTerminal(props.terminal);
    }
  }, [props.terminal]);

  const load = useCallback(() => {
    if(loading) return
    setLoading(true)
    terminalAPI.listTerminals(200, 0, "asc", "name", as).then(resp => {
      setTerminals(resp.data.terminals.map(a => Terminal.any(a)));
    }).catch(err => {
      console.log("There was a problem loading Terminals")
    }).finally(() => {
      setLoading(false)
    })
  }, [terminalAPI, openSnack, as]); //eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    load();
  }, [load]);

  const remove = () => {
    if (currentTerminal) {
      terminalAPI
        .removeTerminal(currentTerminal.key, as)
        .then(resp => {
          openSnack("Terminal Deleted");
          let a = terminals;
          a.splice(terminals.indexOf(currentTerminal), 1);
          setTerminals([...a]);
        })
        .catch(err => {
          openSnack("Failed to delete terminal");
        })
        .finally(() => {
          setRemoveTerminal(false);
        });
    }
  };

  const terminalMenu = () => {
    if (currentTerminal === undefined) return;
    return (
      <Menu
        id="terminalMenu"
        anchorEl={menuAnchorEl ? menuAnchorEl : null}
        open={menuAnchorEl !== null}
        onClose={() => {
          setMenuAnchorEl(null);
        }}>
        {permissions.includes(pond.Permission.PERMISSION_WRITE) && (
          <MenuItem
            onClick={() => {
              setAddTerminal(true);
              setMenuAnchorEl(null);
            }}
            aria-label="Edit Terminal"
            dense>
            <ListItemIcon>
              <EditIcon className={classes.green} />
            </ListItemIcon>
            <ListItemText secondary="Edit Terminal" />
          </MenuItem>
        )}
        {permissions.includes(pond.Permission.PERMISSION_WRITE) && (
          <MenuItem
            onClick={() => {
              setRemoveTerminal(true);
              setMenuAnchorEl(null);
            }}
            aria-label="Remove Terminal"
            dense>
            <ListItemIcon>
              <Delete className={classes.red} />
            </ListItemIcon>
            <ListItemText secondary="Delete Terminal" />
          </MenuItem>
        )}
        {permissions.includes(pond.Permission.PERMISSION_USERS) && (
          <MenuItem
            dense
            onClick={() => {
              setUserSharing(true);
              setMenuAnchorEl(null);
            }}>
            <ListItemIcon>
              <ObjectUsersIcon />
            </ListItemIcon>
            <ListItemText primary="Users" />
          </MenuItem>
        )}
        {permissions.includes(pond.Permission.PERMISSION_USERS) && (
          <MenuItem
            dense
            onClick={() => {
              setTeamSharing(true);
              setMenuAnchorEl(null);
            }}>
            <ListItemIcon>
              <ObjectTeamsIcon />
            </ListItemIcon>
            <ListItemText primary="Teams" />
          </MenuItem>
        )}
        <MenuItem
          dense
          onClick={() => {
            setRemoveSelfDialog(true);
            setMenuAnchorEl(null);
          }}>
          <ListItemIcon>
            <RemoveSelfIcon className={classes.red} />
          </ListItemIcon>
          <ListItemText primary="Leave" />
        </MenuItem>
      </Menu>
    );
  };

  const changeTabs = (newValue: number) => {
    //TODO: change this to just change the selected tab
    if (newValue <= terminals.length) {
      setValue(newValue);
      if (terminals[newValue - 1]) {
        setCurrentTerminal(terminals[newValue -1])
      } else {
        setCurrentTerminal(undefined)
      }
    }
  };

  const gateDisplay = () => {
    return (
      <GateList
        currentTerminal={currentTerminal?.key}
        terminals={terminals}
        useMobile={props.terminal !== undefined}
      />
    );
  };

  //could update the tabs in the same way as the bin yard tabs
  const terminalTabs = () => {
    return (
      <React.Fragment>
        {/* TODO: convert this to use DraggableTabs */}
        <Tabs
          variant="scrollable"
          scrollButtons="auto"
          value={value}
          onChange={(_, v) => changeTabs(v)}
          TabIndicatorProps={{ style: { background: "rgba(0,0,0,0)" } }}>
          <Tab
            key={"all"}
            label="All"
            disableTouchRipple
            classes={{ root: classes.smallTab, selected: classes.selectedTab }}
            style={{ marginLeft: theme.spacing(1) }}
          />
          {terminals.map((a, index) => (
            <Tab
              classes={{ root: classes.tab, selected: classes.selectedTab }}
              disableTouchRipple
              key={a.key}
              label={
                <span>
                  <div className={classes.tabText}>{a.name}</div>
                  <MoreVert
                    className={classes.icon}
                    onClick={event => {
                      event.stopPropagation()
                      let target = event.currentTarget;
                      setMenuAnchorEl(target);
                      setCurrentTerminal(terminals[index]);
                    }}
                  />
                </span>
              }
            />
          ))}

          <Tab
            classes={{ root: classes.smallTab, selected: classes.selectedTab }}
            label={terminals.length === 0 ? "Add Terminal" : <AddIcon />}
            onClick={() => {
              setCurrentTerminal(undefined);
              setAddTerminal(true);
            }}
            disableTouchRipple={true}
          />
        </Tabs>
      </React.Fragment>
    );
  };

  const removeDialog = () => {
    return (
      <ResponsiveDialog
        open={removeTerminal}
        onClose={() => {
          setRemoveTerminal(false);
        }}>
        <DialogTitle>Delete Terminal</DialogTitle>
        <DialogContent>Are you sure you wish to delete this Terminal?</DialogContent>
        <DialogActions>
          <Button>Cancel</Button>
          <Button onClick={remove}>Confirm</Button>
        </DialogActions>
      </ResponsiveDialog>
    );
  };

  const sharingDialogs = () => {
    if (!currentTerminal) return;
    return (
      <React.Fragment>
        <ShareObject
          scope={{ kind: "terminal", key: currentTerminal.key } as Scope}
          label={currentTerminal.name}
          permissions={permissions}
          isDialogOpen={baseShareDialog}
          closeDialogCallback={() => {
            setBaseShareDialog(false);
          }}
        />
        <ObjectUsers
          scope={{ kind: "terminal", key: currentTerminal.key } as Scope}
          label={currentTerminal.name}
          permissions={permissions}
          isDialogOpen={userSharing}
          closeDialogCallback={() => setUserSharing(false)}
          refreshCallback={() => {}}
        />
        <ObjectTeams
          scope={{ kind: "terminal", key: currentTerminal.key } as Scope}
          label={currentTerminal.name}
          permissions={permissions}
          isDialogOpen={teamSharing}
          closeDialogCallback={() => setTeamSharing(false)}
          refreshCallback={() => {
            return true;
          }}
        />
        <RemoveSelfFromObject
          scope={{ kind: "terminal", key: currentTerminal.key } as Scope}
          label={currentTerminal.name}
          isDialogOpen={removeSelfDialog}
          closeDialogCallback={removed => {
            if (removed) {
              let a = terminals;
              a.splice(terminals.indexOf(currentTerminal), 1);
              setTerminals([...a]);
            }
            setRemoveSelfDialog(false);
          }}
        />
      </React.Fragment>
    );
  };

  return (
    <PageContainer>
      <TerminalSettings
        open={addTerminal}
        closeDialog={newTerminal => {
          if (newTerminal) {
            let a = terminals;
            a.push(newTerminal);
            setTerminals([...a]);
          }
          setAddTerminal(false);
        }}
        terminal={currentTerminal}
      />
      {!props.terminal && terminalTabs()}
      {terminalMenu()}
      {removeDialog()}
      {sharingDialogs()}
      {gateDisplay()}
    </PageContainer>
  );
}
