import UploadFileIcon from "@mui/icons-material/UploadFile";
import { Button, Tooltip, Typography } from "@mui/material";
import React from "react";
import { FileApi, UploadedFile } from "../../api/FileApi";
import { ServerApi } from "../../api/ServerApi";
import { useAlert } from "../../hooks/context_providers/AlertDialogProvider";
import { useLoadingMessage } from "../../hooks/context_providers/LoadingMessageProvider";
import { useSnackbar } from "../../hooks/context_providers/SnackbarProvider";

// https://medium.com/@dprincecoder/creating-a-drag-and-drop-file-upload-component-in-react-a-step-by-step-guide-4d93b6cc21e0

export function UploadFileButton(p: {
  onUploaded: (file: UploadedFile) => void;
  label: string;
  tooltip: string;
}): React.ReactElement {
  const alert = useAlert();
  const loadingMessage = useLoadingMessage();
  const snackbar = useSnackbar();

  const fileInput = React.useRef<HTMLInputElement>(null);

  const [dragActive, setDragActive] = React.useState(false);

  const forceFileSelect = () => fileInput.current?.click();

  const dragEnter = () => {
    setDragActive(true);
  };
  const dragLeave = () => {
    setDragActive(false);
  };

  const handleUpload = async (file: File[]) => {
    if (file.length < 1) return;

    try {
      loadingMessage.show("Uploading file...");

      const result = await FileApi.UploadFile(file[0]);

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

      p.onUploaded(result);
    } catch (e) {
      console.error("Failed to upload file!", e);
      alert(`Failed to upload file! ${e}`);
    } finally {
      loadingMessage.hide();
    }
  };

  const handleDrop = (ev: React.DragEvent) => {
    ev.preventDefault();
    handleUpload([...ev.dataTransfer.files]);
  };

  const handlefileChange = (ev: React.ChangeEvent) => {
    ev.preventDefault();
    if ((fileInput.current?.files?.length ?? 0) > 0) {
      handleUpload([...fileInput.current!.files!]);
    }
  };

  return (
    <Tooltip
      title={p.tooltip}
      onDrop={handleDrop}
      onDragOver={(event) => {
        event.preventDefault();
      }}
      onDragEnter={dragEnter}
      onDragLeave={dragLeave}
    >
      <Button
        size="small"
        startIcon={<UploadFileIcon fontSize="small" />}
        variant={dragActive ? "outlined" : "text"}
        onClick={forceFileSelect}
      >
        <input
          ref={fileInput}
          type="file"
          accept={ServerApi.Config.constraints.file_allowed_types.join(",")}
          style={{
            border: "0",
            height: "1px",
            width: "1px",
            padding: "0px",
            position: "absolute",
            clipPath: "inset(50%)",
          }}
          onChange={handlefileChange}
        />
        <Typography variant="caption">{p.label}</Typography>
      </Button>
    </Tooltip>
  );
}
