<template>
  <div class="flex-1 auto-overflow flex flex-column flex-nowrap rel">
    <div
      v-show="error.type"
      class="flex-auto top-padding-medium horizontal-padding-medium full-width abs"
      style="z-index: 10"
    >
      <base-alert :apperance="error.type" @close="error = {}" class="shadow-large">
        {{ error.message }}
      </base-alert>
    </div>

    <div
      v-if="files.length === 0"
      class="flex flex-column flex-nowrap full-height rel hidden-overflow"
    >
      <div class="flex-1 flex flex-column flex-nowrap center-xs middle-xs">
        <i
          class="fas fa-file-upload bigger-text-medium text-gray bottom-padding-medium"
        ></i>
        <span class="bigger-text-x-small text-dark">Arraste os arquivos para cá</span>
        <span class="text-medium text-gray vertical-padding-medium">ou</span>
        <base-button size="small" class="bottom-margin-x-large"
          >Selecione do computador</base-button
        >
        <input
          multiple
          type="file"
          @change="previewFiles"
          class="full-width full-height center-middle-absolute cursor-pointer"
          style="opacity: 0"
          ref="inputFile"
        />
      </div>
      <div class="flex-auto padding-medium text-center">
        <span class="text-small text-gray visible-inline-block">
          Arquivos permitidos: {{ allowedExtensions.join(", ") }}
        </span>
      </div>
    </div>

    <div v-else class="flex flex-column flex-nowrap full-height">
      <div
        v-show="enableClipping"
        class="flex-auto flex flex-row center-xs middle-xs full-width padding-small background-white bottom-border-gray"
      >
        <base-button
          apperance="outline"
          size="small"
          class="right-margin-small"
          @click.native="enableClipping = false"
        >
          Cancelar
        </base-button>
        <base-button size="small" @click.native="onClipping"> Aplicar </base-button>
      </div>

      <div
        v-show="!enableClipping"
        class="flex-auto flex flex-row flex-nowrap center-xs middle-xs full-width vertical-padding-small horizontal-padding-medium background-white bottom-border-gray"
      >
        <div class="flex-1 right-padding-small">
          <base-input
            type="text"
            v-model="selectedFile.name"
            @input="onInput"
            size="small"
            :error="selectedFile.error"
          />
        </div>

        <div
          v-show="
            selectedFile.src.original !== selectedFile.src.final &&
            selectedFile.extension !== 'pdf'
          "
          class="flex-auto right-padding-small"
        >
          <base-button apperance="outline" square size="small" @click.native="onHistory">
            <template #icon>
              <i class="fas fa-history"></i>
            </template>
          </base-button>
        </div>

        <div
          v-show="selectedFile.extension !== 'pdf'"
          class="flex-auto right-padding-small"
        >
          <base-button
            apperance="outline"
            square
            size="small"
            @click.native="enableClipping = true"
          >
            <template #icon>
              <i class="fas fa-crop-alt"></i>
            </template>
          </base-button>
        </div>

        <div class="flex-auto">
          <base-button
            apperance="outline"
            square
            size="small"
            @click.native="onRemoveFile"
          >
            <template #icon>
              <i class="fas fa-trash"></i>
            </template>
          </base-button>
        </div>
      </div>

      <div
        v-if="selectedFile.extension === 'pdf'"
        class="flex-1 flex flex-row center-xs middle-xs full-width hidden-overflow padding-medium"
      >
        <div
          class="background-white border-gray rel full-height"
          style="width: 12.5rem; max-height: 18rem"
        >
          <i
            class="fas fa-file-pdf bigger-text-x-large text-dark center-middle-absolute"
          />
        </div>
      </div>
      <div
        v-else
        class="flex-1 flex flex-row center-xs middle-xs full-width hidden-overflow padding-medium"
      >
        <div
          v-if="enableClipping"
          ref="containerClipper"
          class="flex-1 flex flex-row center-xs middle-xs full-width full-height"
        >
          <cropper
            ref="cropper"
            :src="selectedFile.src.final"
            :auto-zoom="true"
            :transitions="true"
            :resize-image="{
              adjustStencil: true,
            }"
            image-restriction="fit-area"
            default-boundaries="fill"
          />
        </div>
        <img v-else :src="selectedFile.src.final" class="image-contain" />
      </div>

      <div
        v-if="!enableClipping"
        class="flex-auto flex flex-row center-xs middle-xs full-width horizontal-padding-medium bottom-padding-medium"
      >
        <div
          v-for="(fileItem, fileIndex) in files"
          :key="fileIndex"
          class="background-white hover:border-primary cursor-pointer margin-x-small rel"
          :class="[
            { 'border-primary': fileItem.selected },
            { 'border-gray': !fileItem.selected && !fileItem.error },
            { 'border-error': !fileItem.selected && fileItem.error },
          ]"
          style="width: 40px; height: 40px"
          @click="onSelectFile(fileIndex)"
          :title="fileItem.name + '.' + fileItem.extension"
        >
          <i
            v-if="fileItem.extension === 'pdf'"
            class="fas fa-file-pdf text-medium text-gray cursor-pointer center-middle-absolute"
          />
          <img
            v-else
            :src="fileItem.src.final"
            :class="['image-cover', { 'opacity-5': fileItem.selected }]"
          />
        </div>
        <div
          class="background-white border-gray hover:border-primary cursor-pointer margin-x-small rel"
          style="width: 40px; height: 40px"
          title="Selecionar do computador"
        >
          <i
            class="fas fa-file-upload text-medium text-gray cursor-pointer center-middle-absolute"
          ></i>
          <input
            multiple
            type="file"
            @change="previewFiles"
            class="full-width full-height center-middle-absolute cursor-pointer"
            style="opacity: 0"
            ref="inputFile"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import BaseInput from "@elements/BaseInput/index.vue";
