import {
  IconButton,
  ListItemIcon,
  ListItemText,
  Menu,
  MenuItem,
  Theme,
  Tooltip
} from "@mui/material";
import { blue } from "@mui/material/colors";
import RemoveSelfIcon from "@mui/icons-material/ExitToApp";
import MoreIcon from "@mui/icons-material/MoreVert";
import GroupSettingsIcon from "@mui/icons-material/Settings";
import ShareObjectIcon from "@mui/icons-material/Share";
import SensorIcon from "@mui/icons-material/SettingsInputAntenna";
import ObjectUsersIcon from "@mui/icons-material/AccountCircle";
import ObjectTeamsIcon from "@mui/icons-material/SupervisedUserCircle";
import BinSettings from "bin/BinSettings";
import { Bin, binScope, Component, User } from "models";
import { pond } from "protobuf-ts/pond";
import React, { useState } from "react";
import ObjectUsers from "user/ObjectUsers";
import RemoveSelfFromObject from "user/RemoveSelfFromObject";
import ShareObject from "user/ShareObject";
import { isOffline } from "utils/environment";
import ObjectTeams from "teams/ObjectTeams";
import BinDuplication from "./BinDuplication";
import BinsIcon from "products/Bindapt/BinsIcon";
import HelpIcon from "@mui/icons-material/Help";
import BinSensors from "./BinSensors";
import { useGlobalState, useSnackbar, useUserAPI } from "providers";
import { useMobile } from "hooks";
import { makeStyles } from "@mui/styles";

const useStyles = makeStyles((theme: Theme) => {
  return ({
    shareIcon: {
      color: blue["500"],
      "&:hover": {
        color: blue["600"]
      }
    },
    removeIcon: {
      color: "var(--status-alert)"
    },
    red: {
      color: "var(--status-alert)"
    }
  });
});

interface Props {
  bin: Bin;
  permissions: pond.Permission[];
  refreshCallback: () => void;
  userID: string;
  components?: Map<string, Component>;
  setComponents?: React.Dispatch<React.SetStateAction<Map<string, Component>>>;
  updateBinStatus?: (componentKeys: string[], removed?: boolean) => void;
}

interface OpenState {
  share: boolean;
  users: boolean;
  teams: boolean;
  settings: boolean;
  sensors: boolean;
  removeSelf: boolean;
  duplication: boolean;
}

