<template>
  <div
    ref="pyxis-container"
    class="pyxis-container"
  >
    <div class="pyxis-alert-container">
      <ui-alert
        v-if="assetExistAlert.status"
        class="pyxis-alert"
        type="error"
        @dismiss="resetAssetExistAlert"
      >
        <span>Asset already exists.
          <span
            class="error-link"
            @click="gotToExistingAsset"
          >
            Go to asset page.
          </span>
        </span>
      </ui-alert>
      <div
        v-for="(alert, index) in alerts"
        :key="index"
        class="pyxis-alert"
      >
        <ui-alert
          :type="alert.type"
          :dismissible="alert.dismissible"
          @dismiss="dismissAlert(index)"
        >
          <span>{{ alert.text }}</span>
        </ui-alert>
      </div>
    </div>
    <SharedMetadata
      :asset-types="assetTypes"
      :selected-ids="selectedKeys"
      :provided-tags="checkboxTags"
      :metadata-modal-state="metadataModalState"
      @alert="createAlert"
      @closeAndRefresh="closeAndRefresh"
      @closeMetadataModal="closeMetadataModal"
      @editSelection="editSelection"
    />
    <Detail
      v-if="assetsId"
      :assets-id="assetsId"
      :previews="previews"
      :tags="checkboxTags"
      :asset-types="assetTypes"
      :master-crop-config="masterCropConfig"
      :validations="validations"
      @alert="createAlert"
      @clearAlerts="clearAlerts"
      @resetAlert="resetAlert"
      @showListView="showListView"
    />
    <List
      v-show="!assetsId"
      :assets-id="assetsId"
      :filtered-list="filteredList"
      :force-refresh="forceRefresh"
      :tags="tags"
      :assets="assets"
      :reset-dates-flag="resetDatesFlag"
      :reset-filters-on-upload="resetFiltersOnUpload"
      :items-per-page="itemsPerPage"
      :items-per-page-options="itemsPerPageOptions"
      :last-upload="lastUpload"
      :total="total"
      :thumbnail-rendition="thumbnailRendition"
      :selected="selected"
      :uploading-files="uploadingFiles"
      :users="users"
      @alert="createAlert"
      @itemClick="setAssetId"
      @itemSelect="selectItem"
      @resetForceRefresh="resetForceRefresh"
      @setAssets="setAssets"
      @setFiltersInUrl="setFiltersInUrl"
      @selectAll="selectAll"
      @deselectAll="resetForm"
      @scrollToTop="scrollToTop"
      @setTotal="setTotal"
      @setLastUpload="setLastUpload"
      @setItemsPerPage="setItemsPerPage"
      @openSelection="openSelection"
      @openMetadataModal="openMetadataModal"
    >
      <file-upload
        @addAsset="addAsset"
        @alert="createAlert"
        @assetExists="setAssetExistAlert"
        @endFilesUpload="endFilesUpload"
        @resetFilters="resetFilters"
        @startFilesUpload="startFilesUpload"
      />
    </List>
  </div>
</template>
<script>

import { ALERT_TYPES, ITEMS_PER_PAGE_OPTIONS, USERNAME } from 'Config';
import { DEFAULT_THUMBNAIL_RENDITION } from 'Config/constants';
import FileUpload from 'Components/list/FileUpload.vue';
import { navigate } from 'Helpers/navigation';
import {
  ensureUserExists,
  fetchUsers,
  fetchAllConfig
} from 'Api';
import { getStateUrlParameters, handleUsersRequest } from 'Helpers/api';
import { getPreviewSizes, getThumbnailRendition, formatMasterCropConfig } from 'Helpers/asset';
import Detail from 'Components/detail/Detail.vue';
import List from 'Components/list/List.vue';
import SharedMetadata from 'Components/list/SharedMetadata.vue';

const { UiAlert } = window.kiln.utils.components,
  CHECKBOX = 'checkbox';

