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

    /**
     * @class module:ArcGis.ArcGisPolygon
     * @description ArcGis服务
     * @author 基础平台-杨琨
     * @param options - {Object} 必选项，构造点对象参数。
     * @param {String} [options.rings] 可选项。构成多边形的点坐标，坐标必须闭合，可有多个矩形。
     * Example：rings:[[[x1,y1],[x2,y2],[x3,y3],[x1,y1]],[[x4,y4],[x5,y5],[x6,y6],[x4,y4]]]
     * @param {ArcGisSpatialReference} [options.spatialReference] 可选项。多边形的空间坐标系，默认4326。
     */
    class ArcGisPolygon extends ArcGisGeometry {
      constructor(options) {
        super(options)
        this.centroid = null
        this.isSelfIntersecting = false
        this.rings = []
        this.type = 'polygon'

        extend(this, options)

        if (this.rings[0] && this.rings[0][0]) {
          if (this.rings[0][0].length >= 3) {
            this.hasZ = true
          }
        }
      }
    }

    /**
     * @function module:ArcGis.ArcGisPolygon.prototype.getPoint
     * @description 根据ringIndex、pointIndex返回点对象
     * @param ringIndex - {Number} 必选项，要查询的多边形序号。
     * @param pointIndex - {Number} 必选项，要查询的点序号。
     * @returns ArcGisPoint，点对象
     */
    ArcGisPolygon.prototype.getPoint = function (ringIndex, pointIndex) {
      if (
        ringIndex >= this.rings.length ||
        pointIndex >= this.rings[ringIndex].length
      ) {
        return null
      }
      return returnPoint(ArcGisPoint, this, this.rings[ringIndex][pointIndex])
    }

    /**
     * @function module:ArcGis.ArcGisPolygon.prototype.insertPoint
     * @description 根据ringIndex、pointIndex，在pointIndex之后插入一个点对象
     * @param ringIndex - {Number} 必选项，要插入的多边形序号。
     * @param pointIndex - {Number} 必选项，在第pointIndex之后插入一个点，线标从0开始。
     * @param point - {Number} 必选项，要要插入的点对象。
     * @returns ArcGisPolygon，多边形对象
     */
    ArcGisPolygon.prototype.insertPoint = function (ringIndex, pointIndex, point) {
      if (
        ringIndex < this.rings.length &&
        pointIndex <= this.rings[ringIndex].length
      ) {
        if (point instanceof Array) {
          this.rings[ringIndex].splice(pointIndex, 0, point)
        } else if (point instanceof ArcGisPoint) {
          this.rings[ringIndex].splice(
            pointIndex,
            0,
            point.hasZ ? [point.x, point.y, point.z] : [point.x, point.y]
          )
        }
      }
      return this
    }

    /**
     * @function module:ArcGis.ArcGisPolygon.prototype.removePoint
     * @description 根据ringIndex、pointIndex删除一个点，并返回该点对象
     * @param ringIndex - {Number} 必选项，要删除的点所在的多边形序号。
     * @param pointIndex - {Number} 必选项，在pointIndex处，删除这个点。
     * @returns ArcGisPoint，点对象
     */
    ArcGisPolygon.prototype.removePoint = function (ringIndex, pointIndex) {
      if (
        ringIndex >= this.rings.length ||
        pointIndex >= this.rings[ringIndex].length
      ) {
        return null
      }
      const positionArr = this.rings[ringIndex].splice(pointIndex, 1)[0]
      return returnPoint(ArcGisPoint, this, positionArr)
    }

    /**
     * @function module:ArcGis.ArcGisPolygon.prototype.setPoint
     * @description 根据ringIndex、pointIndex，更新一个点对象
     * @param ringIndex - {Number} 必选项，要更新的点所在的多边形序号。
     * @param pointIndex - {Number} 必选项，在pointIndex处，更新这个点。
     * @param point - {ArcGisPoint} 必选项，ArcGisPoint对象或者[x,y]或[x,y,z]数组,要更新的点。
     * @returns ArcGisPolygon，多边形对象
     */
    ArcGisPolygon.prototype.setPoint = function (ringIndex, pointIndex, point) {
      if (
        ringIndex >= this.rings.length ||
        pointIndex >= this.rings[ringIndex].length
      ) {
        return null
      }
      if (point instanceof Array) {
        this.rings[ringIndex][pointIndex] = point
      } else if (point instanceof ArcGisPoint) {
        const pointArr = [point.x, point.y]
        if (point.hasZ) {
          pointArr.push(point.z)
        }
        if (point.hasM) {
          pointArr.push(point.m)
        }
        this.rings[ringIndex][pointIndex] = pointArr
      }
      return this
    }

    /**
     * @function module:ArcGis.ArcGisPolygon.prototype.addRing
     * @description 根据ringIndex、pointIndex，更新一个多边形对象
     * @param points - {Array} 必选项，要插入的一组多边形点坐标数组，
     * example：[[x1,y1],[x2,y2],[x3,y3],[x1,y1]]。
     * @returns ArcGisPolygon，多边形对象
     */
    ArcGisPolygon.prototype.addRing = function (points) {
      if (points instanceof Array) {
        this.rings.push(formatPoints(points))
      } else {
        this.rings.push([])
      }
      return this
    }

    /**
     * @function module:ArcGis.ArcGisPolygon.prototype.removeRing
     * @description 根据index，删除一个多边形点坐标数组
     * @param index - {Array} 必选项，要删除的多边形序号。
     * @returns [ArcGisPoint]，被删除的多边形点对象数组
     */
    ArcGisPolygon.prototype.removeRing = function (index) {
      if (index >= this.rings.length) return null
      const path = this.rings.splice(index, 1)[0]
      let point
      const pointArr = []
      for (let i = 0; i < path.length; i++) {
        point = returnPoint(ArcGisPoint, this, path[i])
        pointArr.push(point)
      }
      return pointArr
    }

    /**
     * @function module:ArcGis.ArcGisPolygon.prototype.isClockwise
     * @description 判断是否是顺时针。
     * @param ring - {Array} 必选项，[ArcGisPoint]或[[x,y,z]]或[x,y],输入值必须是一组点坐标或对象数组（就是一条线,封闭线就是多边形），不能是多维数组。
     * @returns {boolean} 是否是顺时针。
     */
    ArcGisPolygon.prototype.isClockwise = function (ring) {
      let sum = 0
      let i = 1
      let hasZ = false // 是否有值
      let prev // 上一个点
      let cur // 当前点
      hasZ = !!ring[0][2]
      while (i < ring.length) {
        // 第一次将ring[0]给prev，之后都是cur
        prev = cur || ring[0]
        cur = ring[i]
        // 根据两组坐标(x1 - x1) * (y1 + y0) * (z1 + z0)的值累计相加，最后的值大于0则是顺实战，否则逆时针
        sum += hasZ
          ? (cur[0] - prev[0]) * (cur[1] + prev[1]) * (cur[2] + prev[2])
          : (cur[0] - prev[0]) * (cur[1] + prev[1])
        i++
      }
      return sum > 0
    }

    /**
     * @function module:ArcGis.ArcGisPolygon.prototype.contains
     * @description 判断多边形是否包含一个点。
     * @param point - {ArcGisPoint} 必选项，要检测的点对象。
     * @returns {boolean} 多边形是否包含点。
     */
    ArcGisPolygon.prototype.contains = function (point) {
      if (point instanceof ArcGisPoint) {
        const g = H.polygon(this.rings, { name: '_extentPlygon' })
        const p = H.point(point.toArray())
        return T.booleanContains(g, p)
      } else {
        return false
      }
    }

    /**
     * @function module:ArcGis.ArcGisPolygon.prototype.toGeometryJSON
     * @description 将点坐标转换为Json对象
     * @returns String
     */
    ArcGisPolygon.prototype.toGeometryJSON = function () {
      const rings = this.rings
      let geometryStr = '{"rings":['
      for (let i = 0; i < rings.length; i++) {
        geometryStr += '['
        for (let j = 0; j < rings[i].length; j++) {
          geometryStr += '['
          geometryStr += rings[i][j].join(',')
          geometryStr += '],'
        }
        geometryStr = geometryStr.substr(0, geometryStr.length - 1)
        geometryStr += '],'
      }
      geometryStr = geometryStr.substr(0, geometryStr.length - 1)
      geometryStr += ']}'
      return geometryStr
    }

    /**
     * @function module:ArcGis.ArcGisPolygon.prototype.fromExtent
     * @description 输入一个Extent对象返回一个多边形对象
     * @param Extent - {ArcGisExtent} 必选项，要输入的ArcGisExtent对象。
     * @returns {ArcGisPolygon} 新的多边形对象。
     */
    ArcGisPolygon.prototype.fromExtent = function (Extent) {
      return new ArcGisPolygon({
        rings: Extent._extentPolygon.geometry.coordinates
      })
    }

    export default ArcGisPolygon
    Zondy.Service.ArcGisPolygon = ArcGisPolygon