import useMapStore from '@/store/modules/maps';
export default class Roaming {
  /**
    *Creates an instance of Roaming.
    * @param * viewer 需要传入
    * @param * options.modeluri 模型的uri 需要传入
    * @param * options.time 漫游时间  需要传入
    * @param * options.start 开始节点 不需要传入
    * @param * options.stop  结束节点 不需要传入
    * @param * options.Lines  点集合 需要传入
    * @param * options.isPathShow 路径是否显示 需要传入
    * @memberof Roaming
  */
  constructor(viewer, options) {
    this.viewer = viewer
    this.entity = undefined
    this.id = options.id ? options.id : new Date()
    this.url = options.modeluri
    this.time = options.time
    this.start = undefined
    this.stop = undefined
    this.Lines = options.Lines
    this.isPathShow = options.isPathShow
    this.property = this.ComputeRoamingLineProperty(options.Lines, options.time, options.start)
    this.InitRoaming(this.property, this.start, this.stop, this.isPathShow)
  }
  /**
   *
   *
   * @param * Lines 点集合
   * @param * time 漫游时间
   * @param * start 开始时间节点
   * @returns
   * @memberof Roaming
  */
  ComputeRoamingLineProperty(Lines, time) {
    let Cesium = useMapStore().$state.cesium;
    let property = new Cesium.SampledPositionProperty()
    let lineLength = Lines.length
    let tempTime = time - time % lineLength
    // let increment = tempTime / lineLength
    let start = Cesium.JulianDate.now()
    this.start = start
    let stop = Cesium.JulianDate.addSeconds(start, tempTime, new Cesium.JulianDate())
    this.stop = stop
    this.viewer.clock.startTime = start.clone()
    this.viewer.clock.stopTime = stop.clone()
    this.viewer.clock.currentTime = start.clone()
    this.viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP // Loop at the end
    // this.viewer.clock.multiplier = 10    
    let totalDistance = 0;
    for (let i = 0; i < lineLength; i++) {
      if (i > 0)
        totalDistance = totalDistance + this.calculateDistance(Lines[i - 1], Lines[i]);
    }
    let speed = totalDistance / time
    for (let i = 0; i < lineLength; i++) {
      let increment = 0;
      if (i > 0)
        increment = this.calculateDistance(Lines[i - 1], Lines[i]) / speed;
      let time = Cesium.JulianDate.addSeconds(start, increment, new Cesium.JulianDate())
      start = time;
      let position = Lines[i]
      property.addSample(time, position)
    }
    return property
  }
  /**
   *
   *
   * @param * position computeRoamingLineProperty计算的属性
   * @param * start 开始时间节点
   * @param * stop 结束时间节点
   * @param * isPathShow path路径是否显示
   * @memberof Roaming
  */
  InitRoaming(position, start, stop, isPathShow) {
    let Cesium = useMapStore().$state.cesium;
    this.entity = this.viewer.entities.add(
      {
        availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval(
          {
            start: start,
            stop: stop
          }
        )]),
        // 位置
        position: position,
        // 计算朝向
        orientation: new Cesium.VelocityOrientationProperty(position),
        // 加载模型
        model: {
          // 模型路径
          uri: this.url,
          // 模型最小刻度
          minimumPixelSize: 64,
          maximumSize: 128,
          // 设置模型最大放大大小
          maximumScale: 200,
          // 模型是否可见
          show: false,
          // 模型轮廓颜色
          silhouetteColor: Cesium.Color.WHITE,
          // 模型颜色  ，这里可以设置颜色的变化
          // color: color,
          // 仅用于调试，显示魔仙绘制时的线框
          debugWireframe: false,
          // 仅用于调试。显示模型绘制时的边界球。
          debugShowBoundingVolume: false,
          scale: 0.3,
          heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
          runAnimations: true // 是否运行模型中的动画效果
        },
        path: {
          resolution: 1,
          material: new Cesium.PolylineGlowMaterialProperty(
            {
              // glowPower: 0.1,
              color: Cesium.Color.YELLOW,
            }
          ),
          width: 10,
          show: isPathShow
        },
        polyline: {
          positions: this.Lines,
          width: 5.0,
          material: new Cesium.PolylineGlowMaterialProperty({
            color: Cesium.Color.YELLOW,
          }),
          depthFailMaterial: new Cesium.PolylineGlowMaterialProperty({
            color: Cesium.Color.YELLOW,
          }),
          show: isPathShow,
          clampToGround: true //贴地
        }
      }
    )
    this.entity.position.setInterpolationOptions({// 点插值
      interpolationDegree: 0,
      interpolationAlgorithm: Cesium.LagrangePolynomialApproximation
    })
    // this.addSceneEvent((time) => {
    //   this.getRoamingPosition(time);
    // });
  }
  /**
   * 监听场景渲染事件
   * @param callback
  */
  addSceneEvent(callback) {
    // addEventListener() → Event.RemoveCallback
    // 监听之前先销毁
    if (this.handler instanceof Function) {
      this.handler();
      this.handler = null;
    }
    this.handler = this.viewer.scene.preRender.addEventListener((scene, time) => {
      callback(time);
    });
  }
  /**
   * 根据时刻获取漫游位置
   * @param {object} time
   * @memberof Roaming
  */
  getRoamingPosition(time, height) {
    if (this.entity) {
      const position = this.entity.position.getValue(time);
      if (height == 0)
        this.setCameraPosition(position, this.view || {});
      else
        this.setCameraPosition(position, this.view || { alt: height });
    }
  }
  /**
   * 设置相机位置
   * @param {cartesian3} position
   * @param {object} options
   * @memberof Roaming
 */
  setCameraPosition(position, options) {
    if (position) {
      // 最新传进来的坐标（后一个位置）
      this.position2 = this.cartesian3ToWGS84(position);
      let heading = 0;
      // 前一个位置点位
      if (this.position1) {
        // 计算前一个点位与第二个点位的偏航角
        heading = this.bearing(this.position1.latitude, this.position1.longitude,
          this.position2.latitude, this.position2.longitude);
      }
      this.position1 = this.cartesian3ToWGS84(position);
      if (position) {
        const dynamicHeading = Cesium.Math.toRadians(heading);
        const pitch = Cesium.Math.toRadians(options.pitch || -8.0);
        const range = options.range || 40.0;
        if (options.alt) {
          var ellipsoid = this.viewer.scene.globe.ellipsoid;
          var cartographic = Cesium.Cartographic.fromDegrees(this.cartesian3ToWGS84(position).longitude, this.cartesian3ToWGS84(position).latitude, options.alt);
          var destination = ellipsoid.cartographicToCartesian(cartographic);
          this.viewer.camera.lookAt(destination, new Cesium.HeadingPitchRange(dynamicHeading, pitch, range));
        }
        else
          this.viewer.camera.lookAt(position, new Cesium.HeadingPitchRange(dynamicHeading, pitch, range));
      }
    }
  }
  /**
   * @name bearing 计算两点的角度 heading
   * @param startLat 初始点的latitude
   * @param startLng 初始点的longitude
   * @param destLat 第二个点的latitude
   * @param destLng 第二个点的latitude
   * @return {number} heading值
 */
  bearing(startLat, startLng, destLat, destLng) {
    startLat = Cesium.Math.toRadians(startLat);
    startLng = Cesium.Math.toRadians(startLng);
    destLat = Cesium.Math.toRadians(destLat);
    destLng = Cesium.Math.toRadians(destLng);
    const y = Math.sin(destLng - startLng) * Math.cos(destLat);
    const x = Math.cos(startLat) * Math.sin(destLat) - Math.sin(startLat) * Math.cos(destLat) * Math.cos(destLng - startLng);
    const brng = Math.atan2(y, x);
    const brngDgr = Cesium.Math.toDegrees(brng);
    return (brngDgr + 360) % 360;
  }
  /**
   * cartographic 转Degrees下地理坐标
   * @param point radius下的WGS84坐标
   * @return degrees下的WGS84坐标
  */
  cartesian3ToWGS84(point) {
    const cartographic = Cesium.Cartographic.fromCartesian(point);
    const lat = Cesium.Math.toDegrees(cartographic.latitude);
    const lng = Cesium.Math.toDegrees(cartographic.longitude);
    const alt = cartographic.height;
    return {
      longitude: lng,
      latitude: lat,
      height: alt,
    };
  }
  /**
   *漫游的暂停和继续
   *
   * @param * state bool类型 false为暂停，ture为继续
   * @memberof Roaming
  */
  PauseOrContinue(state,alt) {
    if (state) {
      // 继续播放
      if (!this.handler && this.entity) {
        this.addSceneEvent((time) => {
          this.getRoamingPosition(time, alt);
        });
      }
    } else if (this.handler) {
      // 停止监听屏幕绘制事件(停止相机变化)
      this.handler();
      this.handler = null;
      // 解锁相机视角
      this.viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
    }
    this.viewer.clock.shouldAnimate = state;
  }
  /**
   * 设置漫游路径是否可见
   * @param {boolean} visible
   * @memberof Roaming
  */
  setRoamingPathVisibility(visible) {
    if (this.entity) {
      this.entity.path.show = false;
      this.entity.polyline.show = visible;
    }
    // 更新全局漫游路径是否可见参数
    this.isPathShow = visible;
  }

  /**
   * 设置漫游模型是否可见
   * @param {boolean} visible
   * @memberof Roaming
  */
  setRoamingModelVisibility(visible) {
    if (this.entity) {
      this.entity.model.show = visible;
    }
  }
  /**
   *改变飞行的速度
   *
   * @param * value  整数类型
   * @memberof Roaming
  */
  ChangeRoamingSpeed(value) {
    this.viewer.clock.multiplier = value
  }
  /**
   *
   *取消漫游
   * @memberof Roaming
  */
  EndRoaming() {
    if (this.entity !== undefined)
      this.viewer.entities.remove(this.entity)
  }
  /**
   *
   *计算距离
  */
  calculateDistance(start, end) {
    let Cesium = useMapStore().$state.cesium;
    var geodesic = new Cesium.EllipsoidGeodesic();
    geodesic.setEndPoints(Cesium.Cartographic.fromCartesian(start), Cesium.Cartographic.fromCartesian(end));
    var distance = geodesic.surfaceDistance
    return distance
  }
}