import Utils from './utils'
class $Query {
  constructor(AV, className, request, that) {
    this.AV = AV
    this.$http = className ? new AV.Query(className) : AV.Query
    this.request = request
    this.that = that
  }

  get(objectId) {
    if (!objectId) return
    const { $http, request, that } = this
    const dispatchRequest = () => $http.get(objectId)
    return request.call(that, dispatchRequest)
  }
  first() {
    const { $http, request, that } = this
    const dispatchRequest = () => $http.first()
    return request.call(that, dispatchRequest)
  }
  find() {
    const { $http, request, that } = this
    const dispatchRequest = () => $http.find()
    return request.call(that, dispatchRequest)
  }
  count() {
    const { $http, request, that } = this
    const dispatchRequest = () => $http.count()
    return request.call(that, dispatchRequest)
  }

  or(...arg) {
    if (!arg) return
    this.$http.or(...arg)
    return this
  }
  and(...arg) {
    if (!arg) return
    this.$http.and(...arg)
    return this
  }

  includeACL(isShow) {
    console.log(isShow)
    this.$http.includeACL(isShow)
    return this
  }

  include(keys) {
    if (!keys) return
    this.$http.include(keys)
    return this
  }

  // 精确查询
  equalTo(jsonObj) {
    if (!jsonObj) return
    Object.keys(jsonObj).forEach((item) =>
      this.$http.equalTo(item, jsonObj[item])
    )
    return this
  }
  notEqualTo(jsonObj) {
    if (!jsonObj) return
    Object.keys(jsonObj).forEach((item) =>
      this.$http.notEqualTo(item, jsonObj[item])
    )
    return this
  }
  sizeEqualTo(jsonObj) {
    if (!jsonObj) return
    Object.keys(jsonObj).forEach((item) =>
      this.$http.sizeEqualTo(item, jsonObj[item])
    )
    return this
  }

  // 关联查询
  matchesKeyInQuery(key, queryKey, query) {
    this.$http.matchesKeyInQuery(key, queryKey, query)
    return this
  }

  // 比较查询 > < >= <=
  lessThan(jsonObj) {
    if (!jsonObj) return
    Object.keys(jsonObj).forEach((item) =>
      this.$http.lessThan(item, jsonObj[item])
    )
    return this
  }
  lessThanOrEqualTo(jsonObj) {
    if (!jsonObj) return
    Object.keys(jsonObj).forEach((item) =>
      this.$http.lessThanOrEqualTo(item, jsonObj[item])
    )
    return this
  }
  greaterThan(jsonObj) {
    if (!jsonObj) return
    Object.keys(jsonObj).forEach((item) =>
      this.$http.greaterThan(item, jsonObj[item])
    )
    return this
  }
  greaterThanOrEqualTo(jsonObj) {
    if (!jsonObj) return
    Object.keys(jsonObj).forEach((item) =>
      this.$http.greaterThanOrEqualTo(item, jsonObj[item])
    )
    return this
  }

  exists(attributes) {
    //* 查找包含某一属性的对象
    this.$http.exists(attributes)
    return this
  }
  doesNotExist(attributes) {
    //* 查找不包含某一属性的对象
    this.$http.doesNotExist(attributes)
    return this
  }

  // 匹配查询
  startsWith(jsonObj) {
    for (const k in jsonObj) {
      this.$http.startsWith(k, jsonObj[k])
    }
    return this
  }
  contains(jsonObj) {
    for (const k in jsonObj) {
      this.$http.contains(k, jsonObj[k])
    }
    return this
  }
  containsAll(jsonObj) {
    for (const k in jsonObj) {
      this.$http.containsAll(k, jsonObj[k])
    }
    return this
  }
  containedIn(jsonObj) {
    if (!jsonObj) return
    Object.keys(jsonObj).forEach((item) =>
      this.$http.containedIn(item, jsonObj[item])
    )
    return this
  }
  notContainedIn(jsonObj) {
    if (!jsonObj) return
    Object.keys(jsonObj).forEach((item) =>
      this.$http.notContainedIn(item, jsonObj[item])
    )
    return this
  }
  matches(jsonObj) {
    if (!jsonObj) return
    Object.keys(jsonObj).forEach((item) =>
      this.$http.matches(item, jsonObj[item])
    )
    return this
  }
  matchesQuery(jsonObj) {
    if (!jsonObj) return
    Object.keys(jsonObj).forEach((item) =>
      this.$http.matchesQuery(item, jsonObj[item])
    )
    return this
  }
  doesNotMatchQuery(jsonObj) {
    if (!jsonObj) return
    Object.keys(jsonObj).forEach((item) =>
      this.$http.doesNotMatchQuery(item, jsonObj[item])
    )
    return this
  }

  // 排序查询
  ascending(key) {
    this.$http.ascending(key)
    return this
  }
  addAscending(key) {
    this.$http.addAscending(key)
    return this
  }
  descending(key) {
    this.$http.descending(key)
    return this
  }
  addDescending(key) {
    this.$http.addDescending(key)
    return this
  }

  // 翻页查询
  limit(size) {
    this.$http.limit(size)
    return this
  }
  skip(size) {
    this.$http.skip(size)
    return this
  }

  // ? 自定义接口----------
  /**
   * 获查询表数据 (行数据)
   * @param {Object} screen 需要筛选的数据项
   * @returns {Array} 返回的数据列表
   */
   async getData(
    { page = 1, start = 0, limit, sort = [], filter = [] } = {},
    { isCreate = false, isGetCount = true, method = 'find' } = {}
  ) {
    const { AV } = this
    const ASCE = 'ascending' // 升序
    const DESC = 'descending' // 降序

    let total = 0
    // 翻页部分
    if (limit) {
      // 翻页部分
      const skip = (page - 1) * limit + start
      this.limit(limit).skip(skip)
    }
    // 排序部分
    const asceKeys = sort.filter((item) => item.direction === ASCE)
    const descKeys = sort.filter((item) => item.direction === DESC)
    asceKeys.forEach((item, index) =>
      index === 0
        ? this.ascending(item.property)
        : this.addAscending(item.property)
    )
    descKeys.forEach((item, index) =>
      index === 0
        ? this.descending(item.property)
        : this.addDescending(item.property)
    )
    // 筛选部分
    filter.forEach((item) => {
      const { operator, property, value = null } = item
      switch (operator) {
        case 'exists':
        case 'doesNotExist':
        //
        case 'select':
        case 'include':
          this[operator](property)
          break
        case 'or':
        case 'and':
        //
        case 'equalTo':
        case 'notEqualTo':
        //
        case 'lessThan':
        case 'lessThanOrEqualTo':
        case 'greaterThan':
        case 'greaterThanOrEqualTo':
        //
        case 'startsWith':
        case 'contains':
        case 'matches':
        case 'containedIn':
        case 'notContainedIn':
        //
        case 'matchesQuery':
        case 'doesNotMatchQuery':
          if (value && Utils.isPlainObject(value)) console.log(value)
          else this[operator]({ [property]: value })
          break
        case 'matchesKeyInQuery':
          this[operator](
            property,
            Object.keys(value)[0],
            value[Object.keys(value)[0]]
          )
          break
        case 'includeACL':
          this[operator](value)
        default:
          break
      }
    })
    if (isCreate) return this.$http

    // 获取统计数量
    if (isGetCount) total = await this.count()

    return new Promise((resolve, reject) => {
      this[method]()
        .then((res) => {
          const data = { result: res, total }
          resolve(data)
        })
        .catch((err) => reject(err))
    })
  }
}

export default $Query
