<template>
  <div class="container">
    <div
      v-show="!isLoading"
      class="upload-area"
      :class="{ dragging: dragging }"
      @dragleave="dragLeave"
      @drop.prevent.stop="dragAsset"
      @dragover.prevent.stop="dragEnter"
    >
      <p>Drag Image(s) to Upload or</p>
      <ui-file-upload
        v-if="renderInput"
        label="Choose file(s)"
        name="file"
        accept="image/x-png,image/gif,image/jpeg"
        :multiple="true"
        @change="uploadImages"
      />
    </div>
    <div
      v-show="isLoading"
      class="upload-area"
    >
      <ui-progress-circular
        :size="50"
        type="determinate"
        :progress="progress"
      />
    </div>
  </div>
</template>
<script>

import { newImages, setOnUploadMetadataMutiple, setOnUploadMetadataSingle } from 'Api';
import { navigate } from 'Helpers/navigation';
import { ITEMS_PER_PAGE_OPTIONS } from 'Config';
import { hasStatusError, hasStatusCreated } from 'Helpers/api';

const { UiFileupload, UiProgressCircular } = window.kiln.utils.components;

export default {
  components: {
    'ui-file-upload': UiFileupload,
    'ui-progress-circular': UiProgressCircular
  },
  data() {
    return {
      dragging: false,
      uploadFileText: 'Choose file(s)',
      renderInput: true,
      filesResponses: 0,
      uploadedFiles: 0,
      isLoading: false
    };
  },
  computed: {
    progress() {
      return this.filesResponses > 0
        ? parseInt(this.filesResponses / this.uploadedFiles * 100, 10) : 0;
    }
  },
  methods: {
    /**
     * Show alert message
     * @param {string} text text to show
     * @param {string} type type of alert
     */
    alert(text, type) {
      this.$emit('alert', { text, type });
    },
    /**
     * Reset progress
     */
    resetProgress() {
      this.isLoading = false;
      this.filesResponses = 0;
      this.uploadedFiles = 0;
    },
    /**
     * Upload single file, open detail view after upload
     *
     * @param {File} file File to upload
     */
    uploadSingleFile(file) {
      newImages(file)
        .then((data) => {
          if (hasStatusError(data)) {
            this.alert(`${data.error}: ${data.message}`);
            this.clear();
            return;
          }

          if (!hasStatusCreated(data)) {
            this.$emit('assetExists', data.id);
            this.clear();
            return;
          }

          return setOnUploadMetadataSingle(data.id)
            .then((response) => {
              if (hasStatusError(response)) {
                this.alert(`${response.error}: ${response.message}`);
              }
            })
            .catch(this.error)
            .finally(() => {
              navigate.toDetail(data.id, this.$store);
              this.$emit('resetFilters');
              this.clear();
            });
        })
        .catch(this.error);
    },
    /**
     * Upload multiple files, stay in results view after upload
     *
     * @param {File} files Files to upload
     */
    uploadMultipleFiles(files) {
      const ids = [];

      this.uploadedFiles = files.length;
      this.isLoading = true;
      this.$emit('startFilesUpload');

      Object.keys(files).forEach((index) => {
        const item = files[index];

        newImages(item)
          .then((data) => {
            if (hasStatusError(data)) {
              this.alert(`${data.error}: ${data.message} (${item.name})`);
            } else {
              this.$emit('addAsset', data);
              ids.push(data.id);
            }

            this.filesResponses++;

            if (this.filesResponses === this.uploadedFiles) {
              return setOnUploadMetadataMutiple(ids)
                .then((resp) => {
                  resp.forEach((respData) => {
                    if (hasStatusError(respData)) {
                      this.alert(`${respData.error}: ${respData.message}`);
                    }
                  });

                  this.resetProgress();
                  this.clear();
                  this.$emit('endFilesUpload');
                })
                .catch(console.error);
            }
          })
          .catch((e) => {
            this.resetProgress();
            this.error(e);
          });
      });
    },

    /**
     * Upload assets to pyxis
     * @param {File[]} assets
     */
    handleAssetsUpload(assets) {
      if (!assets.length) {
        this.error(new Error('Could not upload file(s)'));
      }

      if (assets.length === 1) {
        this.uploadSingleFile(assets[0]);
      } else if (assets.length <= ITEMS_PER_PAGE_OPTIONS[ITEMS_PER_PAGE_OPTIONS.length - 1]) {
        this.uploadMultipleFiles(assets);
      } else {
        this.alert(`Batch size exceeds the allowable limit (${ITEMS_PER_PAGE_OPTIONS[ITEMS_PER_PAGE_OPTIONS.length - 1]})`);
      }
    },
    /**
     * Upload image to the service
     * Go to detail page on success
     * @param {File[]} files
     */
    uploadImages(files) {
      if (files.length) {
        this.handleAssetsUpload(files);
      }
    },
    /**
     * Handle drag enter
     */
    dragEnter() {
      this.dragging = true;
    },
    /**
     * Handle drag leave
     */
    dragLeave() {
      this.dragging = false;
    },
    /**
     * Handle on drag
     * @param  {Event} e DOM Event Object
     */
    dragAsset(e) {
      const { dataTransfer } = e,
        { files } = dataTransfer;

      this.dragging = false;

      if (files.length > 0) {
        this.handleAssetsUpload(files);
      }
    },
    /**
     * Clear file upload input
     */
    clear() {
      this.renderInput = false;

      this.$nextTick(() => {
        this.renderInput = true;
      });
    },
    /**
     * handle errors
     * @param {Error} err
     */
    error(err) {
      console.error(err);
      this.alert(`${err.message}`);
    }
  }
};
</script>
<style lang="scss" scoped>
  @import 'Styles/colors.scss';

  .container {
    height: 100%;
    width: 28em;
  }

  .upload-area {
    align-items: center;
    border: dashed 1px $black;
    border-radius: 3px;
    display: flex;
    flex-direction: column;
    height: 100%;
    justify-content: center;

    .ui-fileupload__icon {
      display: none;
    }

    > p {
      color: $border-color-darker;
      font-size: 20px;
      font-weight: bold;
    }

    &.dragging {
      background-color: $gray;
    }
  }

  /deep/ .ui-fileupload--type-primary {
    &.ui-fileupload--color-default {
      .ui-fileupload__content {
        font-weight: 600;
      }

      .ui-fileupload__icon {
        color: $border-color-darker;
      }
    }
  }
</style>
