import MapCoordSys from './MapCoordSys'

let echartsIdIndex = 0

/**
 * @author 基础平台/创新中心 潘卓然
 * @class module:客户端可视化.EchartsLayer
 * @classdesc Echarts图表图层
 * @description cesium的echars 4.0的实现。请详细参考echarts源码,CesiumZondy.Overlayer.EchartsLayer
 * @see http://echarts.baidu.com/api.html#echarts
 * @example 这里唯一要注意的是我们中地数码的ceisum的右键事件不是放大缩小而是旋转视角
 * option = {
        title: {
            text: '全国主要城市空气质量 - 百度地图提供数据',
            textStyle: {
                color: '#eee'
            },
            subtext: 'data from PM25.in',
            sublink: 'http://www.pm25.in',
            left: 'center'
        },
        legend: {
            orient: 'vertical',
            y: 'top',
            x: 'left',
            data: ['pm2.5'],
            textStyle: {
                color: '#fff'
            }
        },
        tooltip: {
            trigger: 'item'
        },
        cesium: {
            roam: true
        },
        series: [{
                name: 'pm2.5',
                type: 'scatter',
                coordinateSystem: 'cesium',
                data: convertData(data),
                symbolSize: function (val) {
                    return val[2] / 10;
                },
                showEffectOn: 'render',
                rippleEffect: {
                    brushType: 'stroke'
                },
                hoverAnimation: true,
                label: {
                    normal: {
                        formatter: '{b}',
                        position: 'right',
                        show: false
                    },
                    emphasis: {
                        show: true
                    }
                },
                itemStyle: {
                    normal: {
                        color: '#ddb926'
                    }
                },
                zlevel: 1
            },
            {
                name: 'Top 5',
                type: 'effectScatter',
                coordinateSystem: 'cesium',
                data: convertData(data.sort(function (a, b) {
                    return b.value - a.value;
                }).slice(0, 6)),
                symbolSize: function (val) {
                    return val[2] / 10;
                },
                showEffectOn: 'render',
                rippleEffect: {
                    brushType: 'stroke'
                },
                hoverAnimation: true,
                label: {
                    normal: {
                        formatter: '{b}',
                        position: 'right',
                        show: true
                    }
                },
                itemStyle: {
                    normal: {
                        color: '#f4e925',
                        shadowBlur: 10,
                        shadowColor: '#333'
                    }
                },
                zlevel: 1
            }
        ]
    }
 layer = new CesiumZondy.Overlayer.EchartsLayer(map, option).addTo(map);
 */
export default class EchartsLayer {
  /**
   * @param {Cesium.Viewer} map Cesium.Viewer
   * @param {*} options 百度EchartsOptions https://echarts.apache.org/zh/option.html#title
   * @param {Boolean} [options.postRender=false] 是否实时渲染
   * @param {HTMLElement} [container] 传递给echarts绘制canvas的元素，如不传内部自动建立一个画布元素,外接的方式使用请MapvLayer
   */
  constructor(map, options, container) {
    // 地图对象
    this.map = map
    // 三维对象的场景
    this.scene = map.scene
    // 选项
    this.options = options
    // 初始状态
    this.initStats = false

    // 事件
    this.handler = undefined
    // 移动结束事件
    this.moveEndEvent = undefined
    // 事件发生后
    this.postEvent = undefined
    // 开始事件后
    this.postStartEvent = undefined
    // 结束事件后
    this.postEndEvent = undefined

    // 图层id
    this.layerId = options.layerId || `echarts${echartsIdIndex++}`
    // 图层类
    this.layerClass = options.layerClass || 'echartlayerdefaultclass'

    // 初始化设备像素比率
    this.initDevicePixelRatio()

    // 是否可视
    this.visible = true
    // canvas画布
    this.canvas = this._createCanvas()
    // 渲染时间
    this.postRenderTime = 0
    //
    this.postRenderFrame = options.postRenderFrame || 30

    /*         this.container = map.container;
        this.addInnerContainer(); */
    if (container != undefined) {
      this.container = container
      // 将canvas画布添加到容器内
      container.appendChild(this.canvas)
    } else {
      const parents = document.getElementsByClassName('cesium-widget')
      const parent = parents.length > 0 ? parents[0] : map.container
      this.container = parent
      this.addInnerContainer()
    }

    this.chart = echarts.init(this.canvas)

    // 初始化echarts图层
    this.initEcharts()
    // 调整画布大小
    this._resizeCanvas()

    // 重置图层大小
    this.resize()
    return this
  }

  /// /初始化设备像素比率
  initDevicePixelRatio() {
    this.devicePixelRatio = window.devicePixelRatio || 1
  }

