    import * as T from '@turf/turf'
    import * as H from '@turf/helpers'
    import { extend, notNULL } from '../../util'
    import Zondy from '../Zondy'
    import ArcGisGeometry from './Geometry'
    import ArcGisPoint from './Point'

    function initCenter(me) {
      const points = [
        H.point([me.xmin, me.ymin]),
        H.point([me.xmin, me.ymax]),
        H.point([me.xmax, me.ymax]),
        H.point([me.ymax, me.ymin]),
        H.point([me.xmin, me.ymin])
      ]
      const featureCollection = H.featureCollection(points)
      const coordinates = T.center(featureCollection).geometry.coordinates
      return new ArcGisPoint({
        longitude: coordinates[0],
        latitude: coordinates[1]
      })
    }

    /**
     * @class module:ArcGis.ArcGisExtent
     * @description ArcGisExtent对象
     * @author 基础平台-杨琨
     * @param options - {Object} 必选项，构造Extent对象参数。
     * @param {String} [query.xmin] 可选项，x轴最小坐标。
     * @param {String} [query.ymin] 可选项，x轴最大坐标。
     * @param {String} [query.ymin] 可选项，y轴最小坐标。
     * @param {String} [query.ymax] 可选项，y轴最小坐标。
     * @param {String} [query.zmin] 可选项，z轴最小坐标。
     * @param {String} [query.zmax] 可选项，z轴最小坐标。
     * @param {String} [query.mmin] 可选项，m轴最小坐标。
     * @param {String} [query.mmax] 可选项，m轴最小坐标。
     */

    class ArcGisExtent extends ArcGisGeometry {
      constructor(options) {
        super(options)
        this.center = undefined
        this.hasM = false
        this.hasZ = false
        this.height = 0
        this.mmax = undefined
        this.mmin = undefined
        this.type = 'extent'
        this.width = 0
        this.xmax = 0
        this.xmin = 0
        this.ymax = 0
        this.ymin = 0
        this.zmax = undefined
        this.zmin = undefined
        this.extent = this

        // 确保私有变量不能被options修改
        this.private = [
          'center',
          'hasM',
          'hasZ',
          'height',
          'width',
          'type',
          'extent'
        ]
        for (const key in this.private) {
          if (notNULL(options[this.private[key]])) {
            throw new Error(
              `[accessor] cannot assign to read-only property '${this.private[key]}' of ArcGisExtent`
            )
          }
        }

        extend(this, options)

        // 如果z、m有值，hasZ、hasM采薇true
        if (this.zmax || this.zmin) {
          this.hasZ = true
        }
        if (this.mmax || this.mmin) {
          this.hasM = true
        }

        // 生成bbox
        this._extentPolygon = T.polygon(
          [
            [
              [this.xmin, this.ymin],
              [this.xmin, this.ymax],
              [this.xmax, this.ymax],
              [this.ymax, this.ymin],
              [this.xmin, this.ymin]
            ]
          ],
          { name: '_extentPlygon' }
        )

        // 生成中心点
        this.center = initCenter(this)

        // 计算width，height
        this.width = this.xmax - this.xmin
        this.height = this.ymax - this.ymin
      }
    }

    /**
     * @function module:ArcGis.ArcGisExtent.prototype.equals
     * @description 比较两个Extent对象是否相等
     * @param extent - {ArcGisExtent} 必选项，要比较的ArcGisExtent对象。
     * @returns Boolean，对象是否相等
     */
    ArcGisExtent.prototype.equals = function (extent) {
      return (
        this.mmax === extent.mmax &&
        this.mmin === extent.mmin &&
        this.xmax === extent.xmax &&
        this.xmin === extent.xmin &&
        this.ymax === extent.ymax &&
        this.ymin === extent.ymin &&
        this.zmax === extent.zmax &&
        this.zmin === extent.zmin
      )
    }

    /**
     * @function module:ArcGis.ArcGisExtent.prototype.contains
     * @description 判断是否包含一个点或者一个ArcGisExtent对象
     * @param geometry - {Geometry} 必选项，要比较的ArcGisExtent对象或者ArcGisPoint对象。
     * @returns Boolean，是否包含
     */
    ArcGisExtent.prototype.contains = function (geometry) {
      if (geometry.type === 'point') {
        let point = geometry.toArray()
        point = T.point([point[0], point[1]])
        return T.booleanContains(this._extentPolygon, point)
      }
      if (geometry.type === 'extent') {
        return T.booleanContains(this._extentPolygon, geometry._extentPolygon)
      }
      return false
    }

    /**
     * @function module:ArcGis.ArcGisExtent.prototype.expand
     * @description 根据输入的值，扩大或缩小一个ArcGisExtent
     * @param factor - {Number} 必选项，放大或缩小系数。
     * @returns ArcGisExtent，缩放后的ArcGisExtent
     */
    ArcGisExtent.prototype.expand = function (factor) {
      if (factor instanceof Number) {
        factor = Math.abs(factor)
        this.width *= factor
        this.height *= factor
        this.xmin = this.center.x - this.width / 2
        this.xmax = this.center.x + this.width / 2
        this.ymin = this.center.y - this.height / 2
        this.ymax = this.center.y + this.height / 2
        return this
      } else {
        throw new Error('require is not defined')
      }
    }

    /**
     * @function module:ArcGis.ArcGisExtent.prototype.intersects
     * @description 比较点、多点、线、多边形、extent是否与当前extent相交
     * @param geometry - {Geometry} 必选项，要比较的几何对象。
     * @returns Boolean，是否相交
     */
    ArcGisExtent.prototype.intersects = function (geometry) {
      if (!geometry.type) {
        return false
      }
      let geom
      if (geometry.type === 'polyline') {
        geom = H.multiLineString(geometry.paths)
      } else if (geometry.type === 'point') {
        geom = H.point(geometry.toArray())
      } else if (geometry.type === 'multipoint') {
        geom = H.multiPoint(geometry.points)
      } else if (geometry.type === 'extent') {
        geom = geometry._extentPolygon
      } else if (geometry.type === 'polygon') {
        geom = H.polygon(geometry.rings)
      }
      return !T.booleanDisjoint(geom, this._extentPolygon)
    }

    /**
     * @function module:ArcGis.ArcGisExtent.prototype.offset
     * @description 根据输入的dx, dy, dz值，平移extend
     * @param dx - {Number} 必选项，要平移的x值。
     * @param dx - {Number} 必选项，要平移的y值。
     * @param dx - {Number} 必选项，要平移的z值。
     * @returns ArcGisExtent，平移后的ArcGisExtent对象
     */
    ArcGisExtent.prototype.offset = function (dx, dy, dz) {
      this.xmax += dx
      this.xmin += dx
      this.ymax += dy
      this.ymin += dy
      if (this.hasZ) {
        this.zmax += dz
        this.zmin += dz
      } else {
        this.hasZ = true
        this.zmax = 0
        this.zmin = 0
      }
      return this
    }

    /**
     * @function module:ArcGis.ArcGisExtent.prototype.centerAt
     * @description 根据输入的ArcGisPoint对象，生成衣蛾新的中心点
     * @param point - {ArcGisPoint} 必选项，新的中心点。
     * @returns ArcGisExtent
     */
    ArcGisExtent.prototype.centerAt = function (point) {
      if (point instanceof ArcGisPoint) {
        this.center = new ArcGisPoint({
          longitude: point.x,
          latitude: point.y
        })
        this.xmin = this.center.x - this.width / 2
        this.xmax = this.center.x + this.width / 2
        this.ymin = this.center.y - this.height / 2
        this.ymax = this.center.y + this.height / 2
        return this
      }
    }

    ArcGisExtent.prototype.normalize = function () {
      return [this]
    }

    /**
     * @function module:ArcGis.ArcGisExtent.prototype.union
     * @description 输入一个ArcGisExtent对象，与原extent对象合并，生成一个新的extent
     * @param extent - {ArcGisExtent} 必选项，要合并的ArcGisExtent对象。
     * @returns ArcGisExtent，新的Extent对象
     */
    ArcGisExtent.prototype.union = function (extent) {
      const cur = this.center
      const nex = extent.center
      if (
        (nex.x - cur.x > 0 && nex.y - cur.y > 0) ||
        (nex.x - cur.x === 0 && nex.y - cur.y > 0) ||
        (nex.x - cur.x === 0 && nex.y - cur.y === 0) ||
        (nex.x - cur.x > 0 && nex.y - cur.y === 0)
      ) {
        this.xmax = extent.xmax
        this.ymax = extent.ymax
      } else if (
        (nex.x - cur.x > 0 && nex.y - cur.y < 0) ||
        (nex.x - cur.x === 0 && nex.y - cur.y < 0)
      ) {
        this.xmax = extent.xmax
        this.ymin = extent.ymin
      } else if (nex.x - cur.x < 0 && nex.y - cur.y < 0) {
        this.xmin = extent.xmin
        this.ymin = extent.ymin
      } else if (
        nex.x - cur.x < 0 &&
        (nex.y - cur.y || (nex.x - cur.x < 0 && nex.y - cur.y < 0)) === 0
      ) {
        this.xmin = extent.xmin
        this.ymax = extent.ymax
      }
      this.center = initCenter(this)
      // 计算width，height
      this.width = this.xmax - this.xmin
      this.height = this.ymax - this.ymin
      return this
    }

    /**
     * @function module:ArcGis.ArcGisExtent.prototype.toString
     * @description 返回如下格式的字符串："xmin,ymin,xmax,ymax"
     * @returns Sting
     */
    ArcGisExtent.prototype.toString = function () {
      return `${this.xmin},${this.ymin},${this.xmax},${this.ymax}`
    }

    export default ArcGisExtent
    Zondy.Service.ArcGisExtent = ArcGisExtent