    import { Evented, ViewEventType } from '../../base'
    import { defaultValue, getGUID } from '../../util'
    import { SpatialReference } from '../../base/geometry'
    /**
     * 草图基础绘图工具类
     * @class SketchBaseDrawTool
     * @moduleEX SketchEditorModule
     * @param {Object} options 构造参数
     * @param {MapView|SecenView}  [options.mapView]  地图视图对象
     * @param {GraphicsLayer}  [options.layer]  草图图层管对象
     * @param {SketchStyle}  [options.sketchStyle]  草图符号
     * @param {Function}  [options._hitTestEvent]  草图拾取事件
     */

    class SketchBaseDrawTool extends Evented {
      constructor(options) {
        super()
        this._id = defaultValue(options.id, getGUID())
        /**
         * 地图视图
         * @member {MapView|SecenView} SketchEditor.prototype._mapView
         */
        this._mapView = defaultValue(options.mapView, null)
        this._spatialReference = options.mapView.crs
          ? new SpatialReference(options.mapView.crs.code)
          : new SpatialReference('EPSG:4326')
        /**
         * 草图图层
         * @member {GraphicsLayer} SketchEditor.prototype._layer
         */
        this._layer = defaultValue(options.layer, undefined)
        /**
         * 草图符号
         * @member {SketchStyle} SketchEditor.prototype._sketchStyle
         */
        this._sketchStyle = defaultValue(options.sketchStyle, undefined)
        /**
         * 草图拾取事件
         * @member {Function} SketchEditor.prototype._hitTestEvent
         */
        this._hitTestEvent = defaultValue(options._hitTestEvent, undefined)
        /**
         * 草图绘制鼠标事件处理集
         * @member {Array} SketchEditor.prototype._mouseEventHandlers
         */
        this._mouseEventHandlers = []
        /**
         * 草图拾取事件处理集
         * @member {Array} SketchEditor.prototype._hitTestEventHandlers
         */
        this._hitTestEventHandlers = []
        /**
         * 草图类型
         * @member {Strign} SketchEditor.prototype._sketchDataType
         */
        this._sketchDataType = null
        this._mapView.sketchFeatures = this._mapView.sketchFeatures
          ? this._mapView.sketchFeatures
          : []
        this._drawTools = []
        this._hitTestDrawToolStack = []
      }

      /**
       * 开始绘制草图
       */
      start() {
        this.stop()
        this.drawFeature()
      }

      /**
       * 停止绘制草图
       */
      stop() {
        if (this._editMode === 3 || this._editMode === 0) {
          this._stopDraw()
        } else if (this._editMode === 1 || this._editMode === 2) {
          this._stopHitTest()
        } else {
          this._stopDraw()
          this._stopHitTest()
        }
      }

      /**
       * 停止所有鼠标事件
       * @private
       */
      _stopAll() {
        this._stopDraw()
        this._stopHitTest()
      }

      /**
       * 停止所有鼠标绘制相关事件
       * @private
       */
      _stopDraw() {
        if (this._mouseEventHandlers) {
          this._mouseEventHandlers.forEach((handler) => {
            this._mapView.off(ViewEventType.click, handler)
            this._mapView.off(ViewEventType.mouseUp, handler)
            this._mapView.off(ViewEventType.mouseMove, handler)
            this._mapView.off(ViewEventType.mouseDown, handler)
            this._mapView.off(ViewEventType.doubleClick, handler)
          })
          this._mouseEventHandlers = null
        }
      }

      /**
       * 停止所有拾取相关事件
       * @private
       */
      _stopHitTest() {
        if (this._hitTestEventHandlers && this._hitTestILayer) {
          this._hitTestEventHandlers.forEach((handler) => {
            this._hitTestILayer.off(ViewEventType.click, handler)
            this._mapView.off(ViewEventType.mouseUp, handler)
            this._mapView.off(ViewEventType.mouseMove, handler)
            this._mapView.off(ViewEventType.mouseDown, handler)
            this._mapView.off(ViewEventType.click, handler)
          })
          this._hitTestEventHandlers = null
        }
      }

      /**
       * 设置草图样式
       * @param {SketchStyle} sketchStyle
       */
      setSketchStyle(sketchStyle) {
        this._sketchStyle = sketchStyle
      }

      /**
       * 判断feature是否是绘制图形中
       * @private
       * @param {SketchStyle} sketchStyle
       */
      _isDrawToolFeature(feature) {
        const id = feature.id
        let isDrawTool = false
        if (this._sketchStage.entityGraphic.id === id) {
          isDrawTool = true
          this._editMode = 1
        }
        this._sketchStage.vertexGraphics.forEach((item) => {
          if (item.id === id) {
            isDrawTool = true
            this._editMode = 2
          }
        })
        this._sketchStage.midVertexGraphics.forEach((item) => {
          if (item.id === id) {
            isDrawTool = true
            this._editMode = 2
          }
        })
        if (!isDrawTool) {
          this._editMode = 0
        }
        return isDrawTool
      }

      _getDrawToolByFeature(feature) {
        const id = feature.id
        let drawTool = null
        if (this._sketchStage.entityGraphic.id === id) {
          drawTool = this._sketchStage.entityGraphic
        }
        return drawTool.length > 0 ? drawTool[0] : null
      }

      /**
       * 将图形渲染到地图中
       * @private
       * */
      _addFeaturesToMap(feature) {
        if (this._layer) {
          this._layer.add(feature)
        }
      }

      _removeFeatureFromMap(feature) {
        if (this._layer) {
          this._layer.remove(feature)
        }
      }

      /**
       * 草图事件分发
       * @private
       * @param {String} type 事件类型
       * @param {object} data 传递数据
       */
      _dispatchEvent(type, data, propagate) {
        // 父级草图更新
        if (this._parent) {
          this._parent.fire(type, data, propagate)
        }
        return this
      }

      /**
       * 更新feature
       * @param {Point} point 待更新的位置
       * @param {Feature} feature 被更新的feature
       */
      updateFeature(point, feature) {
        const id = feature.id
        if (this._sketchStage.entityGraphic.id === id) {
          this._sketchStage.entityGraphic.coordinates = point.coordinates
          this._sketchStage.entityGraphic.geometry = point
          feature = this._sketchStage.entityGraphic
        }
      }

      updateSketchStage(sketchStage) {
        this._sketchStage = sketchStage
        const features = this._sketchStage.getAllFeatures()
        this._mapView.sketchFeatures = features
        this._addFeaturesToMap()
      }

      /**
       * @description 清除草图工具
       */
      removeDrawTool() {
        this._sketchStage.getAllFeatures().forEach((feature) => {
          this._removeFeatureFromMap(feature)
        })
        this._stopAll()
      }

      /**
       * @description 清除实体图形
       * @private
       */
      removeEntityGraphic() {
        this._removeFeatureFromMap(this._sketchStage.entityGraphic)
        this._sketchStage.entityGraphic = null
      }

      /**
       * @description 清除顶点图形
       * @private
       */
      removeVertexGraphics() {
        this._sketchStage.vertexGraphics.forEach((feature) => {
          this._removeFeatureFromMap(feature)
        })
        this._sketchStage.vertexGraphics = []
      }

      /**
       * 当前草图图形中插入新的顶点
       * @param {Point} point 新增/插入顶点
       * @param {Number} index 新增/新增点的序号
       */
      addVertex(point, index) {}

      /**
       * 更新当前草图图形的某个顶点
       * @param {Point} point 新的顶点
       * @param {Number} index 需更新的顶点的序号
       */
      updateVertex(point, index) {}

      /**
       * 移除草图图形的某个顶点
       * @param {Number} index 需更新的顶点的序号
       */
      removeVertex(point, index) {}

      /**
       * @description 删除选中的顶点
       * @private
       */
      deleteSelectedVertex() {}

      // 临时用于更新图形
      removeAddGraphic(newFeature) {
        // test
        // 更新sketchFeatures
        this._mapView.sketchFeatures = this._mapView.sketchFeatures
          ? this._mapView.sketchFeatures
          : []
        let haveFeature = false
        this._mapView.sketchFeatures.forEach((feature) => {
          if (feature.id === newFeature.id) {
            feature = newFeature
            haveFeature = true
          }
        })
        if (!haveFeature) {
          this._mapView.sketchFeatures.push(newFeature)
        }
        this._addFeaturesToMap(true)
      }

      updateAllFeature(point) {
        this._sketchStage.entityGraphic.coordinates = point.coordinates
        this._sketchStage.entityGraphic.geometry = point
        this._mapView.sketchFeatures.forEach((item) => {
          if (item.id === this._sketchStage.entityGraphic.id) {
            item = this._sketchStage.entityGraphic
          }
        })
        this._addFeaturesToMap()
      }

      getDistanceByPixel(pixel) {
        return this._mapView.getResolution() * pixel
      }

      getPanCoordinates(coordinates, deltaX, deltaY) {
        return [coordinates[0] + deltaX, coordinates[1] + deltaY]
      }

      getScaleCoordinates(
        coordinates,
        direction,
        extent,
        startPoint,
        movePoint,
        oriCoordinates
      ) {
        const getXY = function (xy, extent, direction, oriCoordinate) {
          let scaleX1 = 1
          let scaleY1 = 1
          let newX = Number(xy[0].toString())
          let newY = Number(xy[1].toString())
          const sCoordinate = startPoint.coordinates
          const mCoordinate = movePoint.coordinates
          oriCoordinate = oriCoordinate || []
          if (direction === 'ne') {
            scaleX1 =
              (mCoordinate[0] - extent.xmin) / (sCoordinate[0] - extent.xmin)
            newX = ([oriCoordinate[0]] - extent.xmin) * scaleX1 + extent.xmin

            scaleY1 =
              (mCoordinate[1] - extent.ymin) / (sCoordinate[1] - extent.ymin)
            newY = (oriCoordinate[1] - extent.ymin) * scaleY1 + extent.ymin
          }
          if (direction === 'se') {
            scaleX1 =
              (mCoordinate[0] - extent.xmin) / (sCoordinate[0] - extent.xmin)
            newX = ([oriCoordinate[0]] - extent.xmin) * scaleX1 + extent.xmin

            scaleY1 =
              (mCoordinate[1] - extent.ymax) / (sCoordinate[1] - extent.ymax)
            newY = (oriCoordinate[1] - extent.ymax) * scaleY1 + extent.ymax
          }
          if (direction === 'sw') {
            scaleX1 =
              (mCoordinate[0] - extent.xmax) / (sCoordinate[0] - extent.xmax)
            newX = ([oriCoordinate[0]] - extent.xmax) * scaleX1 + extent.xmax

            scaleY1 =
              (mCoordinate[1] - extent.ymax) / (sCoordinate[1] - extent.ymax)
            newY = (oriCoordinate[1] - extent.ymax) * scaleY1 + extent.ymax
          }
          if (direction === 'nw') {
            scaleX1 =
              (mCoordinate[0] - extent.xmax) / (sCoordinate[0] - extent.xmax)
            newX = ([oriCoordinate[0]] - extent.xmax) * scaleX1 + extent.xmax

            scaleY1 =
              (mCoordinate[1] - extent.ymin) / (sCoordinate[1] - extent.ymin)
            newY = (oriCoordinate[1] - extent.ymin) * scaleY1 + extent.ymin
          }
          return [newX, newY]
        }
        const newCoordinates = []
        oriCoordinates = oriCoordinates || []
        coordinates.forEach((coordinate, i) => {
          const result = getXY(coordinate, extent, direction, oriCoordinates[i])
          newCoordinates.push(result)
        })
        return newCoordinates
      }

      getMidScaleCoordinates(
        coordinates,
        direction,
        extent,
        startPoint,
        movePoint,
        oriCoordinates
      ) {
        const getXY = function (xy, extent, direction, oriCoordinate) {
          let scaleX1 = 1
          let scaleY1 = 1
          let newX = xy[0]
          let newY = xy[1]
          const sCoordinate = startPoint.coordinates
          const mCoordinate = movePoint.coordinates
          oriCoordinate = oriCoordinate || []
          if (direction === 'e') {
            // 判断是否超过边缘坐标
            scaleX1 =
              (mCoordinate[0] - extent.xmin) / (sCoordinate[0] - extent.xmin)
            newX = ([oriCoordinate[0]] - extent.xmin) * scaleX1 + extent.xmin
          }
          if (direction === 's') {
            scaleY1 =
              (mCoordinate[1] - extent.ymax) / (sCoordinate[1] - extent.ymax)
            newY = (oriCoordinate[1] - extent.ymax) * scaleY1 + extent.ymax
          }
          if (direction === 'w') {
            scaleX1 =
              (mCoordinate[0] - extent.xmax) / (sCoordinate[0] - extent.xmax)
            newX = ([oriCoordinate[0]] - extent.xmax) * scaleX1 + extent.xmax
          }
          if (direction === 'n') {
            scaleY1 =
              (mCoordinate[1] - extent.ymin) / (sCoordinate[1] - extent.ymin)
            newY = (oriCoordinate[1] - extent.ymin) * scaleY1 + extent.ymin
          }
          return [newX, newY]
        }
        const newCoordinates = []
        oriCoordinates = oriCoordinates || []
        coordinates.forEach((coordinate, i) => {
          const result = getXY(coordinate, extent, direction, oriCoordinates[i])
          newCoordinates.push(result)
        })
        return newCoordinates
      }

      addByFeature(feature) {
        this._sketchStage.entityGraphic = feature
        this._mapView.sketchFeatures.push(feature)
        // // 更新图层图形
        // this._addFeaturesToMap()
      }

      _setSketchStage(stage) {
        this._sketchStage = stage
      }

      // 临时方法
      _removeFromSketchFeatures(removedFeatures) {
        this._mapView.sketchFeatures.forEach((feature, i) => {
          if (removedFeatures.filter((item) => item.id === feature.id).length > 0) {
            delete this._mapView.sketchFeatures[i]
          }
        })
        this._mapView.sketchFeatures = this._mapView.sketchFeatures.filter(
          (item) => item !== undefined
        )
      }
    }
    export default SketchBaseDrawTool