export default {
  components: {
    Detail,
    List,
    SharedMetadata,
    UiAlert,
    FileUpload
  },
  data() {
    return {
      resetDatesFlag: false,
      error: null,
      alerts: [],
      itemsPerPageOptions: ITEMS_PER_PAGE_OPTIONS,
      itemsPerPage: ITEMS_PER_PAGE_OPTIONS[0],
      assets: [],
      lastUpload: false,
      selected: {},
      previews: {},
      tags: {},
      total: 0,
      metadataModalState: false,
      forceRefresh: false,
      uploadingFiles: false,
      shouldRefreshUsers: false,
      users: [],
      resetFiltersOnUpload: false,
      assetTypes: [],
      assetExistAlert: {
        status: false,
        id: ''
      },
      masterCropConfig: {},
      validations: {},
      thumbnailRendition: DEFAULT_THUMBNAIL_RENDITION
    };
  },
  computed: {
    assetsId() {
      const { tab, status, query } = getStateUrlParameters(this.$store);

      return tab === 'pyxis' && status === 'detail' ? query : '';
    },
    filteredList() {
      const { tab, status, query } = getStateUrlParameters(this.$store);

      return tab === 'pyxis' && status === 'list' ? query : '';
    },
    selectedKeys() {
      return Object.keys(this.selected);
    },
    checkboxTags() {
      return Object.entries(this.tags)
        .reduce((accum, [tagKey, value]) => {
          if (value.display === CHECKBOX) accum[tagKey] = value;

          return accum;
        }, {});
    }
  },
  mounted() {
    fetchAllConfig()
      .then((config) => {
        const {
          tags = {},
          previews = {},
          assetTypes = [],
          masterCrop = {},
          validations = {}
        } = config;

        this.tags = tags;
        this.previews = getPreviewSizes(previews);
        this.thumbnailRendition = getThumbnailRendition(previews);
        this.assetTypes = assetTypes;
        this.masterCropConfig = formatMasterCropConfig(masterCrop);
        this.validations = validations;
      })
      .catch(console.error);

    ensureUserExists(USERNAME);

    this.getUsers();
  },
  methods: {
    /**
     * Removes alert with given text
     * @param {string} text Text of alert to remove
     */
    resetAlert(text = '') {
      if (text) {
        const index = this.alerts.findIndex(alert => alert.text === text);

        if (index >= 0) this.dismissAlert(index);
      }
    },
    /**
     * Scrolls the container to the top
     * @param {number} offset
     */
    scrollToTop(offset = 0) {
      this.$nextTick(() => {
        this.$refs['pyxis-container'].scrollTop = offset;
      });
    },
    /**
     * Navigates to detail view of existing asset
     */
    gotToExistingAsset() {
      navigate.toDetail(this.assetExistAlert.id, this.$store);
      this.resetAssetExistAlert();
    },
    /**
     * Resets details for alert of existing asset to default values
     */
    resetAssetExistAlert() {
      this.assetExistAlert = {
        status: false,
        id: ''
      };
    },
    /**
     * Sets details for alert of existing asset
     * @param {string} id
     */
    setAssetExistAlert(id = '') {
      this.assetExistAlert = {
        status: true,
        id
      };
    },
    getUsers() {
      fetchUsers()
        .then((data) => {
          this.users = handleUsersRequest(data);
        });
    },
    /**
     * Sets up initial states for multiple file upload
     */
    startFilesUpload() {
      this.uploadingFiles = true;

      this.setAssets([]);
      this.setTotal(0);
      this.resetForm();
    },
    /**
     * Sets up final states for multiple file upload
     */
    endFilesUpload() {
      this.uploadingFiles = false;
      this.shouldRefreshUsers = true;

      if (!this.users.some(({ username }) => username === USERNAME.username)) {
        this.users = [...this.users, USERNAME];
      }

      this.selectAll();
    },
    /**
     * Sets state of metadata to true, so that modal opens
     */
    openMetadataModal() {
      this.metadataModalState = true;
    },
    /**
     * Sets state of metadata to false, so that modal closes
     */
    closeMetadataModal() {
      this.metadataModalState = false;
    },
    /**
     * Closes metadata modal and refresh to reset form.
     */
    closeAndRefresh() {
      this.closeMetadataModal();
      this.resetForm();
      this.forceRefresh = true;
    },
    /**
     * Sets state of metadata to false, so that modal closes and opens edit selection
     */
    editSelection() {
      this.metadataModalState = false;
      this.openSelection();
    },
    /**
     * Resets force refresh to false
     */
    resetForceRefresh() {
      this.forceRefresh = false;
    },
    /**
     * Resets form filters
     */
    resetForm() {
      this.selected = {};
    },
    /**
     * Navigate to the asset detail page
     * @param {Asset} id
     * @param {string} Asset.id
     */
    setAssetId({ id }) {
      this.clearAlerts();
      this.resetForm();

      navigate.toDetail(id, this.$store);
    },
    /**
     * @param {Object} alertDetails
     * @param {string} alertDetails.text
     * @param {string} alertDetails.type
     * @param {boolean} alertDetails.dismissible
     */
    createAlert({ text = '', type = ALERT_TYPES.ERROR, dismissible = true }) {
      this.alerts.push({
        text,
        type,
        dismissible
      });
    },
    resetFilters() {
      this.resetFiltersOnUpload = !this.resetFiltersOnUpload;
    },
    /**
     * dismiss an alert
     * @param {number} index
     */
    dismissAlert(index) {
      this.alerts = [
        ...this.alerts.slice(0, index),
        ...this.alerts.slice(index + 1)
      ];
    },
    /**
     * Clear all alerts
     */
    clearAlerts() {
      this.alerts = [];
    },
    /**
     * Open elements selected
     */
    openSelection() {
      navigate.toDetail(this.selectedKeys.join('&'), this.$store);
      this.resetForm();
    },
    /**
     * Set assets value
     * @param {Array} value Array of assets
     */
    setAssets(value) {
      this.assets = value;
    },
    /**
     * Sets the filters in the url
     * @param {Object} value Object with the properties to set in the url
     */
    setFiltersInUrl(value) {
      navigate.setFiltersInUrl(this.$store, value);
    },
    /**
     * Set total value to state
     * @param {int} value total of results
     */
    setTotal(value) {
      this.total = value;
    },
    /**
     * Set last upload value
     * @param {Boolean} value Whether or not last upload is set
     */
    setLastUpload(value) {
      this.lastUpload = value;
    },
    /**
     * Gets the respective page value, depending on the smalles fit
     * @returns {Array} array of items
     */
    getSmallestItemsPerPage() {
      const lastOption = [...this.itemsPerPageOptions].pop();

      return [...this.itemsPerPageOptions].reverse().reduce((accum, item) => {
        if (this.total <= item) {
          return item;
        }
        return accum;
      }, lastOption);
    },
    /**
     * Add asset to asset list
     *
     * @param {Object} item Item to add to asset list
     */
    addAsset(item) {
      this.assets.push(item);
      this.total += 1;
      this.itemsPerPage = this.getSmallestItemsPerPage();
    },
    /**
     * Add item to selected list
     * @param {Object} asset Selected asset
     */
    selectItem(asset) {
      const { [asset.id]: selectedId } = this.selected;

      if (selectedId) {
        const selection = Object.assign({}, this.selected);

        delete selection[selectedId];

        this.selected = selection;
      } else {
        this.selected = {
          ...this.selected,
          [asset.id]: asset.id
        };
      }
    },
    /**
     * Handle select all functionality
     */
    selectAll() {
      this.selected = this.assets.reduce((accum, item) => ({
        ...accum,
        [item.id]: item.id
      }), {});
    },
    /**
     * Sets Items per page
     * @param {int} value Value to set in items per page
     */
    setItemsPerPage(value) {
      this.resetForm();
      this.itemsPerPage = value;
    },
    /**
     * Shows List view in plugin page
     */
    showListView() {
      this.handleUsersUpdate();
      this.setLastUpload(false);
      this.resetDatesFlag = !this.resetDatesFlag;

      navigate.toList(this.$store);
    },
    /**
     * Handles users who have uploaded an asset update
     */
    handleUsersUpdate() {
      if (this.shouldRefreshUsers) {
        this.getUsers();

        this.shouldRefreshUsers = false;
      }
    }
  }
};
</script>
<style lang="scss" scoped>
  @import 'Styles/colors.scss';
  @import 'Styles/fonts.scss';

  .pyxis-container.nav-content {
    max-width: calc(100vw - 200px);
    overflow-y: auto;
    font: 500 12px/1 $default-font-family;
    font-family: $default-font-family;
    width: inherit;

    .ui-select__options {
      line-height: initial;
    }
  }

  .pyxis-alert-container {
    margin-left: calc(50% - 100px);
    position: fixed;
    top: 78px;
    transform: translateX(-50%);
    width: 768px;
    z-index: 2000;

    > .ui-alert:last-child {
      margin-bottom: 0;
    }
  }

  .pyxis-alert {
    background-color: #fff;
    margin-bottom: 10px;
  }

  .ui-alert {
    box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2),
    0 1px 5px 0 rgba(0, 0, 0, 0.12);
    max-width: 768px;
  }

  .error-link {
    cursor: pointer;
    text-decoration: underline;
    color: $orange-red;
  }
</style>