import BaseButton from "@elements/BaseButton/index.vue";
import BaseAlert from "@elements/BaseAlert/index.vue";

import { Cropper } from "vue-advanced-cropper";

export default {
  name: "TheUpload",
  components: {
    BaseInput,
    BaseButton,
    BaseAlert,
    Cropper,
  },
  props: {
    folderFiles: {
      type: Array,
      default: [],
    },
  },
  data() {
    return {
      files: [],
      error: {},
      enableClipping: false,
      // allowedExtensions: ["jpg", "jpeg", "png", "pdf"],
      allowedExtensions: window.location.href.includes("route=catalog/pdf_upload") ? ["pdf"] : ["jpg", "jpeg", "png", "pdf"],
      maximumAllowedDimensions: [1920, 1920],
    };
  },
  computed: {
    selectedFile() {
      return this.files.find((fileItem) => fileItem.selected);
    },
    selectedFileIndex() {
      return this.files.findIndex((fileItem) => fileItem.selected);
    },
    uploadFiles() {
      return this.files.map((fileItem) => {
        return {
          name: fileItem.name,
          file: fileItem.src.final,
        };
      });
    },
  },
  watch: {
    files() {
      this.$emit("has-image-to-send", this.files.length > 0);
      this.$emit("upload-files", this.uploadFiles);
    },
    enableClipping() {
      this.$emit("has-image-to-send", this.files.length > 0 && !this.enableClipping);
    },
  },
  mounted() {
    this.files = [];
  },
  methods: {
    handleErrorFileName(fileName) {
      fileName = fileName
        ? fileName
        : this.selectedFile.name + "." + this.selectedFile.extension;

      const name = fileName.split(".").slice(0, -1).join(".");
      if (!name || !/^[A-Za-z0-9_-]*$/.test(name)) {
        return "O nome deve ter apenas letras, números e traços";
      }

      const fileNameAlreadyExists = this.folderFiles.find(
        (folderFilesItem) => folderFilesItem.filename === fileName
      );

      return fileNameAlreadyExists ? "Já existe um arquivo com este nome" : "";
    },
    previewFiles(event) {
      if (!event.target.files) {
        return;
      }

      this.error = {};
      const selectedFiles = Array.from(event.target.files);

      const selectedFilesPreview = selectedFiles.map((filesItem) => {
        const name = filesItem.name.split(".").slice(0, -1).join(".");
        // const extension = filesItem.type.split("/")[1];
        const type = filesItem.type.split("/")[0];
        const extension = filesItem.name.split(".").pop();

        const errorFileName = this.handleErrorFileName(filesItem.name);

        const ensureAllowExtensions = this.allowedExtensions.find(
          (allowedExtensionItem) => allowedExtensionItem === extension
        );

        return new Promise((resolve, reject) => {
          if (!ensureAllowExtensions) {
            reject({
              type: "error",
              message: `Arquivos permitidos: ${this.allowedExtensions.join(", ")}`,
            });
          }

          if (type === "image") {
            const image = new Image();

            image.onload = () => {
              const { width, height } = image;

              if (
                width > this.maximumAllowedDimensions[0] ||
                height > this.maximumAllowedDimensions[1]
              ) {
                reject({
                  type: "error",
                  message: `Dimensões máxima permitida: ${this.maximumAllowedDimensions.join(
                    "x"
                  )}`,
                });
              }

              fileToBase64({
                width: {
                  original: width,
                  final: width,
                },
                height: {
                  original: height,
                  final: height,
                },
              });
            };

            image.onerror = () => {
              reject({
                type: "error",
                message: "Erro ao carregar a imagem",
              });
            };

            image.src = window.URL.createObjectURL(filesItem);
          } else {
            fileToBase64();
          }

          function fileToBase64(props) {
            const reader = new FileReader();
            reader.readAsDataURL(filesItem);
            reader.onloadend = function () {
              const base64data = reader.result;
              let result = {
                selected: false,
                name,
                extension,
                error: errorFileName,
                src: {
                  original: base64data,
                  final: base64data,
                },
              };

              if (props) {
                const { width, height } = props;
                result = { ...result, width, height };
              }

              resolve(result);
            };
          }
        });
      });

      Promise.all(selectedFilesPreview)
        .then((values) => {
          const files = [...this.files, ...values];

          this.files = files.map((filesItem, filesItemIndex) => {
            filesItem.selected = filesItemIndex === 0;
            if (filesItem.error !== "") {
              this.$emit("disabled-send-button", true);
            }
            return filesItem;
          });
        })
        .catch((data) => {
          console.log(data);
          this.error = data;
        })
        .then(() => {
          this.$refs.inputFile.type = "text";
          this.$refs.inputFile.type = "file";
        });
    },
    onSelectFile(filesItemIndex) {
      const files = this.files.map((filesItem) => {
        filesItem.selected = false;
        return filesItem;
      });

      files[filesItemIndex].selected = true;

      this.files = files;
    },
    onRemoveFile() {
      this.files.splice(this.selectedFileIndex, 1);
      if (this.files[0]) {
        this.files[0].selected = true;
      }
    },
    onClipping() {
      this.enableClipping = false;
      const { coordinates, canvas } = this.$refs.cropper.getResult();
      this.files[this.selectedFileIndex].width.final = coordinates.width;
      this.files[this.selectedFileIndex].height.final = coordinates.height;
      this.files[this.selectedFileIndex].src.final = canvas.toDataURL();
      this.files = [...this.files];
    },
    onHistory() {
      this.files[this.selectedFileIndex].src.final = this.files[
        this.selectedFileIndex
      ].src.original;
      this.files[this.selectedFileIndex].width.final = this.files[
        this.selectedFileIndex
      ].width.original;
      this.files[this.selectedFileIndex].height.final = this.files[
        this.selectedFileIndex
      ].height.original;
      this.files = [...this.files];
    },
    onInput() {
      this.files[this.selectedFileIndex].error = this.handleErrorFileName();

      const filesError = this.files.filter((filesItem) => filesItem.error);
      if (filesError.length > 0) {
        this.$emit("disabled-send-button", true);
      } else {
        this.$emit("disabled-send-button", false);
      }

      this.$emit("upload-files", this.uploadFiles);
    },
  },
};
</script>
