import Vue from 'vue'
import { nanoid } from 'nanoid'

export default class PagedList {
  // 用url及pageSize构造
  // url - 加载数据的url
  // pageSize - 每页数据个数
  // params - 除正常查询条件外，附加到后台sql中的参数，可以为空。格式为:{参数名:参数值}
  // sums - 需要求和的字段。格式为:{参数名:参数值}
  // isBlank - 是否使用空行填充表格，值为true或者 false
  // comp - 调用时的组件名，方便调试
  // aoteEncrypt - 加密类型, 不传使用全局的
  // encryKey - 加密key, 不传使用全局的
  // timeout - 查询超时时间, 默认50秒
  constructor (url, pageSize, params, sums, isBlank, comp, aoteEncrypt, encryKey, timeout) {
    // 正在查询标志位
    this.seaching = false
    this.url = url
    this.pageSize = pageSize
    this.pageIndex = 0
    this.isBlank = isBlank
    this.aoteEncrypt = aoteEncrypt || Vue.mmType
    this.encryKey = encryKey || Vue.mm
    this.timeout = timeout || 50000

    // 登记组件名
    if (comp) {
      this.comp = comp
    }

    // 登记参数源码，查询前，执行参数源码，获得实际参数值
    if (params) {
      this.paramSource = params
    }
    // 查询时，提交后台的参数值
    this.params = {}

    // 求和的字段
    this.sums = sums
    // 符合条件的数据总数
    this.count = 0
    // 符合条件的数据总页数
    this.totalPage = 0
    // 加载过来的数据
    this.rows = []
    // 状态，字符串型，包括：初始(默认)，查询，错误，正确
    this.state = '初始'
    // 出现错误时的错误内容，没找到符合条件的数据当错误处理
    this.error = '请输入条件, 进行查询'

    // 每次加载所需要的条件
    this.condition = null
    this.model = null
    this.condValue = null

    // 初始填充数据空行
    // isNuN标记本行是否为空行
    if (isBlank === true) {
      for (let i = 1; i <= pageSize; i++) {
        this.rows.push({ isNuN: 'true' })
      }
    }
  }

  // 执行查询过程，加载数据汇总信息
  // condition - 查询组件产生的查询条件
  // model - 查询组件收集到的输入数据
  // condValue - 交给后台的查询条件，可以为空
  search (condition, model, condValue) {
    let param
// 保存条件，以便加载某页时可以直接调用
    this.condition = condition
    this.model = model
    this.condValue = condValue
    this.state = '查询'
    this.procParams()
    this.seaching = true
    if (this.sums) {
      const totals = []
      for (const key in this.sums) {
        totals.push(key)
        param = { data: this.params, sums: totals }
      }
    } else {
      param = { data: this.params }
    }
    // 发生请求时，不进行任何提醒
    return Vue.resetpost(`${this.url}/n`, param, {
      timeout: this.timeout,
      rejectMsg: null,
      aoteEncrypt: this.aoteEncrypt,
      encryKey: this.encryKey
    }).then(response => {
      this.seaching = false
      if (response.n === 0) {
        this.state = '错误'
        this.error = '没有符合条件的记录'
        this.rows = []
        return
      }
      this.state = '正确'
      this.count = response.n
      for (const key in this.sums) {
        this.sums[key] = response[key]
      }
      this.totalPage = Math.ceil(this.count / this.pageSize)
      // 加载第一页数据
      return this.loadPage(1, this.pageSize)
    }).catch((error) => {
      this.seaching = false
      if (error.status !== 603) {
        this.state = '错误'
        this.error = `提取数据出错，错误码: ${error.status}, 错误信息：${error.data}，组件：${this.comp}`
      }
    })
  }

  // 重新进行查询
  refresh () {
    this.search(this.condition, this.model, this.condValue)
  }

  // 加载一页数据
  loadPage (pageNo, pageSize) {
    this.pageIndex = pageNo
    this.pageSize = pageSize
    this.state = '查询'
    return this.postGen(pageNo, pageSize)
  }

  postGen (pageNo, pageSize) {
    this.seaching = true
    return Vue.resetpost(`${this.url}?pageNo=${pageNo}&pageSize=${pageSize}`, { data: this.params }, {
      aoteEncrypt: this.aoteEncrypt,
      encryKey: this.encryKey,
      resolveMsg: null,
      rejectMsg: null
    }).then(response => {
      this.state = '正确'
      // a-table需要每条数据都加上一个字符传类型的key 这里通过一个生成uuid的库加入
      this.rows = response.map(item => {
        item.nanoid = nanoid()
        return item
      })
      if (this.isBlank === true) {
        const size = response.length % this.pageSize
        if (pageNo === this.totalPage) {
          for (let i = 1; i <= this.pageSize - size; i++) {
            this.rows.push({ isNuN: 'true' })
          }
        }
      }
      this.pageIndex = pageNo
      this.seaching = false
    }).catch(error => {
      this.seaching = false
      this.state = '错误'
      this.error = JSON.stringify(error)
      throw error
    })
  }

  // 处理查询参数，把condition以及condValue附加到参数列表中，condValue指后台查询条件
  procParams () {
    this.params.condition = this.condition
    if (this.condValue) {
      this.params.condValue = this.condValue
    }
    if (!this.paramSource) {
      return
    }
    // 对附加参数进行计算
    for (const name in this.paramSource) {
      this.params[name] = this.paramSource[name]
    }
  }
}
