import Position from '../position/Position'

const { Cesium } = BC.Namespace

class Water {
  constructor(pos, opt) {
    if (!(pos instanceof Position)) {
      console.error('参数缺失，水的起点坐标，请new BC.Position（)')
      pos = new Position()
    }
    var expOpt = {
      image: '/libs/resources/static/water.png',
      startColor: [255, 255, 255, 1],
      endColor: [255, 255, 255, 1],
      startScale: 0.5,
      endScale: 3,
      sizeInMeters: true,
      minimumParticleLife: 1,
      maximumParticleLife: 10,
      speed: 26,
      mass: 1,
      imageSize: [2, 2],
      emissionRate: 200,
      lifetime: 16,
      emitter: 0.1
    }
    this.position = pos
    this.opt = Object.assign(expOpt, opt)
    this.entity = null
    this.posEntity = null
  }

  init() {
    if (!window.viewer) {
      console.error('地球未初始化，水流加载失败')
    }
    try {
      this.posEntity = viewer.entities.add({
        position: Cesium.Cartesian3.fromDegrees(
          this.position.lng,
          this.position.lat,
          this.position.alt
        )
      })
      this.entity = viewer.scene.primitives.add(
        new Cesium.ParticleSystem({
          image: this.opt.image,
          startColor: Cesium.Color.fromBytes(
            this.opt.startColor[0],
            this.opt.startColor[1],
            this.opt.startColor[2],
            this.opt.startColor[3] * 255
          ),
          endColor: Cesium.Color.fromBytes(
            this.opt.endColor[0],
            this.opt.endColor[1],
            this.opt.endColor[2],
            this.opt.endColor[3] * 255
          ),
          startScale: this.opt.startScale,
          endScale: this.opt.endScale,
          sizeInMeters: this.opt.sizeInMeters,
          minimumParticleLife: this.opt.minimumParticleLife,
          maximumParticleLife: this.opt.maximumParticleLife,
          speed: this.opt.speed,
          mass: this.opt.mass,
          imageSize: new Cesium.Cartesian2(
            this.opt.imageSize[0],
            this.opt.imageSize[1]
          ),
          emissionRate: this.opt.emissionRate,
          lifetime: this.opt.lifetime,
          emitter: new Cesium.CircleEmitter(this.opt.emitter),
          emitterModelMatrix: this.computeEmitterModelMatrix(),
          updateCallback: this.applyGravity
        }))
    } catch (e){
      console.log(e)
    }
  }

  computeEmitterModelMatrix() {
    var trs = new Cesium.TranslationRotationScale()
    var hpr = Cesium.HeadingPitchRoll.fromDegrees(
      this.position.heading,
      this.position.pitch,
      this.position.roll,
      new Cesium.HeadingPitchRoll()
    ) // 倾斜角度
    trs.translation = Cesium.Cartesian3.fromElements(
      0,
      0,
      1,
      new Cesium.Cartesian3()
    ) // 发射高度
    trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(
      hpr,
      new Cesium.Quaternion()
    )
    return Cesium.Matrix4.fromTranslationRotationScale(
      trs,
      new Cesium.Matrix4()
    )
  }

  computeModelMatrix(entity, time) {
    return entity.computeModelMatrix(time, new Cesium.Matrix4())
  }

  applyGravity(p, dt) {
    var gravityScratch = new Cesium.Cartesian3()
    var position = p.position
    Cesium.Cartesian3.normalize(position, gravityScratch)
    Cesium.Cartesian3.multiplyByScalar(gravityScratch, -4 * dt, gravityScratch)
    p.velocity = Cesium.Cartesian3.add(p.velocity, gravityScratch, p.velocity)
  }

  update(scene, time) {
    this.entity.modelMatrix = this.computeModelMatrix(this.posEntity, time)
    this.entity.emitterModelMatrix = this.computeEmitterModelMatrix()
  }

  start() {
    if (this.entity) {
      this.entity.show = true
      return
    }
    this.init()
    viewer.scene.preUpdate.addEventListener(this.update.bind(this))
  }

  stop() {
    if (!this.entity) return
    this.entity.show = false
    viewer.scene.preUpdate.removeEventListener(this.update.bind(this))
  }

  uninstall() {
    if (!this.entity) return
    viewer.scene.primitives.remove(this.entity)
    viewer.scene.preUpdate.removeEventListener(this.update.bind(this))
    this.entity = null
  }

  zoomTo() {
    viewer.zoomTo(this.entity)
  }
}

export default Water
