<template>
  <div>
    <q-drawer
      v-model="rightDrawerOpen"
      content-class="bg-grey-2"
      side="right"
      elevated>
      <div class="q-pa-md">
        <div class="q-mb-xs text-caption text-grey-7">
          {{$t('category')}}
          <q-icon
            v-if="category"
            style="font-size: 1.3em;"
            name="cancel"
            class="cursor-pointer"
            :title="$t('deleteFilter')"
            :to="{params: {category: null}}"
          />
        </div>
        <div>
          <q-btn
            flat
            class="category q-pa-sm"
            v-for="cat in categories"
            :class="{active: category == cat.id}"
            :key="cat.id"
            :title="cat.name"
            :to="{params: {category: cat.id}}">
            <img
              class="category-img"
              :src="`statics/category/${cat.id}.svg`">
          </q-btn>
        </div>
        <q-select
          v-model="type"
          option-value="id"
          option-label="name"
          :options="types"
          :disable="!category"
          clearable
          :label="$t('family')"
          @filter="filterType"
        />
      </div>
      <q-separator />
      <div class="q-pa-md">
        <q-select
          v-model="order"
          input-debounce="0"
          :options="orderOptions"
          :label="$t('orderBy')"
        />
        <q-input
          v-model="date"
          mask="date"
          :rules="['date']"
          :label="$t('deliveryDate')">
          <template v-slot:append>
            <q-icon name="event" class="cursor-pointer">
              <q-popup-proxy ref="qDateProxy" anchor="bottom left" self="top middle">
                <q-date v-model="date" @input="() => $refs.qDateProxy.hide()" />
              </q-popup-proxy>
            </q-icon>
          </template>
        </q-input>
      </div>
      <q-separator />
      <div class="q-pa-md"
        v-if="type || search">
        <div class="q-mb-md"
          v-for="tag in tags"
          :key="tag.uid">
          <div class="q-mb-xs text-caption text-grey-7">
            {{tag.name}}
            <q-icon
              v-if="tag.filter.length || tag.filter.min || tag.filter.max"
              style="font-size: 1.3em;"
              name="cancel"
              :title="$t('deleteFilter')"
              class="cursor-pointer"
              @click="onResetTagFilterClick(tag)"
            />
          </div>
          <div v-if="!tag.useRange">
            <div
              v-for="value in tag.values.slice(0, tag.showCount)"
              :key="value">
              <q-checkbox
                v-model="tag.filter"
                :dense="true"
                :val="value"
                :label="value"
                @input="loadItems"
              />
            </div>
            <div v-if="tag.values.length > tag.showCount">
              <span
                class="cursor-pointer text-blue"
                @click="tag.showCount = Infinity">
                <q-icon name="keyboard_arrow_down" />
                {{$t('viewMore')}}
              </span>
            </div>
            <div v-if="tag.showCount == Infinity">
              <span
                class="cursor-pointer text-blue"
                @click="tag.showCount = tag.initialCount">
                <q-icon name="keyboard_arrow_up" />
                {{$t('viewLess')}}
              </span>
            </div>
          </div>
          <div class="q-mx-md">
            <q-range
              class="q-mt-lg"
              v-if="tag.useRange"
              v-model="tag.filter"
              :min="tag.min"
              :max="tag.max"
              :step="tag.step"
              @input="loadItemsDelayed"
              @change="loadItems"
              label-always
              markers
              snap
            />
          </div>
        </div>
      </div>
    </q-drawer>
    <q-infinite-scroll
      @load="onLoad"
      scroll-taget="html"
      :offset="800"
      :disable="disableScroll">
      <div class="q-pa-md row justify-center q-gutter-md">
        <q-spinner
          v-if="isLoading"
          color="primary"
          size="50px">
        </q-spinner>
        <q-card
          class="my-card"
          v-for="item in items"
          :key="item.id">
          <img :src="`${$imageBase}/catalog/200x200/${item.image}`" />
          <q-card-section>
            <div class="name text-subtitle1">{{item.longName}}</div>
            <div class="text-uppercase text-subtitle1 text-grey-7">
              {{item.subName}}
            </div>
          </q-card-section>
          <q-card-section class="tags">
            <div v-for="tag in item.tags" :key="tag.tagFk">
              <span class="text-grey-7">{{tag.tag.name}}</span> {{tag.value}}
            </div>
          </q-card-section>
          <q-card-actions class="actions justify-between">
            <div class="q-pl-sm">
              <span class="available bg-green text-white">{{item.available}}</span>
              {{$t('from')}}
              <span class="price">{{item.inbounds[0].buy && item.inbounds[0].buy.price3 | currency}}</span>
            </div>
            <q-btn flat>{{$t('buy')}}</q-btn>
          </q-card-actions>
        </q-card>
      </div>
      <template slot="loading">
        <div class="row justify-center q-my-md">
          <q-spinner color="primary" name="dots" size="40px" />
        </div>
      </template>
    </q-infinite-scroll>
  </div>
</template>

<style lang="stylus" scoped>
  .my-card
    width 100%
    max-width 21em
    height 38em
    overflow hidden
    .name
      white-space nowrap
      overflow hidden
      text-overflow ellipsis
    .description
      height 40px
      overflow hidden
  .category
    width 25%
    &.active
      background: rgba(0, 0, 0, .08)
  .category-img
    height 3.5em
  .tags
    max-height 6.2em
    overflow hidden
  .available
    padding .15em
    border-radius .2em
    font-size 1.3em
  .price
    font-size 1.3em
  .actions
    position absolute
    bottom 0
    width 100%
</style>

