# query.js

    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
      }

      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
      }

      // ? 自定义接口----------
      /**
       * todo 获取数据表中最后创建的数据
       * @returns 最后一个创建的数据
       */
      createTimeIsLast() {
        return new Promise((resolve, reject) => {
          this.$http
            .find()
            .then((data) => {
              let lastCreated = data[0]
              data.forEach((element) => {
                if (element.createdAt > lastCreated.createdAt) lastCreated = element
              })
              resolve(lastCreated)
            })
            .catch((err) => {
              reject(err)
            })
        })
      }
      /**
       * 获查询表数据 (行数据)
       * @param {Object} screen 需要筛选的数据项
       * @returns {Array} 返回的数据列表
       */
      getData(
        { page = 1, start = 0, limit, sort = [], filter = [] } = {},
        isCreate,
        qtype = 'find'
      ) {
        const { AV } = this
        const ASCE = 'ascending' // 升序
        const DESC = 'descending' // 降序
        // 翻页部分
        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

            default:
              break
          }
        })
        return isCreate ? this.$http : this[qtype]()
      }
    }

    export default $Query