import {
  Collection,
  defaultValue,
  Feature,
  getGUID,
  SymbolType,
  Log
} from '@mapgis/webclient-common'
import {
  SimpleMarkerGraphic,
  PictureMarkerGraphic,
  SimpleLineGraphic,
  SimpleFillGraphic,
  TextGraphic
} from './index'

const {
  PrimitiveCollection,
  PointPrimitiveCollection,
  BillboardCollection,
  LabelCollection
} = Cesium

/**
 * 插件层中添加cesium几何的图层
 * @private
 * */
class CesiumInnerGraphicsLayer {
  constructor(options) {
    options = defaultValue(options, {})
    // 图层id
    this.id = defaultValue(options.id, getGUID())
    // 图层透明度
    this.opacity = defaultValue(options.opacity, 1)
    // graphic对象的管理容器
    this._graphicsCollection = new Collection()
    // primitive对象的管理容器
    this._primitivesCollection = new PrimitiveCollection()
    // point对象的管理容器
    this._pointsCollection = new PointPrimitiveCollection()
    this._billboardsCollection = new BillboardCollection()
    this._labelsCollection = new LabelCollection()
    // Cesium的viewer对象
    this._viewer = options.viewer
    // 添加PrimitiveCollection到cesium中，这相当于一个图层
    this._viewer.scene.primitives.add(this._primitivesCollection)
    this._viewer.scene.primitives.add(this._pointsCollection)
    this._viewer.scene.primitives.add(this._billboardsCollection)
    this._viewer.scene.primitives.add(this._labelsCollection)
  }

  /**
   * 根据Feature添加Cesium的几何对象
   * @public
   * @param {Feature} feature 要添加的要素对象
   * */
  add(feature) {
    const _feature = Feature.fromJSON(feature)
    // 获取要素符号
    const _symbol = _feature.symbol
    // 生成graphic对象
    let _graphic
    switch (_symbol.type) {
      case SymbolType.simpleMarker:
        _graphic = new SimpleMarkerGraphic({
          feature: _feature,
          layerOpacity: this.opacity,
          pointsCollection: this._pointsCollection,
          billboardsCollection: this._billboardsCollection
        })
        break
      case SymbolType.pictureMarker:
        _graphic = new PictureMarkerGraphic({
          feature: _feature,
          layerOpacity: this.opacity,
          billboardsCollection: this._billboardsCollection
        })
        break
      case SymbolType.text:
        _graphic = new TextGraphic({
          feature: _feature,
          layerOpacity: this.opacity,
          labelsCollection: this._labelsCollection
        })
        break
      case SymbolType.simpleLine:
        _graphic = new SimpleLineGraphic({
          feature: _feature,
          layerOpacity: this.opacity,
          primitivesCollection: this._primitivesCollection
        })
        break
      case SymbolType.simpleFill:
        _graphic = new SimpleFillGraphic({
          feature: _feature,
          layerOpacity: this.opacity,
          primitivesCollection: this._primitivesCollection
        })
        break
      default:
        Log.error('要素的符号暂时不支持！')
        break
    }
    // 添加到图层几何管理容器中
    if (_graphic) {
      this._graphicsCollection.add(_graphic)
    }
  }

  /**
   * 根据要素id删除cesium的几何对象
   * @public
   * @param {String} id 要删除的要素id
   * */
  removeByID(id) {
    const _graphic = this._findGraphicById(id)
    this._graphicsCollection.remove(_graphic)
    _graphic.destroy()
  }

  /**
   * 通过Feature更新三维几何
   * @public
   * @param {Feature} feature 要更新的要素对象
   * */
  update(feature) {
    const _feature = feature.toJSON()
    const _graphic = this._findGraphicById(feature.id)
    _graphic.update(_feature)
  }

  /**
   * 根据要素id查找Graphic对象
   * @public
   * @param {String} id 要查找的要素id
   * @return {BaseGraphic} Graphic对象
   * */
  findByID(id) {
    return this._findGraphicById(id)
  }

  /**
   * 获取所有的Graphic对象
   * @public
   * @return {Collection} 所有的Graphic对象
   * */
  getAll() {
    return this._graphicsCollection
  }

  /**
   * 根据要素删除Graphic对象
   * @public
   * @param {Feature} feature 要删除的要素对象
   * */
  remove(feature) {
    this.removeByID(feature.id)
  }

  /**
   * 删除该图层下所有的cesium的几何对象
   * @public
   * */
  removeAll() {
    this._graphicsCollection.forEach(function (graphic) {
      graphic.destroy()
    })
    this._graphicsCollection.items = []
  }

  /**
   * 销毁图层
   * @public
   * */
  destroy() {
    this.id = undefined
    this.opacity = undefined
    this._graphicsCollection = undefined
    this._primitivesCollection.destroy()
    this._primitivesCollection = undefined
    this._pointsCollection.destroy()
    this._pointsCollection = undefined
    this._billboardsCollection.destroy()
    this._billboardsCollection = undefined
    this._labelsCollection.destroy()
    this._labelsCollection = undefined
    this._viewer = undefined
  }

  /**
   * 显隐图层
   * @public
   * @param {Boolean} visible 是否显示图层
   * */
  setVisible(visible) {
    this._graphicsCollection.forEach(function (graphic) {
      graphic.setVisible(visible)
    })
  }

  /**
   * 设置图层透明度
   * @public
   * @param {Number} opacity 图层透明度
   * */
  setOpacity(opacity) {
    let _opacity = opacity
    if (_opacity < 0) _opacity = 0
    if (_opacity > 1) _opacity = 1
    this.opacity = _opacity
    this._graphicsCollection.forEach(function (graphic) {
      graphic._layerOpacity = _opacity
      graphic.update(graphic._feature)
    })
  }

  /**
   * 根据要素id查找Graphic对象
   * @private
   * @param {String} id 要查找的要素id
   * @return {BaseGraphic} Graphic对象
   * */
  _findGraphicById(id) {
    let _primitive = undefined
    this._graphicsCollection.forEach(function (primitive) {
      if (primitive.id === id) {
        _primitive = primitive
      }
    })
    return _primitive
  }
}

export default CesiumInnerGraphicsLayer
