<template>
  <div>
    <div
      v-if="status == 'clear' || status == 'empty'"
      class="text-subtitle1 text-center text-grey-7 q-pa-md">
      <span v-if="status == 'clear'">
        {{$t('setSearchFilter')}}
      </span>
      <span v-if="status == 'empty'">
        {{$t('noDataFound')}}
      </span>
    </div>
    <q-infinite-scroll
      ref="scroll"
      @load="onLoad"
      scroll-taget="html">
      <slot></slot>
      <template slot="loading">
        <div class="row justify-center q-my-md">
          <q-spinner color="primary" size="40px"/>
        </div>
      </template>
    </q-infinite-scroll>
  </div>
</template>

<script>
import { CancelToken } from 'axios'

export default {
  name: 'LbScroll',
  props: {
    request: {
      type: Function,
      required: true
    },
    autoRefresh: {
      type: Number,
      required: false
    }
  },
  data () {
    return {
      data: null,
      source: null,
      isLoading: false,
      index: null
    }
  },
  computed: {
    status () {
      if (this.isLoading && !this.data) {
        return 'loading'
      } else if (!this.data) {
        return 'clear'
      } else if (this.data.length === 0) {
        return 'empty'
      } else {
        return 'ready'
      }
    }
  },
  beforeDestroy () {
    this.clearTimeout()
  },
  watch: {
    data (val) {
      this.$emit('data', val)
    }
  },
  methods: {
    get (path, params) {
      this.cancelRequest()
      this.isLoading = true
      this.source = CancelToken.source()
      let config = {
        params,
        cancelToken: this.source.token
      }
      return this.$axios.get(path, config)
        .then(res => {
          this.source = null
          this.isLoading = false
          return res
        })
        .catch(err => {
          if (!err.__CANCEL__) {
            this.source = null
            this.isLoading = false
          }
          throw err
        })
    },
    cancelRequest () {
      if (this.source) {
        this.source.cancel()
        this.source = null
      }
    },
    doRequest () {
      this.cancelRequest()
      this.clearTimeout()

      let config = this.request(this.index)
      if (!config) {
        this.data = null
        return Promise.resolve(null)
      }

      let params = config.params || {}
      let filter = config.filter
      let limit

      if (filter) {
        params.filter = filter
        limit = filter.limit

        if (limit === undefined) {
          limit = this.index * 30
          filter.limit = limit
        }
      }

      return this.get(config.url, params)
        .then(res => {
          res.limit = limit
          this.data = res.data
          return res
        })
        .finally(() => {
          this.setTimeout()
        })
    },
    setTimeout () {
      this.clearTimeout()
      if (this.autoRefresh) {
        this.timeout = setTimeout(
          () => this.refresh(), this.autoRefresh * 1000)
      }
    },
    clearTimeout () {
      if (this.timeout) {
        clearTimeout(this.timeout)
        this.timeout = null
      }
    },
    onLoad (index, done) {
      this.index = index
      this.doRequest()
        .then(res => {
          if (!res) return done(true)
          done(!res.limit || !Array.isArray(res.data) || res.data.length < res.limit)
          return res
        })
        .catch(err => {
          done(true)
          throw err
        })
    },
    reload () {
      this.data = null
      let scroll = this.$refs.scroll
      scroll.stop()
      scroll.reset()
      scroll.resume()
      scroll.trigger()
    },
    refresh () {
      this.doRequest()
    }
  }
}
</script>
