<script setup>
import { ref, defineProps, watch, onMounted } from "vue";
import { twMerge } from "tailwind-merge";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const props = defineProps({
  name: String,
  fileList: Array,
  getFileList: Function,
  multiple: Boolean,
  baseUrl: String,
  formats: { type: String, default: "txt、doc、xls、pdf、png、jpg、ppt、zip、rar" },
});

const acceptFileType = [
  ".csv",
  // https://stackoverflow.com/questions/11832930/html-input-file-accept-attribute-file-type-csv
  // Excel Files 97-2003
  "application/vnd.ms-excel",
  // Excel Files 2007+
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  "text/plain",
  "image/*",
  "application/pdf",
  // Microsoft Word -> https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept
  "application/msword",
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  "application/vnd.ms-powerpoint",
  ".ppt",
  ".pptx",
  ".zip",
  ".rar",
  "application/vnd.openxmlformats-officedocument.presentationml.presentation", // PowerPoint Files 2007+
  "application/zip", // ZIP Files
  "application/x-rar-compressed", // RAR Files
];

const loading = ref(false);

const fileInput = ref(null);

const fileCheck = (fileList) => {
  for (let { type, name } of fileList) {
    const ext = name.split(".")[name.split(".").length - 1];

    if (
      !acceptFileType.includes(type) &&
      !acceptFileType.includes(`.${ext}`) &&
      !type.match("image/*")
    ) {
      return false;
    }
  }

  return true;
};

const createPreviewImgURL = (file) => {
  loading.value = true;
  const src = URL.createObjectURL(file);
  return src;
};

const createPreviewFileURL = async (file) => {
  console.log(file);
  if (file) {
    let objectURL = "";
    if (file.lastModified) {
      objectURL = URL.createObjectURL(file);
    } else {
      const response = await fetch(`${props.baseUrl}/${file.src}`);
      const blob = await response.blob();
      objectURL = URL.createObjectURL(blob);
    }
    const link = document.createElement("a");
    link.href = objectURL;
    link.download = file.name;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  }
};

const handleMultipleFiles = (files) => {
  for (let file of files) {
    if (file.type?.match("image/*")) {
      file.src = createPreviewImgURL(file);
      console.log("File", file);
    }
  }
  if (props.multiple) {
    props.getFileList([...props.fileList, ...files]);
  } else {
    props.getFileList([files[0]]);
  }
};

const uploadFile = (e) => {
  console.log("Uploading file", e.target.files);
  const fileCheckIsSuccess = fileCheck(e.target.files);
  if (fileCheckIsSuccess) {
    handleMultipleFiles(e.target.files);
  }
};

const dragFile = (e) => {
  console.log(e.dataTransfer.files);
  const fileCheckIsSuccess = fileCheck(e.dataTransfer.files);
  if (fileCheckIsSuccess) {
    handleMultipleFiles(e.dataTransfer.files);
  }
};

const removeFile = (key) => {
  props.getFileList(
    props.fileList.filter(
      (f) => f.key !== key && f.lastModified !== key && f.id !== key
    )
  );
};

const focusInput = (e) => {
  if (e.constructor.name === "PointerEvent") {
    console.log(e, e.constructor.name);
    fileInput.value.focus();
    // 開啟選擇視窗
    var event = new MouseEvent("click", {
      view: window,
      bubbles: false,
      cancelable: true,
    });
    fileInput.value.dispatchEvent(event);
  }
};

const revokeURL = (src) => {
  console.log(props.fileList);
  loading.value = false;
  URL.revokeObjectURL(src);
};
</script>

