/**
 * @private
 * @author 基础平台-潘卓然ParnDeedlit
 * @description 请仔细对应echart4.0的代码，目前只升级到了echarts-4.4.0版本
 * @example prepareCustoms 这个函数我后来在echarts的bug清单中发现了问题所在，请不要随便改动
 */

export function MapCoordSys(CesiumMap, api) {
  this._CesiumMap = CesiumMap
  this._CesiumScene = CesiumMap.scene
  this.dimensions = ['lng', 'lat']
  this._mapOffset = [0, 0]

  this._api = api
}

MapCoordSys.prototype.dimensions = ['lng', 'lat']

MapCoordSys.prototype.setMapOffset = function (mapOffset) {
  this._mapOffset = mapOffset
}

MapCoordSys.prototype.getBMap = function () {
  return this._CesiumMap
}

/**
 * 对应的地图引擎坐标换算的地方，如果echarts的源码改变了这部分也要一起变化。这里要注意
 * @param {*} data
 */
MapCoordSys.prototype.dataToPoint = function (data) {
  const pointSphere = Cesium.Cartesian3.fromDegrees(data[0], data[1])
  const position = this._CesiumMap.camera.position
  let cameraHeight =
    this._CesiumMap.scene.globe.ellipsoid.cartesianToCartographic(
      position
    ).height
  cameraHeight += this._CesiumMap.scene.globe.ellipsoid.maximumRadius * 1.2
  const distance = Cesium.Cartesian3.distance(position, pointSphere)
  if (distance > cameraHeight) {
    return [-50, -50]
  }
  const mapOffset = this._mapOffset

  const wgs84Position = Cesium.Cartesian3.fromDegrees(data[0], data[1])
  let point = Cesium.SceneTransforms.wgs84ToWindowCoordinates(
    this._CesiumScene,
    wgs84Position
  )
  point = point || { x: 0, y: 0 }
  return [point.x - mapOffset[0], point.y - mapOffset[1]]
}

// 这个函数先不处理，后面我有时间会处理的
MapCoordSys.prototype.pointToData = function (pt) {
  const mapOffset = this._mapOffset
  const position = Cesium.Cartesian3.fromDegrees(
    pt[0] + mapOffset[0],
    pt[1] + mapOffset[1]
  )

  const point = Cesium.SceneTransforms.wgs84ToWindowCoordinates(
    this._CesiumScene,
    position
  )

  return [point.x, point.y]
}

MapCoordSys.prototype.getViewRect = function () {
  const api = this._api
  return new echarts.graphic.BoundingRect(0, 0, api.getWidth(), api.getHeight())
}

MapCoordSys.prototype.getRoamTransform = function () {
  return echarts.matrix.create()
}

MapCoordSys.prototype.prepareCustoms = function () {
  const zrUtil = echarts.util

  const rect = this.getViewRect()
  function dataToCoordSize(dataSize, dataItem) {
    dataItem = dataItem || [0, 0]
    return zrUtil.map(
      [0, 1],
      function (dimIdx) {
        const val = dataItem[dimIdx]
        const halfSize = dataSize[dimIdx] / 2
        const p1 = []
        const p2 = []
        p1[dimIdx] = val - halfSize
        p2[dimIdx] = val + halfSize
        p1[1 - dimIdx] = dataItem[1 - dimIdx]
        p2[1 - dimIdx] = dataItem[1 - dimIdx]
        return Math.abs(
          // eslint-disable-next-line no-invalid-this
          this.dataToPoint(p1)[dimIdx] - this.dataToPoint(p2)[dimIdx]
        )
      },
      // eslint-disable-next-line no-invalid-this
      this
    )
  }
  return {
    coordSys: {
      type: 'cesium',
      x: rect.x,
      y: rect.y,
      width: rect.width,
      height: rect.height
    },
    api: {
      coord: zrUtil.bind(this.dataToPoint, this),
      size: zrUtil.bind(dataToCoordSize, this)
    }
  }
}

MapCoordSys.dimensions = MapCoordSys.prototype.dimensions

MapCoordSys.create = function (ecModel, api) {
  let coordSys

  ecModel.eachComponent('cesium', function (MapModel) {
    const CesiumMap = echarts.cesiumMap
    coordSys = new MapCoordSys(CesiumMap, api)
    coordSys.setMapOffset(MapModel.__mapOffset || [0, 0])
    MapModel.coordinateSystem = coordSys
  })

  ecModel.eachSeries(function (seriesModel) {
    if (seriesModel.get('coordinateSystem') === 'cesium') {
      seriesModel.coordinateSystem = coordSys
    }
  })
}

export default MapCoordSys
