<template>
  <Context
    ref="context"
    class="group-bys"
    :overflow-scroll="true"
    :max-height-if-outside-viewport="true"
  >
    <div>
      <div v-if="view.group_bys.length === 0" class="group_bys__none">
        <div class="group-bys__none-title">
          {{ $t('viewGroupByContext.noGroupByTitle') }}
        </div>
        <div class="group-bys__none-description">
          {{ $t('viewGroupByContext.noGroupByText') }}
        </div>
      </div>
      <div
        v-for="(groupBy, index) in view.group_bys"
        :key="groupBy.id"
        class="group-bys__item"
        :class="{
          'group-bys__item--loading': groupBy._.loading,
        }"
        :set="(field = getField(groupBy.field))"
      >
        <a
          v-if="!disableGroupBy"
          class="group-bys__remove"
          @click.stop="deleteGroupBy(groupBy)"
        >
          <i class="iconoir-cancel"></i>
        </a>
        <div class="group-bys__description">
          <template v-if="index === 0">{{
            $t('viewGroupByContext.groupBy')
          }}</template>
          <template v-if="index > 0">{{
            $t('viewGroupByContext.thenBy')
          }}</template>
        </div>
        <div class="group-bys__field">
          <Dropdown
            :value="groupBy.field"
            :disabled="disableGroupBy"
            :fixed-items="true"
            class="dropdown--floating dropdown--tiny"
            @input="updateGroupBy(groupBy, { field: $event })"
          >
            <DropdownItem
              v-for="field in fields"
              :key="'groupBy-field-' + groupBy.id + '-' + field.id"
              :name="field.name"
              :value="field.id"
              :disabled="groupBy.field !== field.id && !isFieldAvailable(field)"
            ></DropdownItem>
          </Dropdown>
        </div>
        <div
          class="group-bys__order"
          :class="{ 'group-bys__order--disabled': disableGroupBy }"
        >
          <a
            class="group-bys__order-item"
            :class="{ active: groupBy.order === 'ASC' }"
            @click="updateGroupBy(groupBy, { order: 'ASC' })"
          >
            <template v-if="getGroupByIndicator(field, 0) === 'text'">{{
              getGroupByIndicator(field, 1)
            }}</template>
            <i
              v-if="getGroupByIndicator(field, 0) === 'icon'"
              :class="getGroupByIndicator(field, 1)"
            ></i>

            <i class="iconoir-arrow-right"></i>

            <template v-if="getGroupByIndicator(field, 0) === 'text'">{{
              getGroupByIndicator(field, 2)
            }}</template>
            <i
              v-if="getGroupByIndicator(field, 0) === 'icon'"
              class="fa"
              :class="getGroupByIndicator(field, 2)"
            ></i>
          </a>
          <a
            class="group-bys__order-item"
            :class="{ active: groupBy.order === 'DESC' }"
            @click="updateGroupBy(groupBy, { order: 'DESC' })"
          >
            <template v-if="getGroupByIndicator(field, 0) === 'text'">{{
              getGroupByIndicator(field, 2)
            }}</template>
            <i
              v-if="getGroupByIndicator(field, 0) === 'icon'"
              :class="getGroupByIndicator(field, 2)"
            ></i>

            <i class="iconoir-arrow-right"></i>

            <template v-if="getGroupByIndicator(field, 0) === 'text'">{{
              getGroupByIndicator(field, 1)
            }}</template>
            <i
              v-if="getGroupByIndicator(field, 0) === 'icon'"
              :class="getGroupByIndicator(field, 1)"
            ></i>
          </a>
        </div>
      </div>
      <template
        v-if="view.group_bys.length < availableFieldsLength && !disableGroupBy"
      >
        <a
          ref="addContextToggle"
          class="group-bys__add"
          @click="
            $refs.addContext.toggle($refs.addContextToggle, 'bottom', 'left', 4)
          "
        >
          <i class="group-bys__add-icon iconoir-plus"></i>
          {{ $t('viewGroupByContext.addGroupBy') }}
        </a>
        <Context
          ref="addContext"
          class="group-bys__add-context"
          :overflow-scroll="true"
          :max-height-if-outside-viewport="true"
        >
          <ul ref="items" class="context__menu">
            <li
              v-for="field in fields"
              v-show="isFieldAvailable(field)"
              :key="field.id"
            >
              <a @click="addGroupBy(field)">
                <i
                  class="context__menu-icon"
                  :class="field._.type.iconClass"
                ></i>
                {{ field.name }}
              </a>
            </li>
          </ul>
        </Context>
      </template>
    </div>
  </Context>
</template>

<script>
import { notifyIf } from '@baserow/modules/core/utils/error'
import context from '@baserow/modules/core/mixins/context'

export default {
  name: 'ViewGroupByContext',
  mixins: [context],
  props: {
    fields: {
      type: Array,
      required: true,
    },
    view: {
      type: Object,
      required: true,
    },
    readOnly: {
      type: Boolean,
      required: true,
    },
    disableGroupBy: {
      type: Boolean,
      required: true,
    },
  },
  computed: {
    /**
     * Calculates the total amount of available fields.
     */
    availableFieldsLength() {
      return this.fields.filter(this.getCanGroupByInView).length
    },
  },
  methods: {
    getCanGroupByInView(field) {
      return this.$registry.get('field', field.type).getCanGroupByInView(field)
    },
    getField(fieldId) {
      for (const i in this.fields) {
        if (this.fields[i].id === fieldId) {
          return this.fields[i]
        }
      }
      return undefined
    },
    isFieldAvailable(field) {
      const allFieldIds = this.view.group_bys.map((groupBy) => groupBy.field)
      return this.getCanGroupByInView(field) && !allFieldIds.includes(field.id)
    },
    async addGroupBy(field) {
      this.$refs.addContext.hide()

      try {
        await this.$store.dispatch('view/createGroupBy', {
          view: this.view,
          values: {
            field: field.id,
            value: 'ASC',
          },
          readOnly: this.readOnly,
        })
        this.$emit('changed')
      } catch (error) {
        notifyIf(error, 'view')
      }
    },
    async deleteGroupBy(groupBy) {
      try {
        await this.$store.dispatch('view/deleteGroupBy', {
          view: this.view,
          groupBy,
          readOnly: this.readOnly,
        })
        this.$emit('changed')
      } catch (error) {
        notifyIf(error, 'view')
      }
    },
    async updateGroupBy(groupBy, values) {
      if (this.disableGroupBy) {
        return
      }

      try {
        await this.$store.dispatch('view/updateGroupBy', {
          groupBy,
          values,
          readOnly: this.readOnly,
        })
        this.$emit('changed')
      } catch (error) {
        notifyIf(error, 'view')
      }
    },
    getGroupByIndicator(field, index) {
      return this.$registry
        .get('field', field.type)
        .getGroupByIndicator(field, this.$registry)[index]
    },
  },
}
</script>