<template>
  <label class="form-control w-full">
    <div class="label" @click.stop.prevent="() => {}">
      <span class="label-text text-lg"><slot name="topLeft"></slot></span>
      <span class="label-text-alt"> <slot name="topRight"></slot></span>
    </div>
    <div
      class="dropzone p-3 flex flex-col justify-center text-base min-h-[200px] border border-stone-900 shadow-lg rounded-md bg-sub-success bg-opacity-25"
      @click.stop.prevent="focusInput"
      @dragover.stop.prevent
    >
      <div @drop.stop.prevent="dragFile">
        <template v-if="fileList.length">
          <ul class="flex flex-wrap justify-start items-center">
            <li
              :class="
                twMerge(
                  'relative my-2 w-1/5 flex justify-center shadow rounded-lg mx-3 h-40',
                  file.lastModified ? 'bg-dark bg-opacity-50' : 'bg-sub-warning'
                )
              "
              v-for="file in fileList"
              :key="file.key || file.id || file.lastModified"
            >
              <button
                class="absolute z-30 text-2xl -top-3 right-0 w-10 h-10 rounded-full bg-error flex justify-center items-center"
                @click.stop.prevent="
                  () => {
                    removeFile(file.key || file.id || file.lastModified);
                  }
                "
              >
                <font-awesome-icon :icon="['fas', 'trash-alt']" />
              </button>
              <div
                v-if="
                  file.src &&
                  (file.type?.match('image/*') ||
                    file.ext?.match(/png|jpg|jpeg|gif|bmp/g))
                "
                class="w-full h-full z-10 absolute top-0 left-0 rounded-lg opacity-30"
                @click.stop.prevent="() => createPreviewFileURL(file)"
              >
                <img
                  v-if="file.id"
                  :src="`${baseUrl}/${file.src}`"
                  class="w-full h-full"
                />
                <img
                  v-else-if="file.lastModified"
                  class="w-full h-full"
                  :src="file.src"
                  @load="() => revokeURL(file.src)"
                  alt=""
                />
              </div>

              <div
                v-if="!loading"
                :class="
                  twMerge(
                    'relative cursor-pointer px-5 z-20 text-center text-white  flex flex-col justify-center w-full h-full'
                  )
                "
                @click.stop.prevent="() => createPreviewFileURL(file)"
              >
                <template
                  v-if="file.type?.match(/pdf/g) || file.ext?.match(/pdf/g)"
                >
                  <font-awesome-icon
                    class="mx-auto mb-2 text-4xl text-white"
                    :icon="['fas', 'file-pdf']"
                  />
                </template>
                <template
                  v-else-if="
                    file.type?.match(/excel|sheet/g) ||
                    file.ext?.match(/csv|xls/g)
                  "
                >
                  <font-awesome-icon
                    class="mx-auto mb-2 text-4xl text-white"
                    :icon="['fas', 'file-excel']"
                /></template>
                <template
                  v-else-if="
                    file.type?.match(/plain|word/g) ||
                    file.ext?.match(/doc|docx/g)
                  "
                >
                  <font-awesome-icon
                    class="mx-auto mb-2 text-4xl text-white"
                    :icon="['fas', 'file-word']"
                /></template>
                <template
                  v-else-if="
                    file.type?.match(/powerpoint/g) || file.ext?.match(/ppt/g)
                  "
                >
                  <font-awesome-icon
                    class="mx-auto mb-2 text-4xl text-white"
                    :icon="['fas', 'file-powerpoint']"
                  />
                </template>
                <template
                  v-else-if="file.type?.match(/zip|rar/g) || file.ext?.match(/zip|rar/g)"
                >
                  <font-awesome-icon
                    class="mx-auto mb-2 text-4xl text-white"
                    :icon="['fas', 'file-archive']"
                  />
                </template>
                <template
                  v-else-if="
                    !file.type?.match('image/*') &&
                    !file.ext?.match(/png|jpg|jpeg|gif|bmp/g)
                  "
                >
                  <font-awesome-icon
                    class="mx-auto mb-2 text-4xl text-white"
                    :icon="['fas', 'file-alt']"
                  />
                </template>
                <p class="font-bold mb-3" v-if="file.size">
                  {{ (file.size / 1000).toFixed(1) }} KB
                </p>
                <p class="truncate font-extrabold">{{ file.name }}</p>
              </div>
              <span
                v-else
                class="loading loading-dots loading-lg text-slate-800"
              ></span>
            </li>
          </ul>
        </template>
        <div class="w-full text-center" v-else>
          <div>
            <font-awesome-icon size="2x" :icon="['fas', 'cloud-upload-alt']" />
          </div>
          <p class="text-2xl my-2">{{ $t("upload.title") }}</p>
          <p class="mb-0 col-grey">{{ $t("upload.description") }}</p>
          <p class="mb-0 col-grey">
            {{ $t("upload.formats") }} : {{ props.formats }}
          </p>
        </div>
      </div>

      <!-- :accept="acceptFileType.join(',')" -->
      <input
        type="file"
        :name="name || 'file'"
        ref="fileInput"
        :multiple="multiple"
        class="h-0"
        @change="uploadFile"
      />
    </div>
    <div class="">
      <span class="label-text-alt"> <slot name="bottomLeft"></slot></span>
      <span class="label-text-alt"> <slot name="bottomRight"></slot></span>
    </div>
  </label>
</template>

<style lang="scss" scoped></style>
