<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'],
      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>