<template>
  <van-pull-refresh v-model="stateRefreshing" @refresh="getList()">
    <van-list
      v-model="stateLoading"
      :finished="stateFinished"
      finished-text="没有更多了"
      @load="getList('+1')"
    >
      <slot name="default"/>
    </van-list>
  </van-pull-refresh>
</template>

<script>
// 可刷新, 可下拉的vant列表
export default {
  name: 'PagedList',
  props: {
    value: { // 列表 只写
      type: Array,
      default: function() {
        return [];
      },
    },
    pageNum: { // 页码 读写 无监听
      type: Number,
      default: 1,
    },
    pageSize: { // 页量 读写 无监听
      type: Number,
      default: 10,
    },
    total: { // 读取总数 只写
      type: Number,
      default: 0,
    },
    loading: { // 是否加载中 只写
      type: Boolean,
      default: false,
    },
    refreshing: { // 是否刷新中 只写
      type: Boolean,
      default: false,
    },
    finished: { // 是否完全加载 只写
      type: Boolean,
      default: false,
    },
    getWhenCreated: { // 创建后直接获取列表 只读 无监听
      type: Boolean,
      default: false,
    },
    getListFunc: { // 获取数据函数 返回Promise 成功参数传递本次请求响应的列表项数和总数 { length|rows|data, total }
      type: Function,
      default: null,
    },
    reload: { // 变更此值为true则重新加载数据 监听
      type: Boolean,
      default: false,
    },
  },
  components: {
  },
  data() {
    return {
      stateLoading: false,
      stateRefreshing: false,
      stateFinished: !this.getWhenCreated,
      stateTotal: 0,
      queryParams: {
        pageNum: this.pageNum,
        pageSize: this.pageSize,
      },
    }
  },
  created() {
    if(this.getWhenCreated)
      this.getList();
  },
  methods: {
    getList(target) {
      let type = typeof (target);
      this.log(type, target);
      if(target && this.stateFinished)
      {
        this.log('nomore');
        this.$emit('nomore');
        return;
      }
      if (target === 0) {
        this.setupRefreshing(true);
        this.setupFinished(true);
        this.setupTotal(0);
        this.setupPageNum(1);
        this.clearList();
      }
      else if (type === 'number')
        this.setupPageNum(target);
      else if (type === 'string') {
        this.setupPageNum(eval(this.queryParams.pageNum + target));
      }
      else
      {
        this.setupRefreshing(true);
        this.setupFinished(true);
        this.setupTotal(0);
        this.setupPageNum(1);
        this.clearList();
      }

      this.getListFunc(this.queryParams).then((result) => {
        if(result.hasOwnProperty('rows'))
        {
          this.setupTotal(this.stateTotal + result.rows.length);
          this.setupFinished(this.stateTotal >= result.total);
        }
        else if(result.hasOwnProperty('data'))
        {
          this.setupTotal(this.stateTotal + result.data.length);
          this.setupFinished(true);
        }
        else if(result.hasOwnProperty('length'))
        {
          this.setupTotal(this.stateTotal + result.length);
          this.setupFinished(true);
        }

        if(result.hasOwnProperty('total'))
        {
          this.setupFinished(this.stateTotal >= result.total);
        }
        else
        {
          this.setupFinished(true);
        }
      }).catch((err) => {
        this.setupError(err);
      }).finally(() => {
        this.setupLoading(false);
        this.setupRefreshing(false);
      });
    },
    clearList() {
      this.log(`reload`);
      this.$emit('reload');
      this.$emit('input', []);
    },
    setupPageNum(num) {
      this.queryParams.pageNum = num;
      if(this.queryParams.pageNum != this.pageNum)
        this.$emit('update:pageNum', this.queryParams.pageNum);
    },
    setupTotal(num) {
      this.log(`total -> ${num}`);
      this.stateTotal = num;
      if(this.stateTotal != this.total)
        this.$emit('update:total', this.stateTotal);
    },
    setupLoading(ok) {
      this.log(`loading -> ${ok}`);
      this.stateLoading = ok;
      if(this.stateLoading != this.loading)
        this.$emit('update:loading', this.stateLoading);
    },
    setupFinished(ok) {
      this.log(`finished -> ${ok}`);
      this.stateFinished = ok;
      if(this.stateFinished != this.finished)
        this.$emit('update:finished', this.stateFinished);
      if(ok)
        this.$emit('finished', this.stateTotal);
    },
    setupError(err) {
      this.log(`error -> ${err}`);
      this.stateFinished = true;
      if(this.stateFinished != this.finished)
        this.$emit('update:finished', this.stateFinished);
      this.$emit('error', err);
    },
    setupRefreshing(ok) {
      this.log(`refreshing -> ${ok}`);
      this.stateRefreshing = ok;
      if(this.stateRefreshing != this.refreshing)
        this.$emit('update:refreshing', this.stateRefreshing);
    },
    log() {
      return;
      console.log('[PagedList]: ', ...arguments);
    },
  },
  watch: {
    reload(newVal) {
      if(newVal)
      {
        this.$emit('update:reload', false);
        this.getList();
      }
    },
  },
}
</script>

<style scoped lang="scss">

</style>