<script>
import { date } from 'quasar'
import axios from 'axios'

const CancelToken = axios.CancelToken

export default {
  name: 'Catalog',
  data () {
    return {
      uid: 0,
      search: null,
      date: date.formatDate(new Date(), 'YYYY/MM/DD'),
      category: null,
      categories: [],
      tags: [],
      type: null,
      types: [],
      orgTypes: [],
      isLoading: false,
      items: null,
      rightDrawerOpen: this.$q.platform.is.desktop,
      pageSize: 24,
      limit: null,
      maxTags: 5,
      disableScroll: true,
      order: {
        label: this.$t('name'),
        value: 'name'
      },
      orderOptions: [
        {
          label: this.$t('name'),
          value: 'longName'
        }, /* {
          label: this.$t('priceAsc'),
          value: 'price ASC'
        }, {
          label: this.$t('priceDesc'),
          value: 'price DESC'
        }, {
          label: this.$t('available'),
          value: 'available'
        }, */ {
          label: this.$t('siceAsc'),
          value: 'size ASC'
        }, {
          label: this.$t('sizeDesc'),
          value: 'size DESC'
        }
      ]
    }
  },
  mounted () {
    this.$axios.get('ItemCategories')
      .then(res => (this.categories = res.data))
  },
  beforeDestroy () {
    this.clearTimeoutAndRequest()
  },
  watch: {
    order () {
      this.loadItems()
    },
    date () {
      this.loadItems()
    },
    type (type) {
      this.$router.push({
        params: {
          category: this.category,
          type: type && type.id
        }
      })
      this.$state.subtitle = type && type.name
      this.$state.search = ''
      this.loadItems()
    },
    '$state.search': function (value) {
      if (!value) this.loadItems()
      else this.loadItemsDelayed()
    },
    '$route.params.category': function (categoryId) {
      let category = this.categories.find(i => i.id === categoryId)

      if (category) {
        this.$state.title = category.name
        this.$state.titleColor = `#${category.color}`
      } else {
        this.$state.title = this.$t(this.$router.currentRoute.name)
        this.$state.titleColor = null
      }

      this.category = categoryId
      this.type = null

      let params = { filter: { where: { categoryFk: categoryId } } }
      this.$axios.get('ItemTypes', { params })
        .then(res => (this.orgTypes = res.data))
    },
    '$route.params.type': function (type) {
      if (!this.type) this.type = { id: type }
    }
  },
  methods: {
    loadItemsDelayed () {
      this.clearTimeoutAndRequest()
      this.timeout = setTimeout(() => this.loadItems(), 500)
    },
    clearTimeoutAndRequest () {
      if (this.timeout) {
        clearTimeout(this.timeout)
        this.timeout = null
      }
      if (this.source) {
        this.source.cancel()
        this.source = null
      }
    },
    loadItems () {
      this.items = []
      this.isLoading = true
      this.limit = this.pageSize
      this.disableScroll = false
      this.loadItemsBase()
        .finally(() => {
          this.isLoading = false
        })
    },
    onLoad (index, done) {
      if (this.isLoading) return done()
      this.limit += this.pageSize
      this.loadItemsBase()
        .finally(() => done())
    },
    loadItemsBase () {
      this.clearTimeoutAndRequest()

      if (!this.type) {
        return Promise.resolve(true)
      }

      let typeFk
      let tagFilter = []

      for (let tag of this.tags) {
        if (this.hasFilters(tag)) {
          tagFilter.push({
            tagFk: tag.id,
            values: tag.filter
          })
        }
      }

      if (this.type) {
        typeFk = this.type.id
      }

      this.source = CancelToken.source()

      let params = {
        dated: this.date,
        typeFk: typeFk,
        search: this.$state.search,
        order: this.order.value,
        tagFilter: tagFilter,
        limit: this.limit
      }
      let config = {
        params,
        cancelToken: this.source.token
      }
      return this.$axios.get('Items/catalog', config)
        .then(res => this.onItemsGet(res))
        .catch(err => { if (!err.__CANCEL__) throw err })
        .finally(() => (this.cancel = null))
    },
    onItemsGet (res) {
      for (let tag of res.data.tags) {
        tag.uid = this.uid++

        if (tag.filter) {
          tag.useRange =
            tag.filter.max ||
            tag.filter.min
        } else {
          tag.useRange = tag.isQuantitative &&
            tag.values.length > this.maxTags
          this.resetTagFilter(tag)
        }

        if (tag.values) {
          tag.initialCount = this.maxTags
          if (Array.isArray(tag.filter)) {
            tag.initialCount = Math.max(tag.initialCount, tag.filter.length)
          }
          tag.showCount = tag.initialCount
        }
      }

      this.items = res.data.items
      this.tags = res.data.tags
      this.disableScroll = this.items.length < this.limit
    },
    resetTagFilter (tag) {
      if (tag.useRange) {
        tag.filter = {
          min: null,
          max: null
        }
      } else {
        tag.filter = []
      }
    },
    onResetTagFilterClick (tag) {
      this.resetTagFilter(tag)
      this.loadItems()
    },
    hasFilters (tag) {
      let filter = tag.filter
      return filter.length || filter.min || filter.max
    },
    filterType (val, update) {
      if (val === '') {
        update(() => { this.types = this.orgTypes })
      } else {
        update(() => {
          const needle = val.toLowerCase()
          this.types = this.orgTypes.filter(type =>
            type.name.toLowerCase().indexOf(needle) > -1)
        })
      }
    }
  },
  filters: {
    currency: i => i ? i.toFixed(2) + '€' : i
  }
}
</script>
