<template>
  <div
    class="main d-100 h-100"
    @dragover.prevent="dragOver = true"
    @dragenter.prevent="dragOver = true"
    @dragexit="dragOver = false"
    @dragleave="dragOver = false"
    @dragend="dragOver = false"
    @drop.prevent.stop="onFileDrop"
  >
    <div v-show="(isForm || _isUIAllowed('tableAttachment')) && dragOver" class="drop-overlay">
      <div>
        <v-icon small> mdi-cloud-upload-outline </v-icon>
        <span class="caption font-weight-bold">Drop here</span>
      </div>
    </div>

    <div class="d-flex align-center img-container">
      <div class="d-flex no-overflow">
        <div
          v-for="(item, i) in isPublicForm ? localFilesState : localState"
          :key="item.url || item.title"
          class="thumbnail align-center justify-center d-flex"
        >
          <v-tooltip bottom>
            <template #activator="{ on }">
              <v-img
                v-if="isImage(item.title, item.mimetype)"
                lazy-src="https://via.placeholder.com/60.png?text=Loading..."
                alt="#"
                max-height="99px"
                contain
                :src="item.url || item.data"
                v-on="on"
                @click="selectImage(item.url || item.data, i)"
              >
                <template #placeholder>
                  <v-skeleton-loader type="image" :height="active ? 33 : 22" :width="active ? 33 : 22" />
                </template>
              </v-img>
              <v-icon
                v-else-if="item.icon"
                :size="active ? 33 : 22"
                v-on="on"
                @click="openUrl(item.url || item.data, '_blank')"
              >
                {{ item.icon }}
              </v-icon>
              <v-icon v-else :size="active ? 33 : 22" v-on="on" @click="openUrl(item.url || item.data, '_blank')">
                mdi-file
              </v-icon>
            </template>
            <span>{{ item.title }}</span>
          </v-tooltip>
        </div>
      </div>
      <div
        v-if="isForm || (active && !isPublicGrid && !isLocked)"
        class="add d-flex align-center justify-center px-1 nc-attachment-add"
        @click="addFile"
      >
        <v-icon v-if="uploading" small color="primary" class="nc-attachment-add-spinner"> mdi-loading mdi-spin </v-icon>
        <v-btn v-else-if="isForm" outlined x-small color="" text class="nc-attachment-add-btn">
          <v-icon x-small color=""> mdi-plus </v-icon>
          Attachment
        </v-btn>
        <v-icon
          v-else-if="_isUIAllowed('tableAttachment')"
          v-show="active"
          small
          color="primary nc-attachment-add-icon"
        >
          mdi-plus
        </v-icon>
      </div>

      <v-spacer />

      <v-icon class="expand-icon mr-1" x-small color="primary" @click.stop="dialog = true"> mdi-arrow-expand </v-icon>
      <input ref="file" type="file" multiple class="d-none" @change="onFileSelection" />
    </div>
    <v-dialog v-if="dialog" v-model="dialog" width="800">
      <v-card class="h-100 images-modal">
        <v-card-text class="h-100 backgroundColor">
          <div class="d-flex mx-2">
            <v-btn
              v-if="(isForm || _isUIAllowed('tableAttachment')) && !isPublicGrid && !isLocked"
              small
              class="my-4"
              :loading="uploading"
              @click="addFile"
            >
              <v-icon small class="mr-2"> mdi-link-variant </v-icon>
              <span class="caption">Attach File</span>
            </v-btn>

            <!--            <v-text-field v-model="urlString" @keypress.enter="uploadByUrl" />-->
          </div>

          <div class="d-flex flex-wrap h-100">
            <v-container fluid style="max-height: calc(90vh - 80px); overflow-y: auto">
              <draggable v-model="localState" class="row" @update="onOrderUpdate">
                <v-col v-for="(item, i) in isPublicForm ? localFilesState : localState" :key="i" cols="4">
                  <v-card
                    class="modal-thumbnail-card align-center justify-center d-flex"
                    height="200px"
                    style="position: relative"
                  >
                    <v-icon
                      v-if="_isUIAllowed('tableAttachment') && !isPublicGrid && !isLocked"
                      small
                      class="remove-icon"
                      @click="removeItem(i)"
                    >
                      mdi-close-circle
                    </v-icon>
                    <v-icon color="grey" class="download-icon" @click.stop="downloadItem(item, i)">
                      mdi-download
                    </v-icon>
                    <div class="pa-2 d-flex align-center" style="height: 200px">
                      <img
                        v-if="isImage(item.title, item.mimetype)"
                        style="max-height: 100%; max-width: 100%"
                        alt="#"
                        :src="item.url || item.data"
                        @click="selectImage(item.url, i)"
                      />

                      <v-icon v-else-if="item.icon" size="33" @click="openUrl(item.url || item.data, '_blank')">
                        {{ item.icon }}
                      </v-icon>
                      <v-icon v-else size="33" @click="openUrl(item.url || item.data, '_blank')"> mdi-file </v-icon>
                    </div>
                  </v-card>
                  <p class="caption mt-2 modal-title" :title="item.title">
                    {{ item.title }}
                  </p>
                </v-col>
              </draggable>
            </v-container>
          </div>
        </v-card-text>
      </v-card>
    </v-dialog>

    <v-overlay v-if="showImage" v-model="showImage" z-index="99999" opacity=".93">
      <div v-click-outside="hideIfVisible" class="image-overlay-container">
        <template v-if="showImage && selectedImage">
          <v-carousel v-model="carousel" height="calc(100vh - 100px)" hide-delimiters>
            <v-carousel-item v-for="(item, i) in isPublicForm ? localFilesState : localState" :key="i">
              <div class="mx-auto d-flex flex-column justify-center align-center" style="min-height: 100px">
                <p class="title text-center">
                  {{ item.title }}
                  <v-icon class="ml-3" color="grey" @click.stop="downloadItem(item, i)"> mdi-download </v-icon>
                </p>
                <div style="width: 90vh; height: calc(100vh - 150px)" class="d-flex align-center justify-center">
                  <img
                    v-if="isImage(item.title, item.mimetype)"
                    style="max-width: 90vh; max-height: calc(100vh - 100px)"
                    :src="item.url || item.data"
                  />
                  <v-icon v-else-if="item.icon" size="55">
                    {{ item.icon }}
                  </v-icon>
                  <v-icon v-else size="55"> mdi-file </v-icon>
                </div>
              </div>
            </v-carousel-item>
          </v-carousel>
        </template>
        <v-sheet
          v-if="showImage"
          class="mx-auto align-center justify-center"
          max-width="90vw"
          height="80px"
          style="background: transparent"
        >
          <v-slide-group multiple show-arrows>
            <v-slide-item v-for="(item, i) in isPublicForm ? localFilesState : localState" :key="i">
              <v-card
                :key="i"
                class="ma-2 pa-2 d-flex align-center justify-center overlay-thumbnail"
                :class="{ active: carousel === i }"
                width="48"
                height="48"
                @click="carousel = i"
              >
                <img
                  v-if="isImage(item.title, item.mimetype)"
                  style="max-width: 100%; max-height: 100%"
                  :src="item.url || item.data"
                />
                <v-icon v-else-if="item.icon" size="48">
                  {{ item.icon }}
                </v-icon>
                <v-icon v-else size="48"> mdi-file </v-icon>
              </v-card>
            </v-slide-item>
          </v-slide-group>
        </v-sheet>
        <v-icon x-large class="close-icon" @click="showImage = false"> mdi-close-circle </v-icon>
      </div>
    </v-overlay>
  </div>
