import PauseIcon from "@mui/icons-material/Pause";
import PersonalVideoIcon from "@mui/icons-material/PersonalVideo";
import PlayArrowIcon from "@mui/icons-material/PlayArrow";
import PowerSettingsNewIcon from "@mui/icons-material/PowerSettingsNew";
import ReplayIcon from "@mui/icons-material/Replay";
import StopIcon from "@mui/icons-material/Stop";
import {
  CircularProgress,
  IconButton,
  Tooltip,
  Typography,
} from "@mui/material";
import React from "react";
import { useNavigate } from "react-router-dom";
import { VMApi, VMInfo, VMState } from "../../api/VMApi";
import { useAlert } from "../../hooks/providers/AlertDialogProvider";
import { useConfirm } from "../../hooks/providers/ConfirmDialogProvider";
import { useSnackbar } from "../../hooks/providers/SnackbarProvider";

export function VMStatusWidget(p: {
  vm: VMInfo;
  onChange?: (s: VMState) => void;
}): React.ReactElement {
  const snackbar = useSnackbar();
  const navigate = useNavigate();

  const [state, setState] = React.useState<undefined | VMState>(undefined);

  const refresh = async () => {
    try {
      const s = await VMApi.GetState(p.vm);
      if (s !== state) p.onChange?.(s);
      setState(s);
    } catch (e) {
      console.error(e);
      snackbar("Failed to refresh VM status!");
    }
  };

  const changedAction = () => setState(undefined);

  React.useEffect(() => {
    refresh();
    const i = setInterval(() => refresh(), 3000);

    return () => clearInterval(i);
  });

  if (state === undefined)
    return (
      <>
        <CircularProgress size={"1rem"} />
      </>
    );

  return (
    <div style={{ display: "inline-flex" }}>
      <Typography>{state}</Typography>

      {
        /* VNC console */ p.vm.vnc_access && (
          <ActionButton
            currState={state}
            cond={["Running"]}
            icon={<PersonalVideoIcon />}
            tooltip="Graphical remote control over the VM"
            performAction={async () => navigate(p.vm.VNCURL)}
            onExecuted={() => {}}
          />
        )
      }

      {/* Start VM */}
      <ActionButton
        currState={state}
        cond={["Shutdown", "Shutoff", "Crashed"]}
        icon={<PlayArrowIcon />}
        tooltip="Start the Virtual Machine"
        performAction={() => VMApi.StartVM(p.vm)}
        onExecuted={changedAction}
      />

      {/* Resume VM */}
      <ActionButton
        currState={state}
        cond={["Paused", "PowerManagementSuspended"]}
        icon={<PlayArrowIcon />}
        tooltip="Resume the Virtual Machine"
        performAction={() => VMApi.ResumeVM(p.vm)}
        onExecuted={changedAction}
      />

      {/* Suspend VM */}
      <ActionButton
        currState={state}
        cond={["Running"]}
        icon={<PauseIcon />}
        tooltip="Suspend the Virtual Machine"
        confirmMessage="Do you really want to supsend this VM?"
        performAction={() => VMApi.SuspendVM(p.vm)}
        onExecuted={changedAction}
      />

      {/* Shutdown VM */}
      <ActionButton
        currState={state}
        cond={["Running"]}
        icon={<PowerSettingsNewIcon />}
        tooltip="Shutdown the Virtual Machine"
        confirmMessage="Do you really want to shutdown this VM?"
        performAction={() => VMApi.ShutdownVM(p.vm)}
        onExecuted={changedAction}
      />

      {/* Kill VM */}
      <ActionButton
        currState={state}
        cond={["Running", "Paused", "PowerManagementSuspended", "Blocked"]}
        icon={<StopIcon />}
        tooltip="Kill the Virtual Machine"
        confirmMessage="Do you really want to kill this VM? This could lead to data loss / corruption!"
        performAction={() => VMApi.KillVM(p.vm)}
        onExecuted={changedAction}
      />

      {/* Reset VM */}
      <ActionButton
        currState={state}
        cond={["Running", "Paused", "PowerManagementSuspended", "Blocked"]}
        icon={<ReplayIcon />}
        tooltip="Reset the Virtual Machine"
        confirmMessage="Do you really want to reset this VM?"
        performAction={() => VMApi.ResetVM(p.vm)}
        onExecuted={changedAction}
      />
    </div>
  );
}

function ActionButton(p: {
  currState: VMState;
  cond: VMState[];
  icon: React.ReactElement;
  tooltip: string;
  confirmMessage?: string;
  performAction: () => Promise<void>;
  onExecuted: () => void;
}): React.ReactElement {
  const confirm = useConfirm();
  const alert = useAlert();

  if (!p.cond.includes(p.currState)) return <></>;

  const performAction = async () => {
    try {
      if (p.confirmMessage && !(await confirm(p.confirmMessage))) return;
      await p.performAction();
      p.onExecuted();
    } catch (e) {
      console.error(e);
      alert("Failed to perform action! " + e);
    }
  };

  return (
    <Tooltip title={p.tooltip}>
      <IconButton
        size="small"
        onClick={performAction}
        style={{ paddingBottom: "0px", paddingTop: "0px" }}
      >
        {p.icon}
      </IconButton>
    </Tooltip>
  );
}