  // 添加内部容器
  addInnerContainer() {
    this.container.appendChild(this.canvas)
  }

  // 初始化echart图层
  initEcharts() {
    echarts.cesiumMap = this.map

    echarts.registerCoordinateSystem('cesium', MapCoordSys)

    echarts.extendComponentModel({
      type: 'cesium',
      getBMap() {
        return this.__cesium
      },
      defaultOption: {
        roam: false
      }
    })

    echarts.registerAction(
      {
        type: 'CesiumRoma',
        event: 'CesiumRoma',
        update: 'updateLayout'
      },
      function (payload, ecModel) {}
    )

    return this
  }

  // 创建canvas画布
  _createCanvas() {
    const canvas = document.createElement('div')
    /*         canvas.setAttribute('id', this.layerId);
        canvas.setAttribute('class', this.layerClass); */
    // canvas.id = this.layerId;
    // canvas类名
    canvas.className = 'cesium-echarts-layer'
    // canvas属性设置
    canvas.setAttribute('class', 'cesium-echarts-layer')
    // canvas的css属性
    canvas.style.position = 'absolute'
    canvas.style.top = '0px'
    canvas.style.left = '0px'

    canvas.style.pointerEvents = 'none' // 屏蔽鼠标事件
    canvas.style.zIndex = this.options.zIndex || 100

    // 获取地图画布的canvas高度和宽度
    const width = `${parseInt(this.map.canvas.width)}px`
    const height = `${parseInt(this.map.canvas.height)}px`

    // 画布的尺寸
    canvas.width = width
    canvas.height = height
    // 浏览器渲染的canvas的尺寸
    canvas.style.width = width
    canvas.style.height = height

    // 这段可以先不不放开
    /* var devicePixelRatio = this.devicePixelRatio;
if (this.mapVOptions.context == '2d') {
    canvas.getContext(this.mapVOptions.context).scale(devicePixelRatio, devicePixelRatio);
} */

    // console.log('_creteWidgetCanvas', this.map.canvas, devicePixelRatio, this);
    return canvas
  }

  // 计算画布大小
  _resizeCanvas() {
    const self = this

    // onresize 事件会在窗口或框架被调整大小时发生
    window.onresize = function () {
      if (this.canvas == undefined || this.canvas == null) return
      const canvas = self.canvas
      const map = self.map

      canvas.style.position = 'absolute'
      canvas.style.top = '0px'
      canvas.style.left = '0px'

      const width = `${parseInt(map.canvas.width)}px`
      const height = `${parseInt(map.canvas.height)}px`

      canvas.width = width
      canvas.height = height
      canvas.style.width = width
      canvas.style.height = height
      // echarts自适应
      self.chart.resize()
    }
  }

  // 控制显示
  _visible() {
    this.visible = true
    this.canvas.style.visibility = 'visible'
  }

  // 控制不显示
  _unvisible() {
    this.visible = false
    this.canvas.style.visibility = 'hidden'
  }

