    import { Feature, ViewEventType } from '../../base'
    import { Polygon, LineString, Circle, Extent } from '../../base/geometry'
    import { defaultValue } from '../../util'
    import SketchBaseDrawTool from './SketchBaseDrawTool'
    import Color from '../../base/Color'
    import SketchPointDrawTool from './SketchPointDrawTool'
    // import SketchSnappingTool from './SketchSnappingTool'
    import { SimpleLineSymbol } from '../../base/symbol'
    import GeometryEngine from '../../base/geometry/GeometryEngine'
    /**
     * 面绘图工具类
     * @class SketchPolylineDrawTool
     * @moduleEX SketchEditorModule
     * @extends SketchBaseDrawTool
     * @param {Object} options 构造参数
     * @param {MapView|SceneView}  [options.view]  地图视图对象
     * @param {GraphicsLayer}  [options.layer]  草图图层管对象
     * @param {SketchStyle}  [options.sketchStyle]  草图符号
     */
    class SketchPolylineDrawTool extends SketchBaseDrawTool {
      constructor(options) {
        super(options)
        this._drawTools = [this]
        this._otherDrawTools = []
        this.snapAndReferGeometries = defaultValue(
          options.snapAndReferGeometries,
          []
        )
      }

      /**
       * @description 鼠标绘制图形：鼠标单击绘制区的一个顶点；鼠标移动，区图形随鼠标位置变动；鼠标双击，完成区图形绘制。
       */
      drawFeature() {
        // 屏蔽地图默认双击事件
        this.view._mapActionControl('double-click-zoom', false)
        // 控制鼠标移动事件频率
        const timer = null
        // 鼠标点击两次以上，即有两个以上的点构成区时，触发鼠标移动时逻辑
        let isStartDrawing = false
        let afterClick = false
        // 鼠标移动过程中，控制鼠标移动逻辑触发次数
        let moving = false
        // 当前正在绘制的图形对象
        let feature = null
        let pixelCoords = []
        // 绘制过程中所有的端点
        let polylineSpots = []
        // 绘制过程中所有所有线段的斜率
        const polylineSpotSlopes = []
        // timer判断是单击事件、双击事件
        const clickTimer = null
        // 区分单击、双击事件，若为双击事件，则阻止单击事件逻辑触发
        // let preventClick = false
        let lastAction = ''
        // 获取两点斜率
        const getSlope = function (point1, point2) {
          return (point1[1] - point2[1]) / (point1[0] - point2[0])
        }
        // 捕获到的坐标点
        let snapPoint = null
        // 处理鼠标点击事件。点击后渲染端点图形，渲染区图形
        const handlerClick = (options) => {
          // clickTimer = setTimeout(() => {
          //   preventClick = false
          // }, 300)
          // // 判断是否为单击事件
          // if (preventClick) return
          if (!options || !options.x || !options.y) return
          clearTimeout(timer)
          this._editMode = 3
          const pixelCoord = { x: options.x, y: options.y }
          let geoCoord = null
          if (!snapPoint) {
            // 如果没有捕获结果，则此时坐标点为屏幕地理坐标
            geoCoord = this.view.toMap({ x: pixelCoord.x, y: pixelCoord.y })
            // if (this._hight) {
            //   geoCoord = new Point({
            //     coordinates: [
            //       geoCoord.coordinates[0],
            //       geoCoord.coordinates[1],
            //       this._hight
            //     ],
            //     spatialReference: this._spatialReference
            //   })
            // }
          } else {
            // 如果有捕获结果，则此时坐标点选取捕获的坐标点
            geoCoord = snapPoint
          }
          if (polylineSpots.length === 0) {
            pixelCoords.push(pixelCoord)
            polylineSpots.push(geoCoord.coordinates)
          } else if (polylineSpots.length === 1) {
            pixelCoords.push(pixelCoord)
            polylineSpots.push(geoCoord.coordinates)
            feature = this._getFeature()
            feature.geometry._pixelCoords = pixelCoords
            feature.geometry.coordinates = polylineSpots
            // 保存当前编辑中的geometry
            this._polylineGeometry = feature
          } else {
            pixelCoords[pixelCoords.length - 1] = pixelCoord
            polylineSpots[polylineSpots.length - 1] = geoCoord.coordinates
            feature.geometry._pixelCoords = pixelCoords
            feature.geometry.coordinates = polylineSpots
            // feature.geometry.coordinates[feature.geometry.coordinates.length - 1] =
            //   geoCoord.coordinates
          }
          // 临时解决，move事件有可能发生在两个click事件之间，导致多绘制一个点
          if (
            lastAction === 'move' &&
            polylineSpots[polylineSpots.length - 1][0] ===
              polylineSpots[polylineSpots.length - 2][0] &&
            polylineSpots[polylineSpots.length - 1][1] ===
              polylineSpots[polylineSpots.length - 2][1]
          ) {
            polylineSpots.splice(polylineSpots.length - 1)
          }

          const pointDrawTool = new SketchPointDrawTool({
            view: this.view,
            layer: this.layer,
            _parent: this,
            sketchStyle: this.sketchStyle
          })
          pointDrawTool.addFeature(geoCoord)
          const vertexGraphic = pointDrawTool.sketchStage.entityGraphic
          this.sketchStage.entityGraphic = feature
          this.sketchStage.vertexGraphics.push(vertexGraphic)

          // 在polyline中更新所有图形
          if (feature) {
            isStartDrawing = true
            afterClick = isStartDrawing
          }
          // preventClick = true
          // 计算线段斜率
          if (polylineSpots.length > 1) {
            polylineSpotSlopes.push(
              getSlope(
                polylineSpots[polylineSpots.length - 1],
                polylineSpots[polylineSpots.length - 2]
              )
            )
          }
          // this.startTime = new Date().getTime()
          lastAction = 'click'
          // 发送绘制一个顶点完成事件
          this.fire(
            'drawn-vertex',
            { geometry: pointDrawTool.sketchStage.entityGraphic },
            self
          )
        }
        // 处理平移时，鼠标移动时逻辑。鼠标移动时根据鼠标坐标实时更新区图形。
        let isFirstAdd = true
        const handlerMove = (options) => {
          if (!options || !options.x || !options.y) return
          if (!isStartDrawing || moving) return
          clearTimeout(timer)
          moving = true
          // 清除捕获效果（上一次）
          if (this.sketchStage.snapGraphics.length > 0) {
            this.sketchStage.snapGraphics.forEach((feature) => {
              this._removeFeatureFromMap(feature)
            })
            this.sketchStage.snapGraphics = []
          }

          const pixelCoord = { x: options.x, y: options.y }
          const geoCoord = this.view.toMap({ x: pixelCoord.x, y: pixelCoord.y })
          // if (this._hight) {
          //   geoCoord = new Point({
          //     coordinates: [
          //       geoCoord.coordinates[0],
          //       geoCoord.coordinates[1],
          //       this._hight
          //     ],
          //     spatialReference: this._spatialReference
          //   })
          // }

          this.endTime = new Date().getTime()
          if (afterClick) {
            pixelCoords[pixelCoords.length] = pixelCoord
            polylineSpots[polylineSpots.length] = geoCoord.coordinates
            afterClick = false
          } else {
            pixelCoords[pixelCoords.length - 1] = pixelCoord
            polylineSpots[polylineSpots.length - 1] = geoCoord.coordinates
          }
          this.sketchStage.entityGraphic = feature

          // 鼠标移动时，去捕获重合点、点在线上、平行线、垂直线
          snapPoint = this.getSnapGraphics(
            geoCoord,
            polylineSpots,
            polylineSpotSlopes
          )
          if (snapPoint) {
            polylineSpots[polylineSpots.length - 1] = snapPoint.coordinates // geoCoord.coordinates
          }

          // 更新草图图层
          feature.geometry._pixelCoords = pixelCoords
          feature.geometry.coordinates = JSON.parse(JSON.stringify(polylineSpots))
          if (isFirstAdd) {
            this._addFeaturesToMap(feature)
            isFirstAdd = false
          }
          moving = false
          lastAction = 'move'
        }
        // 处理鼠标双击时，处理逻辑
        const handlerDoubleClick = () => {
          clearTimeout(clickTimer)
          clearTimeout(timer)
          // preventClick = true

          // if (!isStartDrawing) {
          //   feature = null
          //   polylineSpots = []
          //   pixelCoords = []
          //   return
          // }

          polylineSpots = []
          pixelCoords = []
          // 停止绘制
          this.stop()
          // 清除捕获效果
          if (this.sketchStage.snapGraphics.length > 0) {
            this.sketchStage.snapGraphics.forEach((feature) => {
              this._removeFeatureFromMap(feature)
            })
            this.sketchStage.snapGraphics = []
          }
          this._editMode = 0
          // 绘制完成后，移除顶点
          this.sketchStage.vertexGraphics.forEach((feature) => {
            this._removeFeatureFromMap(feature)
          })
          this.sketchStage.vertexGraphics = []
          // 恢复地图默认双击事件
          this.view._mapActionControl('double-click-zoom', true)
          lastAction = 'double-click'

          // 计算交点，将polyline转为polygon 的feature，并更新图层
          const polygon = this._createPolygonFeatureByPolyline(
            this.sketchStage.entityGraphic.geometry
          )
          this._removeFeatureFromMap(this.sketchStage.entityGraphic)
          // 发送绘制完成事件
          this.fire('drawn', { geometry: polygon }, self)
        }
        // 移除绘制事件
        this._drawEventHandlers.push(handlerClick, handlerMove, handlerDoubleClick)
        this.view.on(ViewEventType.immediateClick, handlerClick)
        this.view.on(ViewEventType.pointerMove, handlerMove)
        this.view.on(ViewEventType.doubleClick, handlerDoubleClick)
      }

      _createPolygonFeatureByPolyline(polyline) {
        // const polyline = feature.geometry
        const lineToCloseLine = (polyline) => {
          const coordinates = JSON.parse(JSON.stringify(polyline.coordinates))
          coordinates.push([polyline.coordinates[0]])
          const closePolyline = new LineString({
            coordinates,
            spatialReference: polyline._spatialReference
          })
          return closePolyline
        }
        const lineToPolygon = (polyline) => {
          const coordinates = JSON.parse(JSON.stringify(polyline.coordinates))
          coordinates.push(coordinates[0])
          const closePolyline = new Polygon({
            coordinates: [coordinates],
            spatialReference: polyline._spatialReference
          })
          return closePolyline
        }
        const closePolygon = lineToPolygon(polyline)
        const getValidGraphics = () => {
          const validGraphics = []
          this.snapAndReferGeometries.forEach((graphic) => {
            if (
              graphic instanceof Polygon ||
              graphic instanceof Circle ||
              graphic instanceof Extent
            ) {
              const isIntersect = GeometryEngine.intersects(polyline, graphic)
              if (isIntersect) {
                validGraphics.push(graphic)
              }
            }
          })
          return validGraphics
        }
        const validGraphics = getValidGraphics()
        const comparedPolygon = GeometryEngine.union(validGraphics)
        let resultPolygon
        if (comparedPolygon && !(comparedPolygon instanceof Array)) {
          resultPolygon = GeometryEngine.difference(closePolygon, comparedPolygon)
        } else {
          resultPolygon = closePolygon
        }
        return resultPolygon // polygonFeature
      }

      /**
       * @description 获取feature实例
       * @private
       * @param {Point} point 生成面的点地理坐标集
       * @param {Symbol} symbol 点的符号样式
       */
      _getFeature(points) {
        if (!points) {
          points = [
            [0, 0],
            [1, 1]
          ]
        }
        const geometry = new LineString({
          coordinates: points,
          spatialReference: this._spatialReference
        })
        const symbol = this.sketchStyle.lineStyle
        const polylineGeometry = new Feature({
          geometry,
          symbol
        })
        return polylineGeometry
      }

      /**
       * 图形捕获，捕获重合点、点在线上、平行线、垂直线
       * @private
       * @param {Point} geoCoord 当前坐标点
       * @param {Array} polygonSpots 被捕获的顶点数据组
       * @param {Array} polygonSpotSlopes 被捕获的直线斜率数据组
       */
      getSnapGraphics(targetPoint, polygonSpots) {
        let realPoint = null
        const tolerance = this.getDistanceByPixel
          ? this.getDistanceByPixel(this.sketchSnappingTool.pixelTolerance)
          : 200
        const moveLine = new LineString({
          coordinates: polygonSpots.slice(polygonSpots.length - 2),
          spatialReference: this._spatialReference
        })
        let geometries
        if (this.sketchSnappingTool.snapSketchGeometry && polygonSpots.length > 3) {
          const entityPolyline = new LineString({
            coordinates: polygonSpots.slice(0, polygonSpots.length - 2),
            spatialReference: this._spatialReference
          })
          geometries = this.snapAndReferGeometries.concat([entityPolyline])
        } else {
          geometries = this.snapAndReferGeometries
        }
        // 获取捕获结果
        const snapResult = this.sketchSnappingTool.snapGeometries(
          targetPoint,
          moveLine,
          geometries,
          tolerance
        )
        if (snapResult.coincidentPoint) {
          // 端点重合
          const pointFeature = new Feature({
            geometry: snapResult.coincidentPoint.realPoint,
            symbol: this.sketchStyle._coincidentPointStyle
          })
          this.sketchStage.snapGraphics.push(pointFeature)
          realPoint = snapResult.coincidentPoint.realPoint
        } else if (snapResult.inLineAndParallel) {
          snapResult.inLineAndParallel.lines.forEach((line) => {
            const lineFeature = new Feature({
              geometry: line,
              symbol: new SimpleLineSymbol({
                color: new Color(255, 255, 0, 1),
                width: 3
              })
            })
            this.sketchStage.snapGraphics.push(lineFeature)
          })
          const pointFeature = new Feature({
            geometry: snapResult.inLineAndParallel.realPoint,
            symbol: this.sketchStyle._selectVertexStyle
          })
          this.sketchStage.snapGraphics.push(pointFeature)
          if (snapResult.inLineAndParallel.symbolGeometry) {
            const symbolFeature = new Feature({
              geometry: snapResult.inLineAndParallel.symbolGeometry,
              symbol: new SimpleLineSymbol({
                color: new Color(255, 255, 0, 1),
                width: 3
              })
            })
            this.sketchStage.snapGraphics.push(symbolFeature)
          }
          realPoint = snapResult.inLineAndParallel.realPoint
        } else if (snapResult.inLineAndPerpendicular) {
          snapResult.inLineAndPerpendicular.lines.forEach((line) => {
            const lineFeature = new Feature({
              geometry: line,
              symbol: new SimpleLineSymbol({
                color: new Color(255, 255, 0, 1),
                width: 3
              })
            })
            this.sketchStage.snapGraphics.push(lineFeature)
          })
          const pointFeature = new Feature({
            geometry: snapResult.inLineAndPerpendicular.realPoint,
            symbol: this.sketchStyle._selectVertexStyle
          })
          this.sketchStage.snapGraphics.push(pointFeature)
          if (snapResult.inLineAndPerpendicular.symbolGeometry) {
            const symbolFeature = new Feature({
              geometry: snapResult.inLineAndPerpendicular.symbolGeometry,
              symbol: new SimpleLineSymbol({
                color: new Color(255, 255, 0, 1),
                width: 3
              })
            })
            this.sketchStage.snapGraphics.push(symbolFeature)
          }
          realPoint = snapResult.inLineAndPerpendicular.realPoint
        } else if (snapResult.pointInLine) {
          // 点在线上捕获上图
          const lineFeature = new Feature({
            geometry: snapResult.pointInLine.line,
            symbol: new SimpleLineSymbol({
              color: new Color(255, 255, 0, 1),
              width: 3
            })
          })
          this.sketchStage.snapGraphics.push(lineFeature)
          const pointFeature = new Feature({
            geometry: snapResult.pointInLine.realPoint,
            symbol: this.sketchStyle._selectVertexStyle
          })
          this.sketchStage.snapGraphics.push(pointFeature)
          realPoint = snapResult.pointInLine.realPoint
        } else if (snapResult.parallelLine) {
          // 平行捕获结果上图
          const lineFeature = new Feature({
            geometry: snapResult.parallelLine.line,
            symbol: new SimpleLineSymbol({
              color: new Color(255, 255, 0, 1),
              width: 3
            })
          })
          this.sketchStage.snapGraphics.push(lineFeature)
          const pointFeature = new Feature({
            geometry: snapResult.parallelLine.realPoint,
            symbol: this.sketchStyle._selectVertexStyle
          })
          this.sketchStage.snapGraphics.push(pointFeature)
          // 渲染高亮平行
          if (snapResult.parallelLine.symbolGeometry) {
            const symbolFeature = new Feature({
              geometry: snapResult.parallelLine.symbolGeometry,
              symbol: new SimpleLineSymbol({
                color: new Color(255, 255, 0, 1),
                width: 3
              })
            })
            this.sketchStage.snapGraphics.push(symbolFeature)
          }
          realPoint = snapResult.parallelLine.realPoint
        } else if (snapResult.perpendicularLine) {
          // 渲染高亮垂直，坐标点
          const lineFeature = new Feature({
            geometry: snapResult.perpendicularLine.line,
            symbol: new SimpleLineSymbol({
              color: new Color(255, 255, 0, 1),
              width: 3
            })
          })
          this.sketchStage.snapGraphics.push(lineFeature)
          const pointFeature = new Feature({
            geometry: snapResult.perpendicularLine.realPoint,
            symbol: this.sketchStyle._selectVertexStyle
          })
          this.sketchStage.snapGraphics.push(pointFeature)
          // 渲染高亮垂足
          if (snapResult.perpendicularLine.symbolGeometry) {
            const symbolFeature = new Feature({
              geometry: snapResult.perpendicularLine.symbolGeometry,
              symbol: new SimpleLineSymbol({
                color: new Color(255, 255, 0, 1),
                width: 3
              })
            })
            this.sketchStage.snapGraphics.push(symbolFeature)
          }
          realPoint = snapResult.perpendicularLine.realPoint
        }
        this.sketchStage.snapGraphics.forEach((feature) => {
          this._addFeaturesToMap(feature)
        })
        return realPoint
      }
    }
    export default SketchPolylineDrawTool