</template>

<script>
import FileSaver from 'file-saver';
import draggable from 'vuedraggable';
import { isImage } from '@/components/project/spreadsheet/helpers/imageExt';

export default {
  name: 'EditableAttachmentCell',
  components: { draggable },
  props: [
    'dbAlias',
    'value',
    'active',
    'isLocked',
    'meta',
    'column',
    'isPublicGrid',
    'isForm',
    'isPublicForm',
    'viewId',
  ],
  data: () => ({
    carousel: null,
    uploading: false,
    localState: '',
    dialog: false,
    showImage: false,
    selectedImage: null,
    dragOver: false,
    localFilesState: [],
    urlString: '',
  }),
  watch: {
    value(val, prev) {
      try {
        this.localState = ((typeof val === 'string' && val !== prev ? JSON.parse(val) : val) || []).filter(Boolean);
      } catch (e) {
        this.localState = [];
      }
    },
  },
  created() {
    try {
      this.localState = ((typeof this.value === 'string' ? JSON.parse(this.value) : this.value) || []).filter(Boolean);
    } catch (e) {
      this.localState = [];
    }
    document.addEventListener('keydown', this.onArrowDown);
  },
  beforeDestroy() {
    document.removeEventListener('keydown', this.onArrowDown);
  },
  mounted() {},
  methods: {
    async uploadByUrl() {
      const data = await this.$api.storage.uploadByUrl(
        {
          path: ['noco', this.projectName, this.meta.title, this.column.title].join('/'),
        },
        [
          {
            url: this.urlString,
          },
        ]
      );

      this.localState.push(...data);
    },
    openUrl(url, target) {
      window.open(url, target);
    },
    isImage,
    hideIfVisible() {
      if (this.showImage) {
        this.showImage = false;
      }
    },
    selectImage(selectedImage, i) {
      this.carousel = i;
      this.selectedImage = selectedImage;
      this.showImage = true;
    },
    addFile() {
      if (!this.isLocked) {
        this.$refs.file.click();
      }
    },
    async onFileSelection() {
      if (this.isPublicGrid) {
        return;
      }
      if (!this.$refs.file.files || !this.$refs.file.files.length) {
        return;
      }

      if (this.isPublicForm) {
        this.localFilesState.push(
          ...Array.from(this.$refs.file.files).map(file => {
            const res = { file, title: file.name };
            if (isImage(file.name, file.mimetype)) {
              const reader = new FileReader();
              reader.onload = e => {
                this.$set(res, 'data', e.target.result);
              };
              reader.readAsDataURL(file);
            }
            return res;
          })
        );

        this.$emit(
          'input',
          this.localFilesState.map(f => f.file)
        );
        return;
      }

      this.uploading = true;
      for (const file of this.$refs.file.files) {
        try {
          const data = await this.$api.storage.upload(
            {
              path: ['noco', this.projectName, this.meta.title, this.column.title].join('/'),
            },
            {
              files: file,
              json: '{}',
            }
          );

          this.localState.push(...data);
        } catch (e) {
          this.$toast.error(e.message || 'Some internal error occurred').goAway(3000);
          this.uploading = false;
          return;
        }
      }

      this.uploading = false;
      this.$emit('input', JSON.stringify(this.localState));
      this.$emit('update');
    },
    onOrderUpdate() {
      this.$emit('input', JSON.stringify(this.localState));
      this.$emit('update');
    },
    removeItem(i) {
      if (this.isPublicForm) {
        this.localFilesState.splice(i, 1);
        this.$emit(
          'input',
          this.localFilesState.map(f => f.file)
        );
      } else {
        this.localState.splice(i, 1);
        this.$emit('input', JSON.stringify(this.localState));
      }
      this.$emit('update');
    },
    downloadItem(item) {
      FileSaver.saveAs(item.url || item.data, item.title);
    },
    onArrowDown(e) {
      if (!this.showImage) {
        return;
      }
      e = e || window.event;
      // eslint-disable-next-line eqeqeq
      if (e.keyCode == '37') {
        this.carousel = (this.carousel || this.localState.length) - 1;
        // eslint-disable-next-line eqeqeq
      } else if (e.keyCode == '39') {
        this.carousel = ++this.carousel % this.localState.length;
        // eslint-disable-next-line eqeqeq
      } else if (e.keyCode == '27') {
        this.hideIfVisible();
      }
    },
    async onFileDrop(e) {
      this.dragOver = false;
      this.$refs.file.files = e.dataTransfer.files;
      await this.onFileSelection();
    },
  },
};
</script>