  /**
   * @description 将图层添加到三维球上
   * @function module:客户端可视化.EchartsLayer.prototype.addTo
   * @param {Cesium.Viewer} viewer
   */
  addTo(viewer) {
    this.endStatus = false
    const self = this
    // 扩展 ECharts 组件的视图
    echarts.extendComponentView({
      type: 'cesium',

      render(mapModel, ecModel, api) {
        let rendering = true

        const cesiumMap = echarts.cesiumMap

        // 获取绘图窗口的根元素
        const viewportRoot = api.getZr().painter.getViewportRoot()

        // 获取图层模式，即图层如何排列和布局
        const coordSys = mapModel.coordinateSystem

        // 鼠标移动处理事件
        const moveHandler = function (type, target) {
          if (rendering || !self.map || !self.visible) {
            return
          }
          self._unvisible()
          const offsetEl = self.map.canvas

          const mapOffset = [
            -parseInt(offsetEl.style.left, 10) || 0,
            -parseInt(offsetEl.style.top, 10) || 0
          ]
          viewportRoot.style.left = `${mapOffset[0]}px`
          viewportRoot.style.top = `${mapOffset[1]}px`

          coordSys.setMapOffset(mapOffset)

          mapModel.__mapOffset = mapOffset

          api.dispatchAction({
            type: 'CesiumRoma'
          })
        }

        // 移动结束处理事件
        const moveEndHandler = function (type, target) {
          if (rendering || !self.map) {
            return
          }

          self._visible()
          const offsetEl = self.map.canvas

          const mapOffset = [
            -parseInt(offsetEl.style.left, 10) || 0,
            -parseInt(offsetEl.style.top, 10) || 0
          ]
          viewportRoot.style.left = `${mapOffset[0]}px`
          viewportRoot.style.top = `${mapOffset[1]}px`

          coordSys.setMapOffset(mapOffset)
          mapModel.__mapOffset = mapOffset

          api.dispatchAction({
            type: 'CesiumRoma'
          })
        }

        // 移动结束事件
        self.moveEndEvent = moveEndHandler

        // 缩放结束事件
        function zoomEndHandler() {
          if (rendering) {
            return
          }
          self._visible()
          api.dispatchAction({
            type: 'CesiumRoma'
          })
        }
        //
        const postHandle = function () {
          // self.moveEndEvent();
          zoomEndHandler()
        }
        // 开始后处理
        const postStartHandle = function () {
          if (!this.endStatus) {
            self.scene.postRender.addEventListener(postHandle)
            // self._visible();
          }
        }

        self.postStartEvent = postStartHandle.bind(self)

        // 结束后处理
        const postEndHandle = function () {
          if (!this.endStatus) {
            self.scene.postRender.removeEventListener(postHandle)
            self.resize()
            self._visible()
          }
        }

        self.postEndEvent = postEndHandle.bind(self)

        self.handler = new Cesium.ScreenSpaceEventHandler(self.scene.canvas)

        if (self.initStats == false) {
          self.initStats = true
          if (self.options.postRender) {
            // 相机开始移动时触发开始事件
            self.scene.camera.moveStart.addEventListener(
              self.postStartEvent,
              self
            )
            // 相机移动结束触发结束事件
            self.scene.camera.moveEnd.addEventListener(self.postEndEvent, self)
          } else {
            // self.handler.setInputAction(zoomStartHandler, Cesium.ScreenSpaceEventType.WHEEL);
            //
            self.handler.setInputAction(
              moveHandler,
              Cesium.ScreenSpaceEventType.LEFT_DOWN
            )
            self.handler.setInputAction(
              moveEndHandler,
              Cesium.ScreenSpaceEventType.LEFT_UP
            )
            self.handler.setInputAction(
              moveHandler,
              Cesium.ScreenSpaceEventType.RIGHT_DOWN
            )
            self.handler.setInputAction(
              moveEndHandler,
              Cesium.ScreenSpaceEventType.RIGHT_UP
            )
            self.map.scene.camera.moveEnd.addEventListener(function () {
              // 获取当前相机高度
              self.moveEndEvent()
            })
          }
        }

        this._oldMoveHandler = moveHandler
        this._oldZoomEndHandler = zoomEndHandler

        const roam = mapModel.get('roam')
        if (roam && roam !== 'scale') {
          // todo 允许拖拽
        } else {
          // todo 不允许拖拽
        }
        if (roam && roam !== 'move') {
          // todo 允许移动
        } else {
          // todo 不允许允许移动
        }

        rendering = false
      }
    })

    this.chart.setOption(this.options)
    return this
  }

  /**
   * @description 显示图层
   * @function module:客户端可视化.EchartsLayer.prototype.show
   */
  show() {
    this._visible()
  }

  /**
   * @description 隐藏图层
   * @function module:客户端可视化.EchartsLayer.prototype.hide
   */
  hide() {
    this._unvisible()
  }

  setOpacity(opacity) {
    this.canvas.style.opacity = opacity
  }

  /**
   * 重置图层大小
   * @function module:客户端可视化.EchartsLayer.prototype. resize
   */
  resize() {
    if (this.canvas == undefined || this.canvas == null) return
    const canvas = this.canvas
    canvas.style.position = 'absolute'
    canvas.style.top = '0px'
    canvas.style.left = '0px'
    canvas.width = parseInt(this.map.canvas.width)
    canvas.height = parseInt(this.map.canvas.height)
    canvas.style.width = this.map.canvas.style.width
    canvas.style.height = this.map.canvas.style.height
  }

  /**
   * 删除图层
   * @function module:客户端可视化.EchartsLayer.prototype.remove
   */
  remove() {
    this.endStatus = true
    const self = this
    this.chart.clear()
    if (self.options.postRender) {
      this.scene.camera.moveStart.removeEventListener(this.postStartEvent, this)
      this.scene.camera.moveEnd.removeEventListener(this.postEndEvent, this)
    } else {
      this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOWN)

      this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_UP)
      this.handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_DOWN)
      this.handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_UP)
      this.scene.camera.moveEnd.removeEventListener(function () {
        self.moveEndEvent()
      })
      this.handler.destroy()
    }

    if (this.canvas.parentElement) {
      this.canvas.parentElement.removeChild(this.canvas)
    }
    this.map = undefined

    return this
  }
}

window.EchartsLayer = EchartsLayer
