import RefreshIcon from "@mui/icons-material/Refresh";
import {
  Button,
  IconButton,
  LinearProgress,
  Tooltip,
  Typography,
} from "@mui/material";
import { filesize } from "filesize";
import React from "react";
import { DiskImage, DiskImageApi } from "../api/DiskImageApi";
import { ServerApi } from "../api/ServerApi";
import { useAlert } from "../hooks/providers/AlertDialogProvider";
import { useSnackbar } from "../hooks/providers/SnackbarProvider";
import { AsyncWidget } from "../widgets/AsyncWidget";
import { FileInput } from "../widgets/forms/FileInput";
import { VirtWebPaper } from "../widgets/VirtWebPaper";
import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer";

export function DiskImagesRoute(): React.ReactElement {
  const [list, setList] = React.useState<DiskImage[] | undefined>();

  const loadKey = React.useRef(1);

  const load = async () => {
    setList(await DiskImageApi.GetList());
  };

  const reload = () => {
    loadKey.current += 1;
    setList(undefined);
  };

  return (
    <VirtWebRouteContainer label="Disk images">
      <AsyncWidget
        loadKey={loadKey.current}
        errMsg="Failed to load disk images list!"
        load={load}
        ready={list !== undefined}
        build={() => (
          <VirtWebRouteContainer
            label="Disk images management"
            actions={
              <span>
                <Tooltip title="Refresh Disk images list">
                  <IconButton onClick={reload}>
                    <RefreshIcon />
                  </IconButton>
                </Tooltip>
              </span>
            }
          >
            <UploadDiskImageCard onFileUploaded={reload} />
            <DiskImageList list={list!} onReload={reload} />
          </VirtWebRouteContainer>
        )}
      />
    </VirtWebRouteContainer>
  );
}

function UploadDiskImageCard(p: {
  onFileUploaded: () => void;
}): React.ReactElement {
  const alert = useAlert();
  const snackbar = useSnackbar();

  const [value, setValue] = React.useState<File | null>(null);
  const [uploadProgress, setUploadProgress] = React.useState<number | null>(
    null
  );

  const handleChange = (newValue: File | null) => {
    if (
      newValue &&
      newValue.size > ServerApi.Config.constraints.disk_image_max_size
    ) {
      alert(
        `The file is too big (max size allowed: ${filesize(
          ServerApi.Config.constraints.disk_image_max_size
        )}`
      );
      return;
    }

    if (
      newValue &&
      newValue.type.length > 0 &&
      !ServerApi.Config.disk_images_mimetypes.includes(newValue.type)
    ) {
      alert(`Selected file mimetype is not allowed! (${newValue.type})`);
      return;
    }

    setValue(newValue);
  };

  const upload = async () => {
    try {
      setUploadProgress(0);
      await DiskImageApi.Upload(value!, setUploadProgress);

      setValue(null);
      snackbar("The file was successfully uploaded!");

      p.onFileUploaded();
    } catch (e) {
      console.error(e);
      await alert(`Failed to perform file upload! ${e}`);
    }

    setUploadProgress(null);
  };

  if (uploadProgress !== null) {
    return (
      <VirtWebPaper label="File upload" noHorizontalMargin>
        <Typography variant="body1">
          Upload in progress ({Math.floor(uploadProgress * 100)}%)...
        </Typography>
        <LinearProgress variant="determinate" value={uploadProgress * 100} />
      </VirtWebPaper>
    );
  }

  return (
    <VirtWebPaper label="Disk image upload" noHorizontalMargin>
      <div style={{ display: "flex", alignItems: "center" }}>
        <FileInput
          value={value}
          onChange={handleChange}
          style={{ flex: 1 }}
          slotProps={{
            htmlInput: {
              accept: ServerApi.Config.disk_images_mimetypes.join(","),
            },
          }}
        />

        {value && <Button onClick={upload}>Upload</Button>}
      </div>
    </VirtWebPaper>
  );
}

function DiskImageList(p: {
  list: DiskImage[];
  onReload: () => void;
}): React.ReactElement {
  return <>todo</>;
}