<style scoped lang="scss">
.img-container {
  margin: 0 -2px;
}

.no-overflow {
  overflow: hidden;
}

.add {
  transition: 0.2s background-color;
  /*background-color: #666666ee;*/
  border-radius: 4px;
  height: 33px;
  margin: 5px 2px;
}

.add:hover {
  /*background-color: #66666699;*/
}

.thumbnail {
  height: 99px;
  width: 99px;
  margin: 2px;
  border-radius: 4px;
}

.thumbnail img {
  /*max-height: 33px;*/
  max-width: 99px;
}

.main {
  min-height: 20px;
  position: relative;
  height: auto;
}

.expand-icon {
  margin-left: 8px;
  border-radius: 2px;
  /*opacity: 0;*/
  transition: 0.3s background-color;
}

.expand-icon:hover {
  /*opacity: 1;*/
  background-color: var(--v-primary-lighten4);
}

.modal-thumbnail img {
  height: 50px;
  max-width: 100%;
  border-radius: 4px;
}

.modal-thumbnail {
  position: relative;
  margin: 10px 10px;
}

.remove-icon {
  position: absolute;
  top: 5px;
  right: 5px;
}

.modal-thumbnail-card {
  .download-icon {
    position: absolute;
    bottom: 5px;
    right: 5px;
    opacity: 0;
    transition: 0.4s opacity;
  }

  &:hover .download-icon {
    opacity: 1;
  }
}

.image-overlay-container {
  max-height: 100vh;
  overflow-y: auto;
  position: relative;
}

.image-overlay-container .close-icon {
  position: fixed;
  top: 15px;
  right: 15px;
}

.overlay-thumbnail {
  transition: 0.4s transform, 0.4s opacity;
  opacity: 0.5;
}

.overlay-thumbnail.active {
  transform: scale(1.4);
  opacity: 1;
}

.overlay-thumbnail:hover {
  opacity: 1;
}

.modal-title {
  text-overflow: ellipsis;
  white-space: nowrap;
  width: 100%;
  overflow: hidden;
}

.modal-thumbnail-card {
  transition: 0.4s transform;
}

.modal-thumbnail-card:hover {
  transform: scale(1.05);
}

.drop-overlay {
  z-index: 5;
  position: absolute;
  width: 100%;
  height: 100%;
  left: 0;
  right: 0;
  top: 0;
  bottom: 5px;
  background: #aaaaaa44;
  display: flex;
  justify-content: center;
  align-items: center;
  pointer-events: none;
}

.expand-icon {
  opacity: 0;
  transition: 0.4s opacity;
}

.main:hover .expand-icon {
  opacity: 1;
}
</style>
<!--
/**
 * @copyright Copyright (c) 2021, Xgene Cloud Ltd
 *
 * @author Naveen MR <oof1lab@gmail.com>
 * @author Pranav C Balan <pranavxc@gmail.com>
 * @author Wing-Kam Wong <wingkwong.code@gmail.com>
 *
 * @license GNU AGPL version 3 or any later version
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */
-->
