    import * as T from '@turf/turf'
    import { Log, defaultValue } from '../../util'
    import { GeometryType } from '../enum'
    import {
      Circle,
      Extent,
      LineString,
      MultiLineString,
      MultiPolygon,
      Point,
      Polygon,
      MultiPoint,
      GeometryEngine
    } from './index'
    import { Feature } from '../feature'

    /**
     * @function createGeometry
     * @private
     * @param options 生成参数
     * @description 根据参数生成几何
     * @return Geometry 生成的几何对象
     */
    function createGeometry(options) {
      options = defaultValue(options, {})

      switch (options.type) {
        case GeometryType.point:
          return new Point(options)
        case GeometryType.multiPoint:
          return new MultiPoint(options)
        case GeometryType.lineString:
          return new LineString(options)
        case GeometryType.multiLineString:
          return new MultiLineString(options)
        case GeometryType.polygon:
          return new Polygon(options)
        case GeometryType.multiPolygon:
          return new MultiPolygon(options)
        case GeometryType.circle:
          return new Circle(options)
        case GeometryType.extent:
          return new Extent(options)
        default:
          Log.error('未输入正确的几何类型')
      }
    }

    /**
     * @function createGeometryByGeoJSON
     * @private
     * @param options 生成参数
     * @description 根据参数生成几何
     * @return Geometry 生成的几何对象
     */
    function createGeometryByGeoJSON(geojson) {
      let geometry
      if (geojson.type === 'Feature') {
        geometry = geojson.geometry
      } else {
        geometry = geojson
      }
      switch (geometry.type) {
        case GeometryType.point: {
          return new Point({
            coordinates: geometry.coordinates
          })
        }
        case GeometryType.multiPoint: {
          return new LineString({
            coordinates: geometry.coordinates
          })
        }
        case GeometryType.lineString:
          return new LineString({
            coordinates: geometry.coordinates
          })
        case GeometryType.multiLineString:
          return new MultiLineString({
            coordinates: geometry.coordinates
          })
        case GeometryType.polygon:
          return new Polygon({
            coordinates: geometry.coordinates
          })
        case GeometryType.multiPolygon:
          return new MultiPolygon({
            coordinates: geometry.coordinates
          })
        default:
          Log.error('无法解析geojson')
      }
    }

    /**
     * 通过三点弧段改造要素几何，打散成离散点
     * @param {Feature} feature 要素对象
     * @return {Feature} 改造后的要素对象
     * */
    function editFeatureByArc3(feature) {
      // 拷贝要素
      let _feature = Feature.fromJSON(feature)

      // 生成一个弧段几何
      const _arcGeometry = GeometryEngine.getArcFromGeometry({
        geometry: _feature.geometry,
        arcInfo: _feature.additional.arc3
      })

      // 转成json数据
      const _featureJSON = _feature.toJSON()

      // 更新点坐标
      _featureJSON.geometry.coordinates = _arcGeometry.coordinates

      // 构造一个新的要素
      _feature = Feature.fromJSON(_featureJSON)

      return _feature
    }

    /**
     * 通过三点弧段改造几何对象，打散成离散点
     * @param {Geometry} geometry 几何对象
     * @param {Object} additional 额外参数
     * @return {Geometry} 改造后的几何对象
     * */
    function editGeometryByArc3(geometry, additional) {
      // 判断是不是三点弧段
      if (additional && additional.arc3) {
        // 生成一个弧段几何
        return GeometryEngine.getArcFromGeometry({
          geometry,
          arcInfo: additional.arc3
        })
      }

      return geometry
    }

    /**
     * 计算并返回多边形的外包盒
     * @param {Array} coordinates 坐标点
     * @param {Boolean} hasZ 是否是三维
     * @param {GeometryType} type 几何类型
     * @returns {Extent} 外包盒对象
     * */
    function calcExtent(coordinates, hasZ, type) {
      type = defaultValue(type, GeometryType.polygon)

      let _geometry
      switch (type) {
        case GeometryType.polygon:
          _geometry = T.polygon(coordinates)
          break
        case GeometryType.lineString:
          _geometry = T.lineString(coordinates)
          break
        case GeometryType.multiPolygon:
          _geometry = T.multiPolygon(coordinates)
          break
        case GeometryType.multiLineString:
          _geometry = T.multiLineString(coordinates)
          break
        default:
          break
      }
      const bbox = T.bbox(_geometry)

      if (!hasZ) {
        return new Extent({
          xmin: bbox[0],
          ymin: bbox[1],
          xmax: bbox[2],
          ymax: bbox[3]
        })
      }

      const _zValues = []
      switch (type) {
        case GeometryType.polygon:
        case GeometryType.multiLineString:
          for (let i = 0; i < coordinates.length; i++) {
            for (let j = 0; j < coordinates[i].length; j++) {
              _zValues.push(coordinates[i][j][2])
            }
          }
          break
        case GeometryType.lineString:
          for (let i = 0; i < coordinates.length; i++) {
            _zValues.push(coordinates[i][2])
          }
          break
        case GeometryType.multiPolygon:
          for (let i = 0; i < coordinates.length; i++) {
            for (let j = 0; j < coordinates[i].length; j++) {
              for (let k = 0; k < coordinates[i][j].length; k++) {
                _zValues.push(coordinates[i][j][k][2])
              }
            }
          }
          break
        default:
          break
      }

      _zValues.sort(function (a, b) {
        return a - b
      })

      const _zmin = _zValues[0]
      const _zmax = _zValues[_zValues.length - 1]

      return new Extent({
        xmin: bbox[0],
        ymin: bbox[1],
        xmax: bbox[2],
        ymax: bbox[3],
        zmin: _zmin,
        zmax: _zmax
      })
    }

    export {
      createGeometry,
      createGeometryByGeoJSON,
      editFeatureByArc3,
      editGeometryByArc3,
      calcExtent
    }