<script lang="ts">
  import { Button, Dropzone, Modal, Spinner, Accordion, AccordionItem } from 'flowbite-svelte';
  import FileUpload from './FileUpload.svelte';
  import { processFiles } from '$lib/upload';
  import { onMount } from 'svelte';
  import { scanFiles } from '$lib/upload';
  import { formatBytes } from '$lib/util/upload';
  import { toClipboard } from '$lib/util';

  export let open = false;

  let promise: Promise<void>;
  let files: FileList | undefined = undefined;

  async function onUpload() {
    if (files) {
      promise = processFiles([...files]).then(() => {
        open = false;
      });
    } else if (draggedFiles) {
      promise = processFiles(draggedFiles).then(() => {
        open = false;
      });
    }
  }

  function reset() {
    files = undefined;
    draggedFiles = undefined;
  }

  let storageSpace = '';

  onMount(() => {
    navigator?.storage?.estimate().then(({ usage, quota }) => {
      if (usage && quota) {
        storageSpace = `Storage: ${formatBytes(usage)} / ${formatBytes(quota)}`;
      }
    });
  });

  let filePromises: Promise<File>[];
  let draggedFiles: File[] | undefined;
  let loading = false;
  $: disabled = loading || (!draggedFiles && !files);

  const dropHandle = async (event: DragEvent) => {
    loading = true;
    draggedFiles = [];
    filePromises = [];
    event.preventDefault();
    activeStyle = defaultStyle;

    if (event?.dataTransfer?.items) {
      for (const item of [...event.dataTransfer.items]) {
        const entry = item.webkitGetAsEntry();
        if (item.kind === 'file' && entry) {
          if (entry.isDirectory) {
            await scanFiles(entry, filePromises);
          } else {
            const file = item.getAsFile();
            if (file) {
              draggedFiles.push(file);
              draggedFiles = draggedFiles;
            }
          }
        }
      }

      if (filePromises && filePromises.length > 0) {
        const files = await Promise.all(filePromises);
        if (files) {
          draggedFiles = [...draggedFiles, ...files];
        }
      }
    }

    loading = false;
  };

  let defaultStyle =
    'flex flex-col justify-center items-center w-full h-64 bg-gray-50 rounded-lg border-2 border-gray-300 border-dashed cursor-pointer dark:hover:bg-bray-800 dark:bg-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:hover:border-gray-500 dark:hover:bg-gray-600';
  let highlightStyle =
    'flex flex-col justify-center items-center w-full h-64 bg-gray-50 rounded-lg border-2 border-gray-300 border-dashed cursor-pointer dark:bg-bray-800 dark:bg-gray-700 bg-gray-100 dark:border-gray-600 dark:border-gray-500 dark:bg-gray-600';

  let activeStyle = defaultStyle;
</script>

<Modal title="Upload" bind:open outsideclose on:close={reset}>
  {#await promise}
    <h2 class="justify-center flex">Loading...</h2>
    <div class="text-center"><Spinner /></div>
  {:then}
    <Accordion flush>
      <AccordionItem>
        <span slot="header">What to upload?</span>
        <div class="flex flex-col gap-5">
          <div>
            <p>
              Firstly, ensure that you process your manga with the <b>0.2.0-beta.6</b> of mokuro, you
              can install it by running the following command:
            </p>
            <div role="none" on:click={toClipboard}>
              <code class="text-primary-600 bg-slate-900"
                >pip3 install git+https://github.com/kha-white/mokuro.git@web-reader</code
              >
            </div>
          </div>
          <p>
            This will generate a <code>.mokuro</code> file for each volume processed, upload your
            manga along with the <code>.mokuro</code> files.
          </p>
          <p>
            On mobile, uploading via directory is not supported so you will need to zip your manga
            first and then upload it via
            <code class="text-primary-600 bg-slate-900">choose files</code>.
          </p>
        </div>
      </AccordionItem>
    </Accordion>
    <Dropzone
      id="dropzone"
      on:drop={dropHandle}
      on:dragover={(event) => {
        event.preventDefault();
        activeStyle = highlightStyle;
      }}
      on:dragleave={(event) => {
        event.preventDefault();
        activeStyle = defaultStyle;
      }}
      on:click={(event) => {
        event.preventDefault();
      }}
      defaultClass={activeStyle}
    >
      <svg
        aria-hidden="true"
        class="mb-3 w-10 h-10 text-gray-400"
        fill="none"
        stroke="currentColor"
        viewBox="0 0 24 24"
        xmlns="http://www.w3.org/2000/svg"
        ><path
          stroke-linecap="round"
          stroke-linejoin="round"
          stroke-width="2"
          d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
        /></svg
      >
      {#if files}
        <p class="mb-2 text-sm text-gray-500 dark:text-gray-400">
          Upload {files.length}
          {files.length > 1 ? 'files' : 'file'}?
        </p>
      {:else if draggedFiles && draggedFiles.length > 0}
        <p class="mb-2 text-sm text-gray-500 dark:text-gray-400">
          Upload {draggedFiles.length} hih
          {draggedFiles.length > 1 ? 'files' : 'file'}?
        </p>
      {:else if loading}
        <Spinner />
      {:else}
        <p class="mb-2 text-sm text-gray-500 dark:text-gray-400">
          Drag and drop / <FileUpload bind:files accept=".mokuro,.zip,.cbz" multiple
            >choose files</FileUpload
          > /
          <FileUpload bind:files webkitdirectory>choose directory</FileUpload>
        </p>
      {/if}
    </Dropzone>
    <p class=" text-sm text-gray-500 dark:text-gray-400 text-center">{storageSpace}</p>
    <div class="flex flex-1 flex-col gap-2">
      <Button outline on:click={reset} {disabled} color="dark">Reset</Button>
      <Button outline on:click={onUpload} {disabled}>Upload</Button>
    </div>
  {/await}
</Modal>