export default function BinActions(props: Props) {
  const classes = useStyles();
  const {
    bin,
    permissions,
    refreshCallback,
    userID,
    components,
    setComponents,
    updateBinStatus
  } = props;
  const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
  const [{ user }, dispatch] = useGlobalState();
  const isMobile = useMobile();
  const { error } = useSnackbar();
  const userAPI = useUserAPI();
  const [openState, setOpenState] = useState<OpenState>({
    share: false,
    users: false,
    teams: false,
    settings: false,
    sensors: false,
    removeSelf: false,
    duplication: false
  });

  const startTour = () => {
    if (user) {
      let u = user.protobuf();
      if (u.status) {
        u.status.finishedBinIntro = "";
        userAPI
          .updateUser(userID, u)
          .then(() => {
            dispatch({ key: "user", value: User.any(u) });
          })
          .catch((err: any) => error(err));
      }
    }
  };

  const groupMenu = () => {
    const canShare = permissions.includes(pond.Permission.PERMISSION_SHARE);
    const canManageUsers = permissions.includes(pond.Permission.PERMISSION_USERS);
    return (
      <Menu
        id="groupMenu"
        anchorEl={anchorEl}
        open={Boolean(anchorEl)}
        onClose={() => setAnchorEl(null)}
        keepMounted
        disableAutoFocusItem>
        {!isOffline() && canShare && (
          <MenuItem
            dense
            onClick={() => {
              setOpenState({ ...openState, share: true });
              setAnchorEl(null);
            }}
          >
            <ListItemIcon>
              <ShareObjectIcon className={classes.shareIcon} />
            </ListItemIcon>
            <ListItemText primary="Share" />
          </MenuItem>
        )}
        {!isOffline() && canManageUsers && (
          <MenuItem
            dense
            onClick={() => {
              setOpenState({ ...openState, users: true });
              setAnchorEl(null);
            }}
          >
            <ListItemIcon>
              <ObjectUsersIcon />
            </ListItemIcon>
            <ListItemText primary="Users" />
          </MenuItem>
        )}
        {!isOffline() && canManageUsers && (
          <MenuItem
            dense
            onClick={() => {
              setOpenState({ ...openState, teams: true });
              setAnchorEl(null);
            }}
          >
            <ListItemIcon>
              <ObjectTeamsIcon />
            </ListItemIcon>
            <ListItemText primary="Teams" />
          </MenuItem>
        )}
        <MenuItem
          dense
          onClick={() => {
            setOpenState({ ...openState, duplication: true });
            setAnchorEl(null);
          }}
        >
          <ListItemIcon>
            <BinsIcon />
          </ListItemIcon>
          <ListItemText primary="Duplicate Bin" />
        </MenuItem>
        {isMobile && (
          <MenuItem
            dense
            onClick={() => {
              setAnchorEl(null);
              startTour();
            }}
          >
            <ListItemIcon>
              <HelpIcon />
            </ListItemIcon>
            <ListItemText primary="Redo Help Tour" />
          </MenuItem>
        )}
        {isMobile && (
          <MenuItem
            dense
            onClick={() => {
              setAnchorEl(null);
              setOpenState({ ...openState, sensors: true });
            }}
          >
            <ListItemIcon>
              <SensorIcon />
            </ListItemIcon>
            <ListItemText primary="Bin Sensors" />
          </MenuItem>
        )}
        <MenuItem
          dense
          onClick={() => {
            setOpenState({ ...openState, removeSelf: true });
            setAnchorEl(null);
          }}
        >
          <ListItemIcon>
            <RemoveSelfIcon className={classes.red} />
          </ListItemIcon>
          <ListItemText primary="Leave" />
        </MenuItem>
      </Menu>
    );
  };

  const dialogs = () => {
    const hasWritePermission = permissions.includes(pond.Permission.PERMISSION_WRITE);
    const key = bin.key();
    const label = bin.name();
    return (
      <React.Fragment>
        <BinSettings
          mode="update"
          bin={bin}
          canEdit={hasWritePermission}
          open={openState.settings}
          userID={userID}
          onClose={refresh => {
            if (refresh === true) {
              refreshCallback();
            }
            setOpenState({ ...openState, settings: false });
          }}
        />
        <BinSensors
          mode="update"
          bin={bin}
          canEdit={hasWritePermission}
          open={openState.sensors}
          userID={userID}
          components={components}
          setComponents={setComponents}
          updateBinStatus={updateBinStatus}
          onClose={refresh => {
            if (refresh === true) {
              refreshCallback();
            }
            setOpenState({ ...openState, sensors: false });
          }}
        />
        <ShareObject
          scope={binScope(key)}
          label={label}
          permissions={permissions}
          isDialogOpen={openState.share}
          closeDialogCallback={() => setOpenState({ ...openState, share: false })}
        />
        <ObjectUsers
          scope={binScope(key)}
          label={label}
          permissions={permissions}
          isDialogOpen={openState.users}
          closeDialogCallback={() => setOpenState({ ...openState, users: false })}
          refreshCallback={refreshCallback}
        />
        <BinDuplication
          open={openState.duplication}
          closeDialog={() => {
            setOpenState({ ...openState, duplication: false });
          }}
          bin={bin}
          refreshCallback={refreshCallback}
        />
        <RemoveSelfFromObject
          scope={binScope(key)}
          label={label}
          isDialogOpen={openState.removeSelf}
          closeDialogCallback={() => setOpenState({ ...openState, removeSelf: false })}
        />
      </React.Fragment>
    );
  };

  return (
    <React.Fragment>
      {!isMobile && (
        <Tooltip title="Redo help tour">
          <IconButton onClick={startTour}>
            <HelpIcon />
          </IconButton>
        </Tooltip>
      )}
      {!isMobile && (
        <Tooltip title="Bin Sensors">
          <IconButton
            id="tour-bin-sensors"
            onClick={() => setOpenState({ ...openState, sensors: true })}>
            <SensorIcon />
          </IconButton>
        </Tooltip>
      )}
      <Tooltip title="Bin Settings">
        <IconButton
          id="tour-bin-settings"
          onClick={() => setOpenState({ ...openState, settings: true })}>
          <GroupSettingsIcon />
        </IconButton>
      </Tooltip>
      <IconButton
        aria-owns={anchorEl ? "groupMenu" : undefined}
        aria-haspopup="true"
        id="tour-bin-kebab"
        onClick={(event: React.MouseEvent<HTMLButtonElement>) => setAnchorEl(event.currentTarget)}>
        <MoreIcon />
      </IconButton>
      {groupMenu()}
      {dialogs()}
      <ObjectTeams
        scope={binScope(bin.key())}
        label="Teams"
        permissions={permissions}
        isDialogOpen={openState.teams}
        refreshCallback={refreshCallback}
        closeDialogCallback={() => setOpenState({ ...openState, teams: false })}
      />
    </React.Fragment>
  );
}
