import AddIcon from "@mui/icons-material/Add";
import DeleteIcon from "@mui/icons-material/Delete";
import EditIcon from "@mui/icons-material/Edit";
import {
  IconButton,
  ListItem,
  ListItemText,
  Tooltip,
  Typography,
} from "@mui/material";
import React from "react";
import { Device, DeviceRelay } from "../../api/DeviceApi";
import { RelayApi, RelayStatus } from "../../api/RelayApi";
import { EditDeviceRelaysDialog } from "../../dialogs/EditDeviceRelaysDialog";
import { useAlert } from "../../hooks/context_providers/AlertDialogProvider";
import { useConfirm } from "../../hooks/context_providers/ConfirmDialogProvider";
import { useLoadingMessage } from "../../hooks/context_providers/LoadingMessageProvider";
import { useSnackbar } from "../../hooks/context_providers/SnackbarProvider";
import { AsyncWidget } from "../../widgets/AsyncWidget";
import { BoolText } from "../../widgets/BoolText";
import { TimeWidget } from "../../widgets/TimeWidget";
import { DeviceRouteCard } from "./DeviceRouteCard";

export function DeviceRelays(p: {
  device: Device;
  onReload: () => void;
}): React.ReactElement {
  const confirm = useConfirm();
  const loadingMessage = useLoadingMessage();
  const snackbar = useSnackbar();
  const alert = useAlert();

  const [dialogOpen, setDialogOpen] = React.useState(false);
  const [currRelay, setCurrRelay] = React.useState<DeviceRelay | undefined>();

  const createNewRelay = () => {
    setDialogOpen(true);
    setCurrRelay(undefined);
  };

  const updateRelay = async (r: DeviceRelay) => {
    setDialogOpen(true);
    setCurrRelay(r);
  };

  const deleteRelay = async (r: DeviceRelay) => {
    if (
      !(await confirm("Do you really want to delete this relay configuration?"))
    )
      return;

    try {
      await RelayApi.Delete(r);

      p.onReload();
      snackbar("The relay configuration was successfully deleted!");
    } catch (e) {
      console.error("Failed to delete relay!", e);
      alert(`Failed to delete device relay configuration! ${e}`);
    } finally {
      loadingMessage.hide();
    }
  };

  return (
    <>
      {dialogOpen && (
        <EditDeviceRelaysDialog
          device={p.device}
          onClose={() => setDialogOpen(false)}
          relay={currRelay}
          onUpdated={() => {
            setDialogOpen(false);
            p.onReload();
          }}
        />
      )}
      <DeviceRouteCard
        title="Device relays"
        actions={
          <Tooltip title="Create new relay">
            <IconButton
              onClick={createNewRelay}
              disabled={p.device.relays.length >= p.device.info.max_relays}
            >
              <AddIcon />
            </IconButton>
          </Tooltip>
        }
      >
        {p.device.relays.length === 0 ? (
          <Typography style={{ textAlign: "center" }}>
            No relay configured yet.
          </Typography>
        ) : (
          <></>
        )}

        {p.device.relays.map((r, i) => (
          <ListItem
            alignItems="flex-start"
            key={r.id}
            secondaryAction={
              <>
                <Tooltip title="Edit the relay configuration">
                  <IconButton onClick={() => updateRelay(r)}>
                    <EditIcon />
                  </IconButton>
                </Tooltip>

                {i === p.device.relays.length - 1 && (
                  <Tooltip title="Delete the relay configuration">
                    <IconButton onClick={() => deleteRelay(r)}>
                      <DeleteIcon />
                    </IconButton>
                  </Tooltip>
                )}
              </>
            }
          >
            <ListItemText
              primary={r.name}
              secondary={<RelayEntryStatus relay={r} />}
            />
          </ListItem>
        ))}
      </DeviceRouteCard>
    </>
  );
}

function RelayEntryStatus(
  p: Readonly<{ relay: DeviceRelay }>
): React.ReactElement {
  const [state, setState] = React.useState<RelayStatus | undefined>();

  const load = async () => {
    setState(await RelayApi.SingleStatus(p.relay));
  };

  return (
    <AsyncWidget
      loadKey={p.relay.id}
      load={load}
      errMsg="Failed to load relay status!"
      build={() => (
        <>
          <BoolText val={state!.on} positive="ON" negative="OFF" />{" "}
          {state?.forced_state.type !== "None" && <b>Forced</b>} for{" "}
          <TimeWidget diff time={state!.for} />
        </>
      )}
    />
  );
}
