import { useState, useEffect, useMemo, useRef } from "react";
import Box from "@mui/material/Box";
import {
  FileBrowser,
  FileContextMenu,
  FileList,
  FileNavbar,
  FileToolbar,
  setChonkyDefaults,
  ChonkyActions,
} from "chonky";
import { ChonkyIconFA } from "chonky-icon-fontawesome";

import {
  getServerFiles,
  createServerFolder,
  deleteServerItem,
  getServerItem,
} from "@mcl/queries";

import "@mcl/css/header.css";

export default function MineclusterFiles(props) {
  // Chonky configuration
  setChonkyDefaults({ iconComponent: ChonkyIconFA });
  const fileActions = useMemo(
    () => [
      ChonkyActions.CreateFolder,
      ChonkyActions.UploadFiles,
      ChonkyActions.DownloadFiles,
      ChonkyActions.CopyFiles,
      ChonkyActions.DeleteFiles,
    ],
    [],
  );
  const { server: serverName } = props;
  const inputRef = useRef(null);
  const [dirStack, setDirStack] = useState(["."]);
  const [files, setFiles] = useState([]);

  const updateFiles = () =>
    getServerFiles(serverName, dirStack.join("/")).then((f) =>
      setFiles(f ?? []),
    );

  useEffect(() => {
    updateFiles();
  }, [dirStack]);

  const getFolderChain = () => {
    if (dirStack.length === 1) return [{ id: "home", name: "/", isDir: true }];
    return dirStack.map((d, i) => ({ id: `${d}-${i}`, name: d, isDir: true }));
  };

  const openParentFolder = () => setDirStack(dirStack.slice(0, -1));

  function openFolder(payload) {
    const { targetFile: file } = payload;
    if (!file || !file.isDir) return;
    setDirStack([...dirStack, file.name]);
  }

  function createFolder() {
    const name = prompt("What is the name of the new folder?");
    const path = [...dirStack, name].join("/");
    createServerFolder(serverName, path).then(updateFiles);
  }

  function deleteItems(files) {
    Promise.all(
      files.map((f) =>
        deleteServerItem(serverName, [...dirStack, f.name].join("/"), f.isDir),
      ),
    )
      .catch((e) => console.error("Error deleting some files!", e))
      .then(updateFiles);
  }

  function uploadFileSelection(e) {
    if (!e.target.files || e.target.files.length === 0) return;
    const { files } = e.target;
    Promise.all([...files].map((f) => uploadFile(f)))
      .catch((e) => console.log("Error uploading a file", e))
      .then(updateFiles);
  }

  async function uploadFile(file) {
    const formData = new FormData();
    formData.append("file", file);
    formData.append("name", serverName);
    formData.append("path", [...dirStack, name].join("/"));
    await fetch("/api/files/upload", {
      method: "POST",
      body: formData,
    });
  }

  async function downloadFiles(files) {
    Promise.all(
      files.map((f) =>
        getServerItem(serverName, f.name, [...dirStack, f.name].join("/")),
      ),
    )
      .then(() => console.log("Done"))
      .catch((e) => console.error("Error Downloading files!", e));
  }

  function fileClick(chonkyEvent) {
    const { id: clickEvent, payload } = chonkyEvent;
    console.log(chonkyEvent);
    if (clickEvent === "open_parent_folder") return openParentFolder();
    if (clickEvent === "create_folder") return createFolder();
    if (clickEvent === "upload_files") return inputRef.current.click();
    if (clickEvent === "download_files")
      return downloadFiles(chonkyEvent.state.selectedFilesForAction);
    if (clickEvent === "delete_files")
      return deleteItems(chonkyEvent.state.selectedFilesForAction);
    if (clickEvent !== "open_files") return console.log(clickEvent);
    openFolder(payload);
  }
  return (
    <Box className="minecluster-files" sx={{ height: "calc(100vh - 6rem)" }}>
      <input
        type="file"
        id="file"
        ref={inputRef}
        style={{ display: "none" }}
        onChange={uploadFileSelection}
        multiple
      />

      <FileBrowser
        files={files}
        folderChain={getFolderChain()}
        onFileAction={fileClick}
        fileActions={fileActions}
        darkMode={true}
      >
        <FileNavbar />
        <FileToolbar />
        <FileList />
        <FileContextMenu />
      </FileBrowser>
    </Box>
  );
}
