    import { Evented, Feature, SketchDataType, ViewEventType } from '../../base'
    import { Point, LineString, Polygon } from '../../base/geometry'
    import { defaultValue, Log } from '../../util'
    import SketchStyle from './SketchStyle'

    /**
     * 草图编辑基类
     * @classdesc 草图编辑基类
     * @moduleEX SketchEditorModule
     * @extends Evented
     * @param {Object} options 构造参数
     * @param {VideoMapView} [options.mapView] 视图
     * @param {SketchStyle} [options.sketchStyle] 草图样式
     * @example
     * // ES5引入方式
     * const { SketchEditorVideo } = Zondy
     * // ES6引入方式
     * import { SketchEditorVideo } from "@mapgis/webclient-common"
     * // 新建一个草图编辑器，传入视频地图mapview
     * sketchEditorVideo = new SketchEditorVideo({
     *   mapView: videoMapView
     * })
     */
    class SketchEditorVideoBase extends Evented {
      /**
       * @param {Object} options
       * @param {VideoMapView} options.mapView 视图
       * @param {SketchStyle} [options.sketchStyle] 草图样式
       */
      constructor(options) {
        super()
        options = defaultValue(options, {})
        if (!options.mapView) {
          Log.error('options.mapView is null!', options)
        }

        this._mapView = options.mapView

        this._coordTransfomrs = defaultValue(
          this._mapView.videoPixelCoordTransforms,
          undefined
        )

        this._mouseEventHandlers = null

        this.sketchStyle = defaultValue(options.sketchStyle, new SketchStyle())

        this._sketchDataType = null

        this._pointGeomtry = null
        this._lineGeomtry = null
        this._polygonGeomtry = null
        this._textGeomtry = null
      }

      /**
       * 像素坐标与地理坐标转换矩阵
       * @readonly
       * @type {VideoPixelCoordTransforms}
       */
      get coorTransfomrs() {
        return this._coordTransfomrs
      }

      /**
       * 开始草图编辑
       * @function SketchEditorVideoBase.prototype.start
       * @param {SketchDataType} dataType 草图编辑类型
       */
      start(dataType) {
        this._stopCurrentGraphicDrawing()
        this.clearGeometry()
        this._mapView._enabledMouseEvent('auto')
        switch (dataType) {
          case SketchDataType.POINT:
            this._sketchDataType = SketchDataType.POINT
            this._drawPoint()
            break
          case SketchDataType.POLYLINE:
            this._sketchDataType = SketchDataType.POLYLINE
            this._drawLine()
            break
          case SketchDataType.POLYGON:
            this._sketchDataType = SketchDataType.POLYGON
            this._drawPolygon()
            break
        }
      }

      /**
       * 结束草图编辑
       * @function SketchEditorVideoBase.prototype.stop
       */
      stop() {
        this._stopCurrentGraphicDrawing()

        this.clearGeometry()

        this._mapView._enabledMouseEvent('none')
      }

      /**
       * 获取当前草图数据类型
       * @function SketchEditorVideoBase.prototype.getSketchDataType
       * @returns {SketchDataType}
       */
      getSketchDataType() {
        return this._sketchDataType
      }

      /**
       * 获取几何
       * @function SketchEditorVideoBase.prototype.getGeometry
       * @returns {Geometry}
       */
      getGeometry() {
        if (this._sketchDataType === SketchDataType.POINT) {
          if (this._pointGeomtry) {
            const geometry = new Point({
              coordinates: this._pointGeomtry.geometry.coordinates
            })
            geometry._pixelCoords = this._pointGeomtry.geometry._pixelCoords
            return geometry
          }
        } else if (this._sketchDataType === SketchDataType.POLYLINE) {
          if (this._lineGeomtry) {
            const geometry = new LineString({
              coordinates: this._lineGeomtry.geometry.coordinates
            })
            geometry._pixelCoords = this._lineGeomtry.geometry._pixelCoords
            return geometry
          }
        } else if (this._sketchDataType === SketchDataType.POLYGON) {
          if (this._polygonGeomtry) {
            const geometry = new Polygon({
              coordinates: this._polygonGeomtry.geometry.coordinates
            })
            geometry._pixelCoords = this._polygonGeomtry.geometry._pixelCoords
            return geometry
          }
        }
      }

      /**
       * 删除编辑中的几何
       * @function SketchEditorVideoBase.prototype.clearGeometry
       */
      clearGeometry() {
        if (this._pointGeomtry) {
          this._mapView.graphics.remove(this._pointGeomtry)
        }
        if (this._lineGeomtry) {
          this._mapView.graphics.remove(this._lineGeomtry)
        }
        if (this._polygonGeomtry) {
          this._mapView.graphics.remove(this._polygonGeomtry)
        }
        if (this._textGeomtry) {
          this._mapView.graphics.remove(this._textGeomtry)
        }
        this._pointGeomtry = null
        this._lineGeomtry = null
        this._polygonGeomtry = null
        this._textGeomtry = null
      }

      isSketchValid() {}

      /**
       * 设置草图样式
       * @function SketchEditorVideoBase.prototype.setSketchStyle
       * @param {SketchStyle} sketchStyle
       * @example
       * // ES5引入方式
       * const { SimpleFillSymbol, SimpleLineSymbol } = Zondy.Symbol
       * const { Color, SketchStyle } = Zondy
       * // ES6引入方式
       * import { SimpleFillSymbol, SimpleLineSymbol, Color, SketchStyle } from "@mapgis/webclient-common"
       * // 新建一个填充样式
       * const fillStyle = new SimpleFillSymbol({
       *   color: new Color(0, 255, 255, 1),
       *   outline: new SimpleLineSymbol({
       *     color: new Color(255, 0, 0, 1),
       *     width: 2
       *   })
       * })
       * // 新建一个草图样式
       * const sketchStyle = new SketchStyle({
       *   // 传入填充样式给区注记使用
       *   fillStyle: fillStyle,
       *   // 绘制线注记时显示分段长度
       *   isShowSegmentLength: true,
       *   // 绘制区注记时显示面积
       *   isShowArea: true
       * })
       * sketchEditorVideo.setSketchStyle(sketchStyle)
       */
      setSketchStyle(sketchStyle) {
        this.sketchStyle = sketchStyle
      }

      /**
       * 获取草图样式
       * @function SketchEditorVideoBase.prototype.getSketchStyle
       * @returns {SketchStyle}
       */
      getSketchStyle() {
        return this.sketchStyle
      }

      _stopCurrentGraphicDrawing() {
        if (this._mouseEventHandlers) {
          this._mouseEventHandlers.forEach((handler) => {
            this._mapView.off(ViewEventType.mouseDown, handler)
            this._mapView.off(ViewEventType.mouseUp, handler)
            this._mapView.off(ViewEventType.mouseMove, handler)
            this._mapView.off(ViewEventType.doubleClick, handler)
          })
          this._mouseEventHandlers = null
        }
      }

      /**
       * @private
       */
      _getGraphic() {
        if (this._sketchDataType === SketchDataType.POINT) {
          const geometry = new Point({
            coordinates: [0, 0, 0]
          })
          const symbol = this.sketchStyle.vertexStyle
          const pointGeometry = new Feature({
            geometry,
            symbol
          })

          return pointGeometry
        } else if (this._sketchDataType === SketchDataType.POLYLINE) {
          const geometry = new LineString({
            coordinates: [
              [0, 0],
              [1, 1]
            ]
          })
          const symbol = this.sketchStyle.lineStyle
          const lineGeometry = new Feature({
            geometry,
            symbol
          })
          lineGeometry.isShowSegmentLength = this.sketchStyle.isShowSegmentLength
          if (lineGeometry.isShowSegmentLength) {
            lineGeometry._textStyle = this.sketchStyle.textStyle
          }
          return lineGeometry
        } else if (this._sketchDataType === SketchDataType.POLYGON) {
          const geometry = new Polygon({
            coordinates: [
              [
                [0, 0],
                [0, 0],
                [0, 0],
                [0, 0]
              ]
            ]
          })
          const symbol = this.sketchStyle.fillStyle
          const polygonGeometry = new Feature({
            geometry,
            symbol
          })
          polygonGeometry.isShowArea = this.sketchStyle.isShowArea
          if (polygonGeometry.isShowArea) {
            polygonGeometry._textStyle = this.sketchStyle.textStyle
          }
          return polygonGeometry
        }
      }

      /**
       * @private
       */
      _drawPoint() {
        const handler = (options) => {
          // 这个判断需要优化
          if (options.target && options.target.type === 'circle') {
            return
          }
          const position = options.pointer
          const pixelCoord = { x: position.x, y: position.y }
          const graphic = this._getGraphic()
          const geoCoord = this._mapView.pixelCoordToGeoCoord(
            new Point({ coordinates: [pixelCoord.x, pixelCoord.y] })
          )
          graphic.geometry.coordinates = geoCoord.coordinates
          graphic.geometry._pixelCoords = pixelCoord
          this._mapView.graphics.add(graphic)
          // 保存point的点坐标
          this._pointGeomtry = graphic

          this._stopCurrentGraphicDrawing()
        }
        this._mouseEventHandlers = this._mouseEventHandlers
          ? this._mouseEventHandlers
          : []
        this._mouseEventHandlers.push(handler)
        this._mapView.on(ViewEventType.mouseUp, handler)
      }

      _drawLine() {
        let movePosition
        let timer = null
        let isStartDrawing = false
        let isDrawing = false
        /** @type {Feature} */
        let graphic = null
        let pixelCoords = []
        let lineSpots = []

        const handlerUp = (options) => {
          clearTimeout(timer)
          const position = options.pointer

          // 保存编辑的折线点
          const pixelCoord = { x: position.x, y: position.y }
          const geoCoord = this._mapView.pixelCoordToGeoCoord(
            new Point({ coordinates: [pixelCoord.x, pixelCoord.y] })
          )
          if (!graphic) {
            pixelCoords.push(pixelCoord, pixelCoord)
            lineSpots.push(geoCoord.coordinates, geoCoord.coordinates)
            graphic = this._getGraphic()
            graphic.geometry.coordinates = lineSpots
            graphic.geometry._pixelCoords = pixelCoords
            this._mapView.graphics.add(graphic)

            // 保存当前编辑中的geometry
            this._lineGeomtry = graphic
          } else {
            pixelCoords.push(pixelCoord)
            lineSpots.push(geoCoord.coordinates)
            graphic.geometry._pixelCoords = pixelCoords
            graphic.geometry.coordinates = lineSpots
          }

          // 判断是否是双击
          timer = setTimeout(() => {
            isStartDrawing = true
          }, 500)
        }

        const handlerMove = (options) => {
          movePosition = options.pointer
          if (!isStartDrawing) {
            return
          }
          isDrawing = true

          const pixelCoord = { x: movePosition.x, y: movePosition.y }
          pixelCoords[pixelCoords.length - 1] = pixelCoord

          const geoCoord = this._mapView.pixelCoordToGeoCoord(
            new Point({ coordinates: [pixelCoord.x, pixelCoord.y] })
          )
          lineSpots[lineSpots.length - 1] = geoCoord.coordinates

          graphic.geometry._pixelCoords = pixelCoords
          graphic.geometry.coordinates = lineSpots
        }

        const handlerDoubleClick = (options) => {
          clearTimeout(timer)
          // 清除双击时单击事件添加的多余点
          lineSpots.pop()
          pixelCoords.pop()

          lineSpots.pop()
          pixelCoords.pop()
          // 清除最后一个点
          lineSpots.pop()
          pixelCoords.pop()
          graphic.geometry._pixelCoords = pixelCoords
          graphic.geometry.coordinates = lineSpots

          if (!isDrawing) {
            graphic = null
            lineSpots = []
            pixelCoords = []
            return
          }
          const position = options.pointer
          const pixelCoord = { x: position.x, y: position.y }
          const geoCoord = this._mapView.pixelCoordToGeoCoord(
            new Point({ coordinates: [pixelCoord.x, pixelCoord.y] })
          )
          pixelCoords.push(pixelCoord)
          lineSpots.push(geoCoord.coordinates)
          graphic.geometry._pixelCoords = pixelCoords
          graphic.geometry.coordinates = lineSpots

          graphic = null
          lineSpots = []
          pixelCoords = []
          isDrawing = false
          isStartDrawing = false

          this._stopCurrentGraphicDrawing()
        }
        this._mouseEventHandlers = this._mouseEventHandlers
          ? this._mouseEventHandlers
          : []

        this._mouseEventHandlers.push(handlerUp, handlerMove, handlerDoubleClick)
        this._mapView.on(ViewEventType.mouseUp, handlerUp)
        this._mapView.on(ViewEventType.mouseMove, handlerMove)
        this._mapView.on(ViewEventType.doubleClick, handlerDoubleClick)
      }

      _drawPolygon() {
        let movePosition
        let timer = null
        let isStartDrawing = false
        let isDrawing = false
        /** @type {Feature} */
        let graphic = null
        let pixelCoords = []
        let polygonSpots = []

        const handlerUp = (options) => {
          clearTimeout(timer)
          const position = options.pointer
          const pixelCoord = { x: position.x, y: position.y }
          const geoCoord = this._mapView.pixelCoordToGeoCoord(
            new Point({ coordinates: [pixelCoord.x, pixelCoord.y] })
          )

          if (!graphic) {
            pixelCoords.push(pixelCoord, pixelCoord)
            polygonSpots.push(geoCoord.coordinates, geoCoord.coordinates)
            graphic = this._getGraphic()
            graphic.geometry._pixelCoords = [...pixelCoords, pixelCoords[0]]
            graphic.geometry.coordinates = [[...polygonSpots, polygonSpots[0]]]
            this._mapView.graphics.add(graphic)

            // 保存当前编辑中的geometr
            this._polygonGeomtry = graphic
          } else {
            pixelCoords.push(pixelCoord)
            polygonSpots.push(geoCoord.coordinates)
            graphic.geometry._pixelCoords = [...pixelCoords, pixelCoords[0]]
            graphic.geometry.coordinates = [[...polygonSpots, polygonSpots[0]]]
          }

          timer = setTimeout(() => {
            isStartDrawing = true
          }, 500)
        }
        const handlerMove = (options) => {
          if (!isStartDrawing) {
            return
          }
          isDrawing = true
          movePosition = options.pointer

          const pixelCoord = { x: movePosition.x, y: movePosition.y }
          pixelCoords[pixelCoords.length - 1] = pixelCoord
          const geoCoord = this._mapView.pixelCoordToGeoCoord(
            new Point({ coordinates: [pixelCoord.x, pixelCoord.y] })
          )
          polygonSpots[polygonSpots.length - 1] = geoCoord.coordinates

          graphic.geometry._pixelCoords = [...pixelCoords, pixelCoords[0]]
          graphic.geometry.coordinates = [[...polygonSpots, polygonSpots[0]]]
        }
        const handlerDoubleClick = (options) => {
          clearTimeout(timer)

          // 清除双击时单击事件添加的多余点
          polygonSpots.pop()
          pixelCoords.pop()

          polygonSpots.pop()
          pixelCoords.pop()

          // 清除最后一个点
          polygonSpots.pop()
          pixelCoords.pop()
          graphic.geometry._pixelCoords = [...pixelCoords, pixelCoords[0]]
          graphic.geometry.coordinates = [[...polygonSpots, polygonSpots[0]]]

          if (!isDrawing) {
            graphic = null
            polygonSpots = []
            pixelCoords = []
            return
          }
          const position = options.pointer
          const pixelCoord = { x: position.x, y: position.y }
          const geoCoord = this._mapView.pixelCoordToGeoCoord(
            new Point({ coordinates: [pixelCoord.x, pixelCoord.y] })
          )
          pixelCoords.push(pixelCoord)
          polygonSpots.push(geoCoord.coordinates)
          graphic.geometry._pixelCoords = [...pixelCoords, pixelCoords[0]]
          graphic.geometry.coordinates = [[...polygonSpots, polygonSpots[0]]]

          graphic = null
          polygonSpots = []
          pixelCoords = []
          isDrawing = false
          isStartDrawing = false

          this._stopCurrentGraphicDrawing()
        }

        this._mouseEventHandlers = this._mouseEventHandlers
          ? this._mouseEventHandlers
          : []

        this._mouseEventHandlers.push(handlerUp, handlerMove, handlerDoubleClick)
        this._mapView.on(ViewEventType.mouseUp, handlerUp)
        this._mapView.on(ViewEventType.mouseMove, handlerMove)
        this._mapView.on(ViewEventType.doubleClick, handlerDoubleClick)
      }
    }
    export default SketchEditorVideoBase