import { mapState, mapGetters } from 'vuex'
import mz from '@mezereon/tracking'
import { isEmpty, isAbsoluteUrl } from '@/helpers'

export default {
  data() {
    return {
      loading: true,
      apiUrl: mz.config.search.url,
      searchKey: mz.config.search.key
    }
  },
  computed: {
    ...mapState('search', [
      'pageId',
      'queryId',
      'segments',
      'keyword',
      'page',
      'sort',
      'pageSize',
      'selections',
      'filters',
      'aggregations',
      'hits',
      'primaryKey',
      'context',
      'fallbackMode',
      'queryParam',
      'pageParam',
      'pagination',
      'redirect'
    ]),
    ...mapGetters('search', ['getFacetBanners', 'getQuery'])
  },
  created() {
    const store = this.$store

    store.dispatch('api/setApiUrl', this.apiUrl, { root: true })
    store.dispatch('api/setSearchKey', this.searchKey, { root: true })

    if (this.$bus) this.$bus.on('run-query', this.doSearch)
  },
  mounted() {
    // initial query is executed only when mz-context is on the page
    if (this.$refs.context === undefined) {
      this.loading = false
      this.showResults()
      return
    }
    if (this.fallbackMode) {
      this.loading = false
      this.turnOnFallbackMode()
      return
    }

    // define queryParam and register query state change handler
    this.$queryState.setQueryParam(this.queryParam)
    this.$queryState.setPageParam(this.pageParam)
    this.$queryState.onChange(this.queryStateChange)
    // run initial query
    this.queryStateChange(this.$queryState.parseUrl())
  },
  methods: {
    pushState(pagination) {
      if (pagination.current_page == 1) {
        return true
      }
      if (
        pagination.pagingType === 'more' ||
        pagination.pagingType == 'infinite'
      ) {
        return false
      }
      return true
    },
    showResults() {
      // hide aggregations div
      const hideAggs =
        isEmpty(this.getFacetBanners) && this.aggregations.length === 0
      const aggs = document.querySelectorAll('.mz-aggs')
      if (aggs) {
        aggs.forEach(item => {
          item.style.display = hideAggs ? 'none' : 'block'
        })
      }
    },
    turnOnFallbackMode() {
      // show fallback content
      const app = document.querySelector('#mz-app')
      if (app) {
        app.style.display = 'none'
      }
      const autocomplete = document.querySelector('#mz-autocomplete')
      if (autocomplete) {
        autocomplete.style.display = 'none'
      }
      const fallback = document.querySelectorAll('.mz-fallback')
      if (fallback) {
        fallback.forEach(item => {
          item.style.display = 'block'
        })
      }
      window.mz.enabled = false
    },
    queryStateChange(state) {
      this.loading = true

      // use sort and pageSize from cookies when undefined
      state.sort = state.sort || this.$cookies.get('sort')
      state.pageSize = state.pageSize || this.$cookies.get('pageSize')

      this.$store.dispatch('search/setState', state, { root: true })
      this.runQuery(false)
    },
    doSearch: function() {
      this.runQuery(true)
    },
    runQuery: function(push) {
      const query = {
        filter: this.context.filter,
        pageUrl: this.context.pageUrl,
        pageId: this.pageId,
        keyword: this.keyword,
        page: this.page,
        sort: this.sort,
        pageSize: this.pageSize,
        filters: this.filters
      }
      const context = {
        visitId: mz ? mz.getVisitId() : '',
        visitorId: mz ? mz.getVisitorId() : '',
        tags: this.context.tags,
        narrow: this.context.narrow
      }
      this.$store
        .dispatch('search/runQuery', { query, context }, { root: true })
        .then(() => {
          // hide loader
          this.loading = false

          if (this.pushState(this.pagination)) {
            // push to history
            if (push) {
              this.$queryState.push(this.getQuery())
            }
            if (this.$scrollTo) {
              if (mz && mz.config && mz.config.scroll) {
                if (!mz.config.scroll.disabled) {
                  this.$scrollTo(
                    mz.config.scroll.element || 'body',
                    mz.config.scroll.duration || 300
                  )
                }
              } else {
                this.$scrollTo(300)
              }
            }
          }

          this.showResults()
          const event = { query, context, result: this.hits }

          if (push) {
            // emit after-query event needed for custom handlers
            if (this.$bus) this.$bus.emit('after-query', event)
          } else {
            // emit after-initial-query event needed for custom handlers
            if (this.$bus) this.$bus.emit('after-initial-query', event)
          }

          const self = this
          this.$nextTick(() => {
            if (self.$bus) self.$bus.emit('after-update', event)
          })

          if (mz && mz.track && this.hits) {
            // retrieve top 10 unique ids from results for ML
            const uids = []
            for (let i = 0; i < 10 && i < this.hits.items.length; i++) {
              uids.push(this.hits.items[i].item[this.hits.primaryKey])
            }
            const banners = []
            if (this.hits.banners) {
              for (const [k, v] of Object.entries(this.hits.banners)) {
                if (v === null) {
                  continue
                }
                banners.push({ zone: k, id: v.id })
              }
            }
            mz.track('query', {
              queryId: this.queryId,
              query: query,
              segments: this.segments,
              context: context,
              total: this.hits.total,
              banners: banners,
              uids: uids,
              redirect: this.redirect
            })
          }
          if (this.redirect) {
            let redirect = this.redirect
            if (isAbsoluteUrl(redirect)) {
              window.location.replace(redirect)
              return
            }
            if (mz && mz.context && mz.context.root) {
              redirect = `${mz.context.root}${redirect}`
            }
            window.location.replace(redirect)
            return
          }
        })
        .catch(() => {
          this.loading = false
          this.turnOnFallbackMode()
        })
    }
  }
}
