# object.js

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

      // 保存
      save() {
        const { $http, avObject, request, that } = this
        const dispatchRequest = () => (avObject ? avObject.save() : $http.save())
        return request.call(that, dispatchRequest)
      }

      saveAll(objects) {
        const { AV, request, that } = this
        console.log(objects)
        const dispatchRequest = () => AV.Object.saveAll(objects)
        return request.call(that, dispatchRequest)
      }

      destroy() {
        const { $http, avObject, request, that } = this
        const dispatchRequest = () =>
          avObject ? avObject.destroy() : $http.destroy()
        return request.call(that, dispatchRequest)
      }

      destroyAll(objectIds) {
        const { AV, request, that } = this
        const dispatchRequest = () => AV.Object.destroyAll(objectIds)
        return request.call(that, dispatchRequest)
      }

      fetch() {
        const { $http, avObject, request, that } = this
        const dispatchRequest = () => (avObject ? avObject.fetch() : $http.fetch())
        return request.call(that, dispatchRequest)
      }

      fetchAll(objectIds) {
        const { AV, request, that } = this
        const dispatchRequest = () => AV.Object.fetchAll(objectIds)
        return request.call(that, dispatchRequest)
      }

      increment(key, count) {
        const { $http, avObject } = this
        const http = avObject || $http
        this.avObject = request.increment(key, count)
        return this
      }

      extend(classname) {
        if (!classname) return null
        return this.$http.extend(classname)
      }

      getUsers() {
        let request = this.$http
        if (this.avObject) request = this.avObject
        request.getUsers()
        this.avObject = request
        return this
      }

      add(key, item) {
        let request = this.$http
        if (this.avObject) request = this.avObject
        request.add(key, item)
        this.avObject = request
        return this
      }

      createWithoutData(className, objectId) {
        const { AV, avObject, $http } = this
        this.avObject = AV.Object.createWithoutData(className, objectId)
        return this
      }

      set(jsonObj) {
        let request = this.$http
        if (this.avObject) request = this.avObject
        for (const k in jsonObj) {
          request.set(k, jsonObj[k])
        }
        this.avObject = request
        return this
      }

      unset(keys) {
        let request = this.$http
        if (!keys || !keys.length) return
        if (this.avObject) request = this.avObject
        keys.forEach((item) => request.unset(item))
        this.avObject = request
        return this
      }

      setACL(acl) {
        if (!acl) return
        let request = this.$http
        if (this.avObject) request = this.avObject
        request.setACL(acl)
        this.avObject = request
        return this
      }

      // 个人定制API

      async handleData(data, { $pointType, $acl }) {
        const { AV, $http, avObject, that } = this
        const TYPE = $pointType
        const ACL = $acl
        const jsonObj = {
          ...data,
        }
        const setData = {}
        // acl对象
        Object.keys(jsonObj).forEach((item) => {
          if (
            jsonObj[item] &&
            (!Utils.isPlainObject(jsonObj[item]) || !jsonObj[item][TYPE]) &&
            item !== ACL
          ) {
            setData[item] = jsonObj[item]
          } else if (jsonObj[ACL] && Utils.isPlainObject(jsonObj[ACL])) {
            const aclObj = that.ACL().createACL({ ...jsonObj[ACL] }).avObject
            this.setACL(aclObj)
          }
        })
        // point指针对象
        const pointObjs = Object.keys(jsonObj)
          .filter(
            (item) => Utils.isPlainObject(jsonObj[item]) && jsonObj[item][TYPE]
          )
          .map((item) => ({
            [item]: jsonObj[item],
          }))
        // point指针搜索项
        const pointObjKeys = pointObjs.map((item) => Object.keys(item)[0])
        const findDatas = await Promise.all(
          pointObjs.map(async (item, index) => {
            const value = item[pointObjKeys[index]]
            const conditionKey = Object.keys(value).filter((item) => item !== TYPE)
            const qdata = new AV.Query(value[TYPE])
            const point = await qdata
              .equalTo([conditionKey[0]], value[conditionKey[0]])
              .first()
            return {
              key: pointObjKeys[index],
              point,
            }
          })
        )
        const pointDatas = findDatas
          .filter((item) => item.point)
          .map((item) => ({
            key: item.key,
            point: AV.Object.createWithoutData(item.point.className, item.point.id),
            className: item.point.className,
            id: item.point.id,
          }))
        pointDatas.forEach((item) => (setData[item.key] = item.point))
        return setData
      }

      /**
       * 构建或更新数据库行数据对象 (行对象)
       * @param {Array} objects  需要保存的数据对象数组
       * @param {String} $objectId 需要修改的对象id属性名
       * @param {String} $class pointer的class名称
       * @param {String} $acl acl的属性名称
       * @return {Array} 创建好的LeanCloud数据对象数组
       */
      async setData(
        objects,
        { $objectId = 'objectId', $pointType = 'pointType', $acl = 'acl' } = {}
      ) {
        if (!objects && objects.length) return
        const OBJECT_ID = $objectId
        const TYPE = $pointType
        const ACL = $acl
        const { AV, $http, avObject, that } = this
        const { className } = $http
        const AVObjcets = await Promise.all(
          objects.map(async (item) => {
            const hasId = item[OBJECT_ID]
            const data = hasId ? item.data : item
            const request = hasId
              ? AV.Object.createWithoutData(className, hasId)
              : new AV.Object(className)
            const setData = await this.handleData(data, {
              $pointType: TYPE,
              $acl: ACL,
            })
            request.set({ ...setData })
            return request
          })
        )
        return this.saveAll(AVObjcets)
      }
      /**
       * 批量删除数据库行数据对象或对象属性 (行对象)
       * @param {Array} objectIds 需要删除的数据对象id数组
       * @return null 返回为空
       */
      deleteData(objectIds) {
        const { AV, $http } = this
        const points = []
        const { className = '' } = $http
        if (!className) return
        if (!objectIds || !objectIds.length) return
        objectIds.forEach((item) =>
          points.push(AV.Object.createWithoutData(className, item))
        )
        return this.destroyAll(points)
      }
    }

    export default $Object