import { Feature, ViewEventType } from '../../base'
import { Point, Extent } from '../../base/geometry'
import { defaultValue } from '../../util'
import SketchStage from './SketchStage'
import SketchBaseDrawTool from './SketchBaseDrawTool'
import SketchPointDrawTool from './SketchPointDrawTool'
import SketchPolygonDrawTool from './SketchPolygonDrawTool'
import SketchStyle from './SketchStyle'
/**
 * 面绘图工具类
 * @class SketchExtentDrawTool
 * @moduleEX SketchEditorModule
 * @extends SketchBaseDrawTool
 * @param {Object} options 构造参数
 * @param {MapView}  [options.mapView]  地图视图对象
 * @param {GraphicsLayer}  [options.layer]  草图图层管对象
 * @param {SketchStyle}  [options.sketchStyle]  草图符号
 */
class SketchExtentDrawTool extends SketchBaseDrawTool {
  constructor(options) {
    super(options)
    /**
     * 地图视图
     * @member {MapView|SecenView} SketchEditor.prototype._mapView
     */
    this._mapView = options.mapView
    /**
     * 草图图层
     * @member {GraphicsLayer} SketchEditor.prototype._layer
     */
    this._layer = defaultValue(options.layer, undefined)
    /**
     * 草图绘图形集合
     * @member {SketchStage} SketchEditor.prototype._sketchStage
     */
    this._sketchStage = new SketchStage()
    /**
     * 草图符号
     * @member {SketchStyle} SketchEditor.prototype._sketchStyle
     */
    this._sketchStyle = defaultValue(options.sketchStyle, new SketchStyle())
    // this._mouseEventHandlers = null
    this._currentVertexIndexOnMultiPoint = null
    /**
     * 草图编辑状态
     * 0:没有画图或编辑状态
     * 1:图形编辑
     * 2:节点编辑
     * 3:画图中
     * @member {MapView|SecenView} SketchEditor.prototype._editMode
     */
    this._editMode = 0
    /**
     * 草图捕获配置项
     * @member {Object} SketchEditor.prototype.snappingOption
     * @param {Object} [snappingOption.showSelectBox = {}] 捕捉时是否展示选中编辑框
     * @param {Object} [snappingOption.showSelectVertex = {}] 捕捉时是否展示顶点可编辑图形
     * @param {Object} [snappingOption._hitTestMode = {}] 捕捉拾取方式,0:click鼠标拾取。1:pointerDown鼠标按下拾取
     */
    const snappingOption = {
      showSelectBox: true,
      showSelectVertex: false,
      canEditFeature: false,
      canEditVertex: false,
      _hitTestMode: 0
    }
    this.snappingOption = defaultValue(options.snappingOption, snappingOption)
    /**
     * 所属父级绘图工具
     * @member {GraphicsLayer} SketchEditor.prototype._layer
     */
    this._parent = defaultValue(options._parent, undefined)
    // 所属sketchEditor对象
    this._sketchEditor = defaultValue(options._sketchEditor, undefined)
    // this.sketchSnappingTool = new SketchSnappingTool(this.snappingOption)
    // 初始化事件
    this._initEvent()
    this.undoRedoManager = defaultValue(options.undoRedoManager, undefined)
    this._drawTools = [this]
    this._otherDrawTools = []
  }
  /**
   * @description 初始化事件
   * @private
   */
  _initEvent() {
    this._processEvent = this._processEvent.bind(this)
    this.on('pan', this._processEvent)
    this.on('vertexScale', this._processEvent)
    this.on('midVertexScale', this._processEvent)
    this.on('vertexMove', this._processEvent)
    this.on('midVertexAdd', this._processEvent)
  }
  /**
   * @description 鼠标绘制图形:鼠标单击绘制区的一个顶点;鼠标移动,区图形随鼠标位置变动;鼠标双击,完成区图形绘制。
   */
  drawFeature() {
    // 屏蔽地图默认拖拽事件
    this._mapView._mapActionControl('drag-pan', false)
    // 控制鼠标移动事件频率
    const timer = null
    /// /////////////////////////
    // 当前正在绘制的图形对象
    let feature = null
    let originCoord = null
    // 处理鼠标点击事件。点击后渲染端点图形,渲染区图形
    const handlerDrag = (options) => {
      clearTimeout(timer)
      if (options.button === 0) {
        if (options.action === 'start') {
          originCoord = originCoord || this._mapView.toMap(options.origin)
        } else if (options.action === 'update') {
          const curCoord = this._mapView.toMap({ x: options.x, y: options.y })
          const xmin = Math.min(
            originCoord.coordinates[0],
            curCoord.coordinates[0]
          )
          const ymin = Math.min(
            originCoord.coordinates[1],
            curCoord.coordinates[1]
          )
          const xmax = Math.max(
            originCoord.coordinates[0],
            curCoord.coordinates[0]
          )
          const ymax = Math.max(
            originCoord.coordinates[1],
            curCoord.coordinates[1]
          )
          if (!feature) {
            feature = this._getFeature(xmin, ymin, xmax, ymax)
            this._addFeaturesToMap(feature)
            this._sketchStage.entityGraphic = feature
          } else {
            feature.geometry.xmin = xmin
            feature.geometry.ymin = ymin
            feature.geometry.xmax = xmax
            feature.geometry.ymax = ymax
          }
        } else if (options.action === 'end') {
          // 停止绘制
          this.stop()
          // 清除捕获效果
          if (this._sketchStage.snapGraphics.length > 0) {
            this._sketchStage.snapGraphics.forEach((feature) => {
              this._removeFeatureFromMap(feature)
            })
            this._sketchStage.snapGraphics = []
          }
          this._editMode = 0
          // 发送绘制完成事件
          this.fire('drawn', { geometry: feature.geometry }, self)
          // 恢复地图默认拖拽事件
          this._mapView._mapActionControl('drag-pan', true)
        }
      }
    }
    this._mouseEventHandlers = this._mouseEventHandlers
      ? this._mouseEventHandlers
      : []
    // 移除绘制事件
    this._mouseEventHandlers.push(handlerDrag)
    this._mapView.on(ViewEventType.drag, handlerDrag)
  }
  /**
   * @description 添加图形
   * @param {Array} points 生成面的点地理坐标集
   * @param {SketchStyle} sketchStyle 面的符号样式
   */
  addFeature(points, sketchStyle, attributes) {
    let lineStyle = null
    if (!sketchStyle || !sketchStyle.lineStyle) {
      lineStyle = this._sketchStyle.lineStyle
    } else {
      lineStyle = sketchStyle.lineStyle
    }
    const feature = this._getFeature(points, lineStyle)
    if (attributes) {
      feature.attributes = attributes
    }
    this._sketchStage.entityGraphic = feature
    // 更新图层图形
    this._addFeaturesToMap(feature)
  }
  addFeatureByGeometry(geometry, sketchStyle, attributes) {
    let symbol = null
    if (!sketchStyle || !sketchStyle.lineStyle) {
      symbol = this._sketchStyle.lineStyle
    } else {
      symbol = sketchStyle.lineStyle
    }
    const feature = new Feature({
      geometry,
      symbol
    })
    if (attributes) {
      feature.attributes = attributes
    }
    this._sketchStage.entityGraphic = feature
    // 更新图层图形
    this._addFeaturesToMap(feature)
  }
  /**
   * @description 获取feature实例
   * @private
   * @param {Point} point 生成面的点地理坐标集
   * @param {Symbol} symbol 点的符号样式
   */
  _getFeature(xmin, ymin, xmax, ymax) {
    xmin = xmin !== undefined ? xmin : 0
    ymin = ymin !== undefined ? ymin : 0
    xmax = xmax !== undefined ? xmax : 0
    ymax = ymax !== undefined ? ymax : 0
    const geometry = new Extent({
      xmin,
      ymin,
      xmax,
      ymax,
      spatialReference: this._spatialReference
    })
    const symbol = this._sketchStyle.fillStyle
    const circleGeometry = new Feature({
      geometry,
      symbol
    })
    return circleGeometry
  }
  /**
   * @description 捕获草图
   * @private
   * @param {Feature} feature 被选中feature对象
   */
  _hitTestFeature(feature, event) {
    if (!this._parent && this.snappingOption.showSelectBox) {
      if (this._editMode === 0) {
        this._editMode = 1
      } else if (this._editMode === 2) {
        // 临时,把clickMap的事件删掉,否则在图形都被删掉时会被触发
        this._mapView.off(ViewEventType.immediateClick, this._mapClickEvent)
        this._mapClickEvent = null
        this._editMode = 1
      }
      // 进入图形编辑状态,高亮点元素,用新图形代替高亮,展示选中图形时的辅助图形
      this.selectFeature(feature)
    }
  }
  /**
   * @description 选中草图feature
   * @param {Feature} feature 被选中草图feature对象
   */
  selectFeature(feature) {
    if (!this.snappingOption.showSelectBox) return
    // 1.删除当前编辑图形状态的辅助图形
    // 2.添加顶点编辑状态的辅助图形
    this._clearEditGraphics(2)
    // 加载选时的辅助图形,外包盒
    const extent = feature.geometry
    const polygonDrawTool = new SketchPolygonDrawTool({
      mapView: this._mapView,
      layer: this._layer,
      sketchStyle: new SketchStyle({
        fillStyle: this._sketchStyle._selectBoxStyle,
        isShowSegmentLength: true,
        isShowArea: true
      }),
      snappingOption: {
        showSelectBox: false,
        _hitTestMode: 1
      },
      _parent: this // 或者只传父级相应pan的事件
    })
    // 注册hitTest事件移动图形
    this._drawTools.push(polygonDrawTool)
    polygonDrawTool.addFeature([
      [extent.xmax, extent.ymax],
      [extent.xmax, extent.ymin],
      [extent.xmin, extent.ymin],
      [extent.xmin, extent.ymax],
      [extent.xmax, extent.ymax]
    ])
    this._sketchStage.selectBoxGraphics = [
      polygonDrawTool._sketchStage.entityGraphic
    ]
    // 外包盒顶点和终点
    let boxVertexPoints = []
    boxVertexPoints = [
      {
        point: new Point({
          coordinates: [extent.xmax, extent.ymax],
          spatialReference: this._spatialReference
        }),
        direction: 'ne'
      },
      {
        point: new Point({
          coordinates: [extent.xmax, extent.ymin],
          spatialReference: this._spatialReference
        }),
        direction: 'se'
      },
      {
        point: new Point({
          coordinates: [extent.xmin, extent.ymin],
          spatialReference: this._spatialReference
        }),
        direction: 'sw'
      },
      {
        point: new Point({
          coordinates: [extent.xmin, extent.ymax],
          spatialReference: this._spatialReference
        }),
        direction: 'nw'
      }
    ]
    if (this._sketchEditor && this._sketchEditor.getCenterCoordinate) {
      const midVertexPoints = [
        // midPoint
        {
          point: new Point({
            coordinates: this._sketchEditor.getCenterCoordinate(
              [extent.xmax, extent.ymax],
              [extent.xmax, extent.ymin]
            ),
            spatialReference: this._spatialReference
          }),
          direction: 'e',
          type: 'midVertex'
        },
        {
          point: new Point({
            coordinates: this._sketchEditor.getCenterCoordinate(
              [extent.xmax, extent.ymin],
              [extent.xmin, extent.ymin]
            ),
            spatialReference: this._spatialReference
          }),
          direction: 's',
          type: 'midVertex'
        },
        {
          point: new Point({
            coordinates: this._sketchEditor.getCenterCoordinate(
              [extent.xmin, extent.ymin],
              [extent.xmin, extent.ymax]
            ),
            spatialReference: this._spatialReference
          }),
          direction: 'w',
          type: 'midVertex'
        },
        {
          point: new Point({
            coordinates: this._sketchEditor.getCenterCoordinate(
              [extent.xmin, extent.ymax],
              [extent.xmax, extent.ymax]
            ),
            spatialReference: this._spatialReference
          }),
          direction: 'n',
          type: 'midVertex'
        }
      ]
      boxVertexPoints = boxVertexPoints.concat(midVertexPoints)
    }
    const pointDrawTools = []
    const boxVertexGraphics = []
    boxVertexPoints.forEach((item) => {
      const pointDrawTool = new SketchPointDrawTool({
        mapView: this._mapView,
        layer: this._layer,
        sketchStyle: new SketchStyle({
          vertexStyle: this._sketchStyle._selectBoxVertexStyle
        }),
        snappingOption: {
          showSelectBox: false,
          _hitTestMode: 1
        },
        _parent: this // 或者只传父级相应pan的事件
      })
      // 注册hitTest事件移动图形
      // this._hitTestDrawToolStack.push(pointDrawTool)
      this._drawTools.push(pointDrawTool)
      pointDrawTool.addFeature(item.point, this._sketchStage, {
        direction: item.direction,
        type: item.type
      })
      pointDrawTools.push(pointDrawTool)
      boxVertexGraphics.push(pointDrawTool._sketchStage.entityGraphic)
    })
    this._sketchStage.selectBoxVertexGraphics = boxVertexGraphics
    if (this._otherDrawTools) {
      this._otherDrawTools.push(polygonDrawTool)
    } else {
      this._otherDrawTools = [polygonDrawTool]
    }
    this._otherDrawTools = this._otherDrawTools.concat(pointDrawTools)
    // 添加到undoRedoManager中
    if (this.undoRedoManager) {
      this.undoRedoManager.addProcess('add', this._sketchStage)
    }
    // 点击到地图没有feature图形区域,退出编辑
    if (
      !this._mapClickEvent &&
      (!this._parent || (this._parent && !this._parent._mapClickEvent))
    ) {
      this._mapClickEvent = () => {
        const removedFeatures = this._sketchStage.selectBoxGraphics
          .concat(this._sketchStage.selectBoxVertexGraphics)
          .concat(this._sketchStage.vertexGraphics)
          .concat(this._sketchStage.midVertexGraphics)
        removedFeatures.forEach((feature) => {
          this._removeFeatureFromMap(feature)
        })
        this._mapView.off(ViewEventType.immediateClick, this._mapClickEvent)
        this._mapView._mapActionControl('drag-pan', true)
        this._mapClickEvent = null
        // 发送草图没有被选中状态
        this.fire('selected', { isSelected: false }, self)
        this._sketchStage.selectBoxGraphics = []
        this._sketchStage.selectBoxVertexGraphics = []
        this._sketchStage.vertexGraphics = []
        this._sketchStage.midVertexGraphics = []
      }
      setTimeout(() => {
        this._hitTestEventHandlers.push(this._mapClickEvent)
        this._mapView.on(ViewEventType.immediateClick, this._mapClickEvent)
      }, 200)
    }
  }
  /**
   * @description 响应图形平移事件
   * @private
   * @param {Object} event 拾取事件参数
   */
  _processEvent(event) {
    if (event.type === 'pan') {
      // 处理平移逻辑
      this._handlerPanEvent(event)
    } else if (event.type === 'vertexScale') {
      // 处理顶点缩放逻辑
      this._handlerVertexScaleEvent(event)
    } else if (event.type === 'midVertexScale') {
      // 处理中点缩放逻辑
      this._handlerMidVertexScaleEvent(event)
    }
  }
  /**
   * @description 响应平移事件
   * @private
   * @param {Object} event 拾取事件参数
   */
  _handlerPanEvent(event) {
    // 更新当前草图的图形位置
    const extent = this._sketchStage.entityGraphic.geometry
    extent.xmin += event.deltaPosition.x
    extent.ymin += event.deltaPosition.y
    extent.xmax += event.deltaPosition.x
    extent.ymax += event.deltaPosition.y
    // 更新同级的辅助草图的图形位置
    if (this._otherDrawTools) {
      this._otherDrawTools.forEach((drawTool) => {
        drawTool._processEvent(event)
      })
    }
  }
  /**
   * @description 响应顶点缩放事件
   * @private
   * @param {Object} event 传入事件参数
   */
  _handlerVertexScaleEvent(event) {
    if (event.action === 'scale') {
      const geometry = this._sketchStage.entityGraphic.geometry
      // 更新当前草图的图形位置
      if (!this._sketchStage.entityGraphic.attributes.lastCoordinates) {
        const oriCoordinates = [
          [geometry.xmin, geometry.ymin],
          [geometry.xmax, geometry.ymax]
        ]
        this._sketchStage.entityGraphic.attributes.lastCoordinates =
          oriCoordinates
      }
      this._sketchStage.entityGraphic.attributes = this._sketchStage
        .entityGraphic.attributes
        ? this._sketchStage.entityGraphic.attributes
        : {}
      const newCoordinates = this.getScaleCoordinates(
        [
          [geometry.xmin, geometry.ymin],
          [geometry.xmax, geometry.ymax]
        ],
        event.direction,
        event.extent,
        event.startPoint,
        event.movePoint,
        this._sketchStage.entityGraphic.attributes.lastCoordinates
      )
      geometry.xmin = newCoordinates[0][0]
      geometry.ymin = newCoordinates[0][1]
      geometry.xmax = newCoordinates[1][0]
      geometry.ymax = newCoordinates[1][1]
      // 更新同级的辅助草图的图形位置
      if (this._otherDrawTools) {
        this._otherDrawTools.forEach((drawTool) => {
          // 传给子草图的extent应该是草图改变前的,不是草图改变后的extent
          // event.extent = extent
          drawTool._processEvent(event)
        })
      }
    } else if (event.action === 'stop') {
      if (this._sketchStage.entityGraphic.attributes.lastCoordinates) {
        this._sketchStage.entityGraphic.attributes.lastCoordinates = undefined
      }
      if (this._otherDrawTools) {
        this._otherDrawTools.forEach((drawTool) => {
          // if (drawTool._sketchStage.entityGraphic.id !== event.feature.id) {
          drawTool._processEvent(event)
          // }
        })
      }
    }
  }
  /**
   * @description 响应中点缩放事件
   * @private
   * @param {Object} event 传入事件参数
   */
  _handlerMidVertexScaleEvent(event) {
    if (event.action === 'scale') {
      // 更新当前草图的图形位置
      const geometry = this._sketchStage.entityGraphic.geometry
      if (!this._sketchStage.entityGraphic.attributes.lastCoordinates) {
        const oriCoordinates = [
          [geometry.xmin, geometry.ymin],
          [geometry.xmax, geometry.ymax]
        ]
        this._sketchStage.entityGraphic.attributes.lastCoordinates =
          oriCoordinates
      }
      const newCoordinates = this.getMidScaleCoordinates(
        [
          [geometry.xmin, geometry.ymin],
          [geometry.xmax, geometry.ymax]
        ],
        event.direction,
        event.extent,
        event.startPoint,
        event.movePoint,
        this._sketchStage.entityGraphic.attributes.lastCoordinates
      )
      geometry.xmin = newCoordinates[0][0]
      geometry.ymin = newCoordinates[0][1]
      geometry.xmax = newCoordinates[1][0]
      geometry.ymax = newCoordinates[1][1]
      // 更新同级的辅助草图的图形位置
      if (this._otherDrawTools) {
        this._otherDrawTools.forEach((drawTool) => {
          // 传给子草图的extent应该是草图改变前的,不是草图改变后的extent
          // event.extent = extent
          drawTool._processEvent(event)
        })
      }
    } else if (event.action === 'stop') {
      if (this._sketchStage.entityGraphic.attributes.lastCoordinates) {
        this._sketchStage.entityGraphic.attributes.lastCoordinates = undefined
      }
      if (this._otherDrawTools) {
        this._otherDrawTools.forEach((drawTool) => {
          // if (drawTool._sketchStage.entityGraphic.id !== event.feature.id) {
          drawTool._processEvent(event)
          // }
        })
      }
    }
  }
  /**
   * 图形捕获,捕获重合点、点在线上、平行线、垂直线
   * @private
   */
  getSnapGraphics() {}
  /**
   * @description 选中图形顶点
   * @private
   */
  selectVertex() {}
}
export default SketchExtentDrawTool