import {
  GeometryType,
  Log,
  createSimpleMarkerSymbolCanvas,
  SimpleMarkerSymbol
} from '@mapgis/webclient-common'
import { BaseGraphic, getPointPositions } from './index'

const { Cartesian2, Color } = Cesium

/**
 * 三维的几何对象
 * @private
 * @param option - {Object} 构造参数
 * @param {Feature} [option.feature = null] 构造Cesium几何的要素对象
 * */
class SimpleMarkerGraphic extends BaseGraphic {
  constructor(options) {
    super(options)
  }

  /**
   * 重载基类的checkSymbol方法
   * @public
   * @return {Boolean} 是否为支持的符号
   * */
  checkSymbol() {
    if (!(this._feature.symbol instanceof SimpleMarkerSymbol)) {
      Log.info('要素的符号类型不是SimpleMarkerSymbol！')
      return false
    }
    return true
  }

  /**
   * 重载基类的_createPrimitive方法
   * @private
   * @return {Primitive} Cesium的几何对象
   * */
  _createPrimitive() {
    // 不存在style，则不绘制几何
    if (!this._feature.symbol.style) return
    // 获取要素符号
    const _symbol = this._feature.symbol
    switch (_symbol.style) {
      case 'circle':
        this._createPointPrimitive()
        break
      default:
        this._createBillBoardPrimitive()
        break
    }
  }

  /**
   * 重载基类的_getPositions方法
   * @private
   * @return {Array<Cartesian3>} Cesium的点坐标
   * */
  _getPositions() {
    return getPointPositions(this._feature)
  }

  /**
   * 判断新旧两个符号的属性是否相等
   * @private
   * @param {Symbol} symbol1 第一个符号
   * @param {Symbol} symbol2 第二个符号
   * @return {Boolean} 符号是否相等
   * */
  _symbolEquals(symbol1, symbol2) {
    // 符号是否相等
    let _equal = true
    if (
      symbol1.size !== symbol2.size ||
      symbol1.style !== symbol2.style ||
      symbol1.outline.width !== symbol2.outline.width ||
      symbol1.outline.color.red !== symbol2.outline.color.red ||
      symbol1.outline.color.green !== symbol2.outline.color.green ||
      symbol1.outline.color.blue !== symbol2.outline.color.blue ||
      symbol1.outline.color.alpha !== symbol2.outline.color.alpha
    ) {
      _equal = false
    }

    // 新旧符号样式类型发生变化，置空_primitiveCollection
    if (
      (symbol1.style === 'circle' && symbol2.style !== 'circle') ||
      (symbol1.style !== 'circle' && symbol2.style === 'circle')
    ) {
      this._primitiveCollection = undefined
    }
    return _equal
  }

  /**
   * 通过feature创建一个Cesium的BillboardCollection对象
   * @private
   * @return {Object} 创建好的cesium的BillboardCollection对象
   * */
  _createBillBoardPrimitive() {
    // 获取symbol
    const _symbol = this._feature.symbol
    // 没有构造canvas，则构造并保存canvas
    if (!this._canvas) {
      this._canvas = createSimpleMarkerSymbolCanvas(_symbol)
    }
    // canvas已经构造过了
    else {
      // 判断新旧两个symbol是否相等
      const _isSymbolEqual = this._symbolEquals(_symbol, this._symbol)
      // 不相等，则重新构造canvas
      if (!_isSymbolEqual) {
        this._canvas = createSimpleMarkerSymbolCanvas(_symbol)
        this._symbol = _symbol
      }
    }
    // 获取要素几何
    const _geometry = this._feature.geometry
    switch (_geometry.type) {
      case GeometryType.point:
      case GeometryType.polygon:
      case GeometryType.extent:
      case GeometryType.circle:
        const _billboard = this._billboardsCollection.add(
          this._createBillBoardOptions(this._getPositions()[0])
        )
        _billboard.id = this._feature.id
        this._billboards.push(_billboard)
        break
      case GeometryType.multiPoint:
      case GeometryType.multiPolygon:
        const _positions = this._getPositions()
        for (let i = 0; i < _positions.length; i++) {
          const _billboard = this._billboardsCollection.add(
            this._createBillBoardOptions(_positions[i])
          )
          _billboard.id = this._feature.id
          this._billboards.push(_billboard)
        }
        break
      default:
        break
    }
  }

  /**
   * 创建billboard的初始化参数
   * @private
   * @param <Cartesian3> position 点坐标
   * @return {Object} billboard的初始化参数
   * */
  _createBillBoardOptions(position) {
    // 获取symbol
    const _symbol = this._feature.symbol
    return {
      // 几何坐标
      position,
      // billboard的image对象
      image: this._canvas,
      // 设置图层透明度
      color: new Color(1, 1, 1, this._layerOpacity),
      // 图片宽度
      width: _symbol.size,
      // 图片高度
      height: _symbol.size,
      // 图片原点偏移
      pixelOffset: new Cartesian2(_symbol.xoffset, _symbol.yoffset * -1)
    }
  }

  /**
   * 创建并返返回一个Cesium的点的PointPrimitiveCollection对象
   * @private
   * @return {PointPrimitiveCollection} Cesium的PointPrimitiveCollection对象
   * */
  _createPointPrimitive() {
    // 获取要素几何
    const _geometry = this._feature.geometry
    switch (_geometry.type) {
      case GeometryType.point:
      case GeometryType.polygon:
      case GeometryType.extent:
      case GeometryType.circle:
        // 根据几何类型获取点坐标
        const _point = this._pointsCollection.add(
          this._createPointOptions(this._getPositions()[0])
        )
        _point.id = this._feature.id
        this._points.push(_point)
        break
      case GeometryType.multiPoint:
      case GeometryType.multiPolygon:
        const _positions = this._getPositions()
        for (let i = 0; i < _positions.length; i++) {
          const _point = this._pointsCollection.add(
            this._createPointOptions(_positions[i])
          )
          _point.id = this._feature.id
          this._points.push(_point)
        }
        break
      default:
        Log.error('要素的几何类型是不支持的类型！')
        break
    }
  }

  /**
   * 创建point的初始化参数
   * @private
   * @param <Cartesian3> position 点坐标
   * @return {Object} point的初始化参数
   * */
  _createPointOptions(position) {
    // 获取要素符号
    const _symbol = this._feature.symbol
    // 构造点的填充颜色
    const _color = this._getCesiumColor(_symbol.color)
    // 设置图层透明度
    _color.alpha *= this._layerOpacity
    // 构造点的外边线颜色
    const _outLineColor = this._getCesiumColor(_symbol.outline.color)
    // 设置图层透明度
    _outLineColor.alpha *= this._layerOpacity
    return {
      position,
      color: _color,
      outlineColor: _outLineColor,
      outlineWidth: _symbol.outline.width,
      pixelSize: _symbol.size
    }
  }
}

export default SimpleMarkerGraphic
