<template>
  <div style="padding-bottom: 5em;">
    <portal place="top">
      <q-input
        v-model="search"
        debounce="500"
        class="q-mr-sm"
        dark
        dense
        standout>
        <template v-slot:append>
          <q-icon
            v-if="search === ''"
            name="search"
          />
          <q-icon
            v-else
            name="clear"
            class="cursor-pointer"
            @click="search = ''"
          />
        </template>
      </q-input>
    </portal>
    <q-drawer
      v-model="$state.rightDrawerOpen"
      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')"
            @click="$router.push({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, type: null}}">
            <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"
          @input="$router.push({params: {type: type && type.id}})"
        />
      </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="typeId || 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.hasFilter"
              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="onCheck(tag)"
              />
            </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"
              :color="tag.hasFilter ? 'primary' : 'grey-6'"
              @input="onRangeChange(tag, true)"
              @change="onRangeChange(tag)"
              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>
        <div
          v-if="items && !items.length"
          class="text-subtitle1 text-grey-7 q-pa-md">
          {{$t('noItemsFound')}}
        </div>
        <div
          v-if="!items && !isLoading"
          class="text-subtitle1 text-grey-7 q-pa-md">
          {{$t('pleaseSetFilter')}}
        </div>
        <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="sub-name text-uppercase text-subtitle1 text-grey-7 ellipsize q-pt-xs">
              {{item.subName}}
            </div>
            <div class="tags q-pt-xs">
              <div v-for="tag in item.tags" :key="tag.tagFk">
                <span class="text-grey-7">{{tag.tag.name}}</span> {{tag.value}}
              </div>
            </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.buy && item.buy.price3 | currency}}</span>
            </div>
            <q-btn
              icon="add_shopping_cart"
              :title="$t('buy')"
              @click="showItem(item)"
              flat>
            </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>
    <q-dialog v-model="showItemDialog">
      <q-card style="width: 25em;">
        <q-img
          :src="`${$imageBase}/catalog/200x200/${item.image}`"
          :ratio="5/3">
          <div class="absolute-bottom text-center q-pa-xs">
            <div class="text-subtitle1">
              {{item.longName}}
            </div>
          </div>
        </q-img>
        <q-card-section>
          <div class="text-uppercase text-subtitle1 text-grey-7 ellipsize">
            {{item.subName}}
          </div>
          <div class="text-grey-7">
             #{{item.id}}
          </div>
        </q-card-section>
        <q-card-section>
          <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 align="right">
          <q-btn
            @click="showItemDialog = false"
            flat>
            {{$t('cancel')}}
          </q-btn>
          <q-btn
            @click="showItemDialog = false"
            flat>
            {{$t('accept')}}
          </q-btn>
        </q-card-actions>
      </q-card>
    </q-dialog>
    <q-page-sticky position="bottom-right" :offset="[18, 18]">
      <q-btn
        fab
        icon="shopping_basket"
        color="accent"
        :to="{name: 'orders'}"
        :title="$t('orders')"/>
    </q-page-sticky>
  </div>
</template>

<style lang="stylus" scoped>
  .my-card
    width 100%
    max-width 17.5em
    height 32.5em
    overflow hidden
    .name, .sub-name
      line-height 1.3em
    .ellipsize
      white-space nowrap
      overflow hidden
      text-overflow ellipsis
    .description
      height 40px
      overflow hidden
  .category
    width 33%
    &.active
      background rgba(0, 0, 0, .08)
  .category-img
    height 3.5em
  .tags
    max-height 4.6em
    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 Page from 'components/Page'
import { date } from 'quasar'
import axios from 'axios'

const CancelToken = axios.CancelToken

export default {
  name: 'Catalog',
  mixins: [Page],
  data () {
    return {
      uid: 0,
      search: '',
      date: date.formatDate(new Date(), 'YYYY/MM/DD'),
      category: null,
      categories: [],
      type: null,
      typeId: null,
      types: [],
      orgTypes: [],
      item: {},
      showItemDialog: false,
      tags: [],
      isLoading: false,
      items: null,
      limit: null,
      pageSize: 30,
      maxTags: 5,
      disableScroll: true,
      order: {
        label: this.$t('relevancy'),
        value: 'relevancy DESC, longName'
      },
      orderOptions: [
        {
          label: this.$t('relevancy'),
          value: 'relevancy DESC, longName'
        }, {
          label: this.$t('name'),
          value: 'longName'
        }, {
          label: this.$t('siceAsc'),
          value: 'size ASC'
        }, {
          label: this.$t('sizeDesc'),
          value: 'size DESC'
        } /* {
          label: this.$t('priceAsc'),
          value: 'price ASC'
        }, {
          label: this.$t('priceDesc'),
          value: 'price DESC'
        }, {
          label: this.$t('available'),
          value: 'available'
        }, {
          label: this.$t('novelty'),
          value: 'dated DESC'
        } */
      ]
    }
  },
  created () {
    this.$state.useRightDrawer = true
  },
  mounted () {
    this.$axios.get('ItemCategories')
      .then(res => (this.categories = res.data))
    this.onRouteChange(this.$route)
  },
  beforeDestroy () {
    this.clearTimeoutAndRequest()
  },
  beforeRouteUpdate (to, from, next) {
    this.onRouteChange(to)
    next()
  },
  watch: {
    categories () {
      this.refreshTitle()
    },
    orgTypes () {
      this.refreshTitle()
    },
    order () {
      this.loadItems()
    },
    date () {
      this.loadItems()
    },
    category (value) {
      this.orgTypes = []

      if (value) {
        let filter = {
          where: { categoryFk: value },
          order: 'order DESC, name'
        }
        this.$axios.get('ItemTypes', { params: { filter } })
          .then(res => (this.orgTypes = res.data))
      }
    },
    search (value) {
      let location = { params: this.$route.params }
      if (value) location.query = { search: value }
      this.$router.push(location)
    }
  },
  methods: {
    onRouteChange (route) {
      let { category, type } = route.params

      category = parseInt(category) || null
      type = parseInt(type) || null

      this.category = category
      this.typeId = category ? type : null
      this.search = route.query.search || ''
      this.tags = []

      this.refreshTitle()
      this.loadItems()
    },
    refreshTitle () {
      let title = this.$t(this.$router.currentRoute.name)
      let titleColor
      let subtitle

      if (this.category) {
        let category = this.categories.find(i => i.id === this.category) || {}
        title = category.name
        titleColor = `#${category.color}`
      }

      if (this.typeId) {
        this.type = this.orgTypes.find(i => i.id === this.typeId)
        subtitle = title
        title = this.type && this.type.name
      } else {
        this.type = null
      }

      Object.assign(this.$state, { title, titleColor, subtitle })
    },
    clearTimeoutAndRequest () {
      if (this.timeout) {
        clearTimeout(this.timeout)
        this.timeout = null
      }
      if (this.source) {
        this.source.cancel()
        this.source = null
      }
    },
    loadItemsDelayed () {
      this.clearTimeoutAndRequest()
      this.timeout = setTimeout(() => this.loadItems(), 500)
    },
    loadItems () {
      this.items = null
      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.category || this.typeId || this.search)) {
        this.tags = []
        return Promise.resolve(true)
      }

      let tagFilter = []

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

      this.source = CancelToken.source()

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

        if (tag.filter) {
          tag.hasFilter = true
          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
    },
    onRangeChange (tag, delay) {
      tag.hasFilter = true

      if (!delay) this.loadItems()
      else this.loadItemsDelayed()
    },
    onCheck (tag) {
      tag.hasFilter = tag.filter.length > 0
      this.loadItems()
    },
    resetTagFilter (tag) {
      tag.hasFilter = false

      if (tag.useRange) {
        tag.filter = {
          min: tag.min,
          max: tag.max
        }
      } else {
        tag.filter = []
      }
    },
    onResetTagFilterClick (tag) {
      this.resetTagFilter(tag)
      this.loadItems()
    },
    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)
        })
      }
    },
    showItem (item) {
      this.item = item
      this.showItemDialog = true

      let conf = this.$state.catalogConfig
      let params = {
        dated: this.date,
        addressFk: conf.addressFk,
        agencyModeFk: conf.agencyModeFk
      }
      this.$axios.get(`Items/${item.id}/calcCatalog`, { params })
        .then(res => (this.lots = res.data))
    }
  }
}
</script>
