/*
 * @Author: your name
 * @Date: 2021-12-07 14:19:18
 * @LastEditTime: 2022-10-12 10:09:44
 * @LastEditors: 纪泽龙 jizelong@qq.com
 * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 * @FilePath: /cesium-vue/src/utils/seieumClass.js
 */
window.danger = { name: "", colorNum: null, path: [], data: {} };
window.dangerArr = JSON.parse(localStorage.getItem('J') )?.length>0? JSON.parse(localStorage.getItem('J') ): [];
window.repeat = () => {
  window.danger = { name: "", path: [], data: {} };
};
window.save = () => {
  window.dangerArr.push(window.danger);
  const json = JSON.stringify(window.dangerArr);
  localStorage.setItem("J", json);
  console.log(json)
  window.repeat()
};

var viewModel = {
  silhouetteColor: "Yellow",
  silhouetteAlpha: 1.0,
  silhouetteSize: 2.0,
};

// 增删改操作
export const HANDLE_TYPE = {
  CREATE: 1, //新建
  EDIT: 2, //编辑
  DELETE: 3, //删除
};

// 新建设备类型
export const DEVICE_TYPE = {
  CAMEAR: 1, //摄像头
  PIPE: 2, //管道
};
// 设备模型路径
export const DEVICE_URL = {
  1: "glb/Cesium_Air.glb",
  2: "glb/Cesium_Air.glb",
  3: "glb/Cesium_Air.glb",
  4: "glb/Cesium_Air.glb",
};

// 上图图片
export const DEVICE_PIC_TYPE = {
  QIYE: 1,
  WEIXIANYUAN: 2,
  JIANKONGJIANCE: 3,
  ZHIYEWEIHAI: 4,
  YINHUAN: 5,
};
// 死数据用的
// const DEVICE_PIC_URL = {
//   1: require("@/assets/marks/jiankong.png"),
//   2: require("@/assets/marks/weixian.png"),
//   3: require("@/assets/marks/qttcq.png"),
//   4: require("@/assets/marks/yltcq.png"),

//   11: require("@/assets/indexImages/bottom/videoUrl.png"),
//   12: require("@/assets/indexImages/bottom/qtbjqUrl.png"),
//   13: require("@/assets/indexImages/bottom/ydtcqUrl.png"),
//   14: require("@/assets/indexImages/bottom/yltcqUrl.png"),
//   15: require("@/assets/indexImages/bottom/wdtcqUrl.png"),
//   // 首页的
// };
const DEVICE_PIC_URL = {
  // 工业探测器
  1: require("@/assets/indexImages/bottom/gytcqUrl.png"),
  // 温度变送器
  2: require("@/assets/indexImages/bottom/wdbsqUrl.png"),
  // 压力监测设备
  3: require("@/assets/indexImages/bottom/yljcqUrl.png"),
  // 液位探测器
  4: require("@/assets/indexImages/bottom/ywtcqUrl.png"),
  // 摄像头
  5: require("@/assets/indexImages/bottom/video2.png"),
  // 危险骷髅
  10: require("@/assets/marks/weixian.png"),

  // 11: require("@/assets/indexImages/bottom/videoUrl.png"),
  // 12: require("@/assets/indexImages/bottom/qtbjqUrl.png"),
  // 13: require("@/assets/indexImages/bottom/ydtcqUrl.png"),
  // 14: require("@/assets/indexImages/bottom/yltcqUrl.png"),
  // 15: require("@/assets/indexImages/bottom/wdtcqUrl.png"),
  // 首页的
};
const DEVICE_PIC_URL_WRING = {
  // 12: require("@/assets/indexImages/bottom/qtbjqUrlWring.png"),
};
const DEVICE_PIC_URL_ALARM = {
  // 12: require("@/assets/indexImages/bottom/qtbjqUrlAlarm.png"),
};
const arr = [];
const dangerColor = {
  // 1:Cesium.Color.fromCssColorString("red")
  1: Cesium.Color.RED.withAlpha(0.5),
  2: Cesium.Color.ORANGE.withAlpha(0.5),
  3: Cesium.Color.YELLOW.withAlpha(0.5),
  4: Cesium.Color.BLUE.withAlpha(0.5),
};

// const picUrlList = {
//   "1":
// }
const tdtLayer1 = new Cesium.UrlTemplateImageryProvider({
  url: "http://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=6",
  // url: "http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
  minimumLevel: 1,
  maximumLevel: 18,
});
const tdtLayer2 = new Cesium.UrlTemplateImageryProvider({
  url: "http://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8",
  // url: "http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
  minimumLevel: 1,
  maximumLevel: 18,
});
const tdtLayer3 = new Cesium.UrlTemplateImageryProvider({
  url: "http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
  // url: "http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
  minimumLevel: 1,
  maximumLevel: 18,
});

// var layer = new Cesium.MapboxStyleImageryProvider({
//   url: "https://api.mapbox.com/styles/v1",
//   username: "jzl007",
//   styleId: "ckx4gzqeg3bwd14phijgljh6p",
//   accessToken:
//     "pk.eyJ1IjoiZGVuZ3plbmdqaWFuIiwiYSI6ImNqbGhnbWo1ZjFpOHEzd3V2Ynk1OG5vZHgifQ.16zy39I-tbQv3K6UnRk8Cw",
//   scaleFactor: true,
// });

export default class CreateCesium {
  // 场景
  viewer = null;
  // div
  container = null;
  // 容器
  scene = null;
  // 三维场景的球体
  ellipsoid = null;
  // 鼠标是否是咋地图按下的状态
  mouseDownFlag = false;
  // 地图是否正在移动（当鼠标点击时鼠标是否在移动）
  mapMoveFlag = false;
  // 可点击的dom窗口
  infoWindow = null;
  // 弹框偏移量
  infowindowoffsetTop = 20;
  // infoWindow属于它，移动屏幕的时候可能会用到
  pickedObj = null;

  // 传入的vue实例
  vue = null;
  // 主场景存这里头
  tilesetArr = [];
  // 存储图片类型设备
  deviceTilesArr = {};
  // 存储危险范围
  dangerArr = [];
  // 增删改类型
  handleType = 1;
  // 新增设备类型
  deviceType = 0;
  // 滑块的位置 高度 水平角度 垂直角度
  sliderValue = [];
  // 当前的挂件
  nowTarget = null;
  infowindowTimer = null;
  // 用来记录同频定时器的timer
  animationTimer = null;
  constructor(container, urlArr, Vue, config) {
    this.vue = Vue;
    console.log("Vue", this.vue.$store);
    this.init(container, urlArr);
  }

  // 初始化
  init(container, urlArr, config = {}) {
    Cesium.Ion.defaultAccessToken =
      "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJhNjBmMGNiNi02ZWFiLTRkYzgtYWViMC05YjI3M2VhYWJlN2IiLCJpZCI6NzUzNDUsImlhdCI6MTY0NTQxMTUwM30.b_BS-ZeaQnLSJIP1HkbO22Z11VKMYuJvkCVvqQzm3QE";
    this.viewer = new Cesium.Viewer(container, {
      geocoder: false,
      homeButton: false,
      sceneModePicker: false,

      baseLayerPicker: false,
      navigationHelpButton: false,
      animation: false,
      // creditContainer: "credit",
      timeline: false,
      fullscreenButton: false,
      vrButton: false,
      infoBox: false,
      selectionIndicator: false,
      ...config,
    });
    this.viewer.cesiumWidget.creditContainer.style.display = "none";
    this.container = container;
    // this.t3 = this.viewer.imageryLayers.addImageryProvider(tdtLayer3);
    // this.t1 = this.viewer.imageryLayers.addImageryProvider(tdtLayer1);
    // this.t2 = this.viewer.imageryLayers.addImageryProvider(tdtLayer2);
    // this.viewer.imageryLayers.lowerToBottom(this.t3);

    // this.viewer.imageryLayers.addImageryProvider(tdtLayer3);
    console.log("this.viewer.imageryLayers", this.viewer.imageryLayers);
    this.viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
      Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
    );
    //   var orientation = {
    //     heading: 6.283185307179586,
    //     // 视角
    //     pitch: 0,
    //     roll: 0,
    // };
    // 地球初始位置
    this.viewer.camera.setView({
      destination: Cesium.Cartesian3.fromDegrees(116.2, 40.55, 10000),
      // orientation: {
      //   heading: -3,
      //   pitch: -1.5707963267948966,
      //   roll: 1.5,
      // },
      // orientation
    });
    // this.viewer.scene.sun.show = false; //在Cesium1.6(不确定)之后的版本会显示太阳和月亮，不关闭会影响展示
    // this.viewer.scene.moon.show = false;
    // this.viewer.scene.skyBox.show = false; //关闭天空盒，否则会显示天空颜色

    // this.viewer.scene.undergroundMode = true; //重要，开启地下模式，设置基色透明，这样就看不见黑色地球了
    // this.viewer.scene.underGlobe.show = true;
    // this.viewer.scene.underGlobe.baseColor = new Cesium.Color(0, 0, 0, 0);
    // this.viewer.scene.globe.show = false; //不显示地球，这条和地球透明度选一个就可以
    // this.viewer.scene.globe.baseColor = new Cesium.Color(0, 0, 0, 0);
    // this.viewer.scene.backgroundcolor = new Cesium.Color(0, 0, 0, 0);
    // this.viewer.imageryLayers.addImageryProvider(layer);

    this.scene = this.viewer.scene;
    // this.scene.globe.show = false; //不显示地球，这条和地球透明度选一个就可以
    // this.scene.sun.show = false; //在Cesium1.6(不确定)之后的版本会显示太阳和月亮，不关闭会影响展示
    // this.scene.moon.show = false;
    // this.scene.skyBox.show = false; //关闭天空盒，否则会显示天空颜色

    // 得到三维场景的球体
    this.ellipsoid = this.scene.globe.ellipsoid;
    // 地形监测
    // this.scene.globe.depthTestAgainstTerrain = true
    // 取消单机聚焦
    // this.viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
    //   Cesium.ScreenSpaceEventType.LEFT_CLICK
    // );

    // 兼容性
    this.compatibility();
    this.addtiles(urlArr, true);

    // this.addDevice(data, "pic");
    // 挂载事件
    // this.windowEvent();
    this.addEvent();
  }

  changeMapA() {
    this.viewer.imageryLayers.lowerToBottom(this.t3);
    // const t1 = this.viewer.imageryLayers.addImageryProvider(tdtLayer1);
    // const t2 = this.viewer.imageryLayers.addImageryProvider(tdtLayer2);
    // this.viewer.imageryLayers._layers.forEach((item) => {
    //   console.log(item);

    //   if (item != t1 && item != t2) {
    //     this.viewer.imageryLayers.remove(item);
    //   }
    // });
    // this.viewer.imageryLayers.addImageryProvider(tdtLayer3);
  }
  changeMapB() {
    this.viewer.imageryLayers.raiseToTop(this.t3);
    // const t3 = this.viewer.imageryLayers.addImageryProvider(tdtLayer3);
    // this.viewer.imageryLayers._layers.forEach((item) => {
    //   if (item != t3) {
    //     this.viewer.imageryLayers.remove(item);
    //   }
    // });
    // this.viewer.imageryLayers.addImageryProvider(tdtLayer3);
  }
  // 主要场景
  /**
   * @description:
   * @param {Array} urlArr 3dtail路径
   * @param {Boolean} main 主场景 true 非主场景 false
   * @return {*}
   */
  async addtiles(urlArr, main) {
    urlArr.forEach((url) => {
      const tileset = new Cesium.Cesium3DTileset({
        url,
      });
      this.scene.primitives.add(tileset);
      // console.log("adsf")
      tileset.readyPromise.then(async (tileset) => {
        let boundingSphere = tileset.boundingSphere;
        let cartographic = Cesium.Cartographic.fromCartesian(
          boundingSphere.center
        );
        const longitudeString = Cesium.Math.toDegrees(cartographic.longitude);
        const latitudeString = Cesium.Math.toDegrees(cartographic.latitude);
        var gps = [longitudeString, latitudeString];
        console.log("tileset加载完毕", gps);
        // 阻塞转换成高德坐标
        let gaodeLnglat = (await this.gpsToGaode(gps))[0];
        console.log("坐标换算完毕", gaodeLnglat);

        // AMap.convertFrom(gps, "gps",  (status, result) =>{
        //   if (result.info === "ok") {
        //     var lnglats = result.locations; // Array.<LngLat>
        //     let position = this.changeRelPosition([...lnglats,26])
        //   }
        // });
        let surface = Cesium.Cartesian3.fromRadians(
          cartographic.longitude,
          cartographic.latitude,
          0.0
        );
        let offset = Cesium.Cartesian3.fromRadians(
          Cesium.Math.toRadians(gps[0]),
          Cesium.Math.toRadians(gps[1]),
          -161.1
        );
        // let offset = Cesium.Cartesian3.fromRadians(
        //   Cesium.Math.toRadians(gaodeLnglat.lng),
        //   Cesium.Math.toRadians(gaodeLnglat.lat),
        //   -160
        // );
        let translation = Cesium.Cartesian3.subtract(
          offset,
          surface,
          new Cesium.Cartesian3()
        );
        tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
        tileset.style = new Cesium.Cesium3DTileStyle({
          color: "color('rgba(255,255,255,1)')",
        });
        // 主场景12312312;
        console.log("gaodeLnglat", gaodeLnglat);
        console.log("main", main);
        // 1.6454928984350525 -1.0974068412623752 0.00004639407505457882 114.14437322429676 38.398663934418344 319.0140849711926
        if (main) {
          this.tilesetArr.push(tileset);

          setTimeout(() => {
            this.viewer.scene.camera.flyTo({
              destination: Cesium.Cartesian3.fromDegrees(
                114.08040670822453,
                38.24912720167037,
                784
              ), //定位坐标点，建议使用谷歌地球坐标位置无偏差
              orientation: {
                // heading: 1.6454928984350525, // 方向
                // pitch: -1.0974068412623752, // 倾斜角度
                // roll: 0.00004639407505457882,
                // heading: Cesium.Math.toRadians(20.0), // 方向
                // pitch: Cesium.Math.toRadians(-90.0,), // 倾斜角度
                // roll: 1.3,
                heading: Cesium.Math.toRadians(0), // 方向
                pitch: Cesium.Math.toRadians(-81.61), // 倾斜角度
                // roll: 1.3,
              },
              duration: 0.1, //定位的时间间隔
            });
            setTimeout(() => {
              // this.changeMapB();
            }, 5);
            this.vue.$store.commit("SET_CESIUMT");
          }, this.vue.$store.state.cesium.CesiumT);
          console.log("走不走啊");
        } else {
          // this.deviceTilesArr.push(tileset);
        }
      });
    });
  }

  // 增加事件监听
  posLng = null;
  posLat = null;
  addEvent() {
    let handler = new Cesium.ScreenSpaceEventHandler(this.scene.canvas);
    handler.setInputAction((movement) => {
      // 新建
      if (this.handleType == 1 && this.deviceType == 1) {
        this.createDevice(movement);
      }
      var picked = this.scene.pick(movement.position);
      // console.log("picked", picked);
      if (Cesium.defined(picked)) {
        if (picked.id && picked.id instanceof Cesium.Entity) {
          // console.log(picked.id)
          // if( picked.id.danger) return;
          if (picked) console.log("选中了Entity");
          // 点中的;
          // this.billboardPicked = picked;
          // // 把点击的对象记录一下
          this.clearInfoWindow();
          this.pickedObj = picked.id;
          // console.log("选中了Entity", picked);

          let component = this.pickedObj.component;
          // 调整dom弹框的位置，如果是摄像头或者其他，那就是20，如果是大于12的别的带线的那就是60；
          if (this.pickedObj.deviceType > 11) {
            this.infowindowoffsetTop = 90;
          } else {
            this.infowindowoffsetTop = 20;
          }
          this.createInfoWindow(this.pickedObj);

          // // 移除地图挪动事件
          // this.viewer.scene.screenSpaceCameraController.enableRotate = false;
          // const lnt = this.changeLngLatHeight(this.nowTarget.position._value);
          // const cartesian = this.viewer.camera.pickEllipsoid(
          //   movement.position,
          //   this.ellipsoid
          // );
          // let cartographic = this.ellipsoid.cartesianToCartographic(cartesian);
          // // 将弧度转为度的十进制度表示,就是将弧度转化为经纬度
          // const longitudeString = Cesium.Math.toDegrees(cartographic.longitude);
          // const latitudeString = Cesium.Math.toDegrees(cartographic.latitude);
          // this.posLng = longitudeString - lnt[0];
          // this.poslat = latitudeString - lnt[1];

          // handler.setInputAction(
          //   this.mouseMove.bind(this),
          //   Cesium.ScreenSpaceEventType.MOUSE_MOVE
          // );
        }
        if (picked.primitive instanceof Cesium.Primitive) {
          console.log("选中了Primitive");
        }
        if (picked.primitive instanceof Cesium.Model) {
          console.log("选中了模型");
        }
        if (picked instanceof Cesium.Cesium3DTileFeature) {
          console.log("选中了3DTile");
        }
      }
      const height = this.viewer.camera.positionCartographic.height.toFixed(0);
      //方向   围绕Z轴旋转
      const heading = Cesium.Math.toDegrees(this.viewer.camera.heading).toFixed(
        2
      );
      //倾斜角度   围绕Y轴旋转
      const pitch = Cesium.Math.toDegrees(this.viewer.camera.pitch).toFixed(2);
      //围绕X轴旋转
      const roll = Cesium.Math.toDegrees(this.viewer.camera.roll).toFixed(2);
      // console.log(height, heading, pitch, roll);
      const ln = this.getLnglat(movement);
      // console.log(ln);

      window.danger.path.push(ln);
      console.log(window.danger.path);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    handler.setInputAction((movement) => {
      // 新建
    }, Cesium.ScreenSpaceEventType.END);

    handler.setInputAction((movement) => {
      // 如果是鼠标按下的状态，则监听地图移动
      if (this.mouseDownFlag) {
        // console.log("地图移动");
        // this.clearInfoWindow();
        // 改变位置
        // this.changePosition();
        // 这里写关于infowindow的事
      } else {
      }

      let picked = this.scene.pick(movement.endPosition);
      if (!Cesium.defined(picked)) {
        this.viewer._container.style.cursor = "default";
        return;
      }
      if (picked.id && picked.id instanceof Cesium.Entity) {
        this.viewer._container.style.cursor = "pointer";
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

    handler.setInputAction(async (movement) => {
      // 鼠标已经按下
      this.mouseDownFlag = true;
      // 按下鼠标删除infoWindow
      // this.clearInfoWindow();

      var picked = this.scene.pick(movement.position);
      // console.log(movement.position);
      if (Cesium.defined(picked)) {
        if (picked.id && picked.id instanceof Cesium.Entity) {
          // console.log(picked.id)
          // if( picked.id.danger) return;
          if (picked) console.log("选中了Entity");
          // 点中的;
          // this.billboardPicked = picked;
          // // 把点击的对象记录一下
          // this.clearInfoWindow();
          // this.pickedObj = picked.id;
          // console.log("选中了Entity", picked);

          // let component = this.pickedObj.component;
          // this.createInfoWindow(this.pickedObj);

          // // 移除地图挪动事件
          // this.viewer.scene.screenSpaceCameraController.enableRotate = false;
          // const lnt = this.changeLngLatHeight(this.nowTarget.position._value);
          // const cartesian = this.viewer.camera.pickEllipsoid(
          //   movement.position,
          //   this.ellipsoid
          // );
          // let cartographic = this.ellipsoid.cartesianToCartographic(cartesian);
          // // 将弧度转为度的十进制度表示,就是将弧度转化为经纬度
          // const longitudeString = Cesium.Math.toDegrees(cartographic.longitude);
          // const latitudeString = Cesium.Math.toDegrees(cartographic.latitude);
          // this.posLng = longitudeString - lnt[0];
          // this.poslat = latitudeString - lnt[1];

          // handler.setInputAction(
          //   this.mouseMove.bind(this),
          //   Cesium.ScreenSpaceEventType.MOUSE_MOVE
          // );
        }
        if (picked.primitive instanceof Cesium.Primitive) {
          console.log("选中了Primitive");
        }
        if (picked.primitive instanceof Cesium.Model) {
          console.log("选中了模型");
        }
        if (picked instanceof Cesium.Cesium3DTileFeature) {
          console.log("选中了3DTile");
          const ln = this.getLnglat(movement);
          console.log(ln);
        }
      }
    }, Cesium.ScreenSpaceEventType.LEFT_DOWN);

    handler.setInputAction((movement) => {
      // 鼠标抬起
      this.mouseDownFlag = false;

      // console.log("up");

      // this.viewer.scene.screenSpaceCameraController.enableRotate = true;
      // handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    }, Cesium.ScreenSpaceEventType.LEFT_UP);

    handler.setInputAction((movement) => {
      // 鼠标中建按下删掉infoWindow
      // this.clearInfoWindow();
    }, Cesium.ScreenSpaceEventType.MIDDLE_DOWN);

    handler.setInputAction((movement) => {
      // 鼠标中建按下删掉infoWindow
      // this.clearInfoWindow();
      // this.changePosition();
      // console.log(this.viewer.camera);
      const cartographic = this.viewer.camera.positionCartographic;
      const { height, longitude, latitude } = cartographic;

      // console.log(
      //   this.viewer.camera.heading,
      //   this.viewer.camera.pitch,
      //   this.viewer.camera.roll,
      //   Cesium.Math.toDegrees(longitude),
      //   Cesium.Math.toDegrees(latitude),
      //   height
      // );
    }, Cesium.ScreenSpaceEventType.WHEEL);
    // 摄像机监听
    this.viewer.camera.changed.addEventListener((percentage) => {
      // 打印中心点坐标、高度
      // 当鼠地图移动的时候与相机事件隔离
      if (!this.mouseDownFlag) {
        // console.log("相机发生变化");
        // this.clearInfoWindow();
      }
    });
    // 键盘ctrl 或者 shift按下，删掉infoWindow 因为位置不好调整
    document.addEventListener(
      "keydown",
      (e) => {
        if (e.key == "Shift" || e.key == "Control") {
          // this.clearInfoWindow();
        }
      },
      false
    );
  }
  windowEvent() {
    let flag = false;
    const canvas = document.querySelector("canvas");

    canvas.addEventListener("pointerdown", (e) => {
      flag = true;
    });
    canvas.addEventListener("pointermove", () => {
      if (flag) {
        console.log(flag);
        // this.changePosition();
      }
    });
    canvas.addEventListener("pointerup", (e) => {
      flag = false;
      // canvas.removeEventListener("mousemove", move)
    });
  }

  // 当创建就会激活，持续的更新infowindow的位置，infowindow改变位置
  changePosition() {
    this.animationTimer = window.requestAnimationFrame(() => {
      // console.log("持续定时")
      if (this.infoWindow) {
        const { width, height } = this.infoWindow.getBoundingClientRect();
        this.infoWindowPositionChange(this.pickedObj, width / 2, height);
        // console.log("计算中");
      }
      this.changePosition();
    });
  }
  // 清除计时器
  requestAnimationFrameClear() {
    // console.log("清除cancelAnimationFrame")
    window.cancelAnimationFrame(this.animationTimer);
  }
  mouseMove(movement) {
    const cartesian = this.viewer.camera.pickEllipsoid(
      movement.endPosition,
      this.ellipsoid
    );
    let cartographic = this.ellipsoid.cartesianToCartographic(cartesian);
    // 将弧度转为度的十进制度表示,就是将弧度转化为经纬度
    const longitudeString = Cesium.Math.toDegrees(cartographic.longitude);
    const latitudeString = Cesium.Math.toDegrees(cartographic.latitude);
    this.vue.heightReset();
    this.glbPositoinChange([longitudeString, latitudeString]);

    // const ray = this.viewer.camera.getPickRay(movement.endPosition)
    // let cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene)
    // console.log(cartesian)

    // this.nowTarget.position = cartesian;
    // this.vue.heightReset();
  }

  // 创建infowindow
  createInfoWindow(obj) {
    console.log("obj.component.myNull", obj.component.myNull);
    if (!obj.component) return;

    if (this.infoWindow) {
      this.clearInfoWindow();
    }
    // // 把点击的对象记录一下
    // this.pickedObj = picked.id;
    const component = this.createInfowindowDom(
      this.vue,
      this,
      obj.data,
      obj.component
    );
    // 当时NUll组件的时候，就不往下走了
    if (component.myNull) return;
    const div = component.$el;

    const { width, height } = div.getBoundingClientRect();
    // 如果为空 就不往下走了
    // if(width===0||height===0) return;
    // div.className = "ol-overlay-container ol-selectable";
    // 挂在infowindow上
    this.infoWindow = div;

    div.style.position = "absolute";
    // div.style.opacity=0;
    document.querySelector(`#${this.container}`).appendChild(div);
    // 改变infoWindow位置
    console.log("this.pickedObj", this.pickedObj);
    // this.infoWindowPositionChange(this.pickedObj, width / 2, height);
    // 持续的更改infowindow的位置
    this.changePosition();
    // this.infoWindowTimerFunc();
  }
  // 用来实时计算winfowindow的位置
  // infoWindowTimerFunc() {
  //   this.infowindowTimer = setInterval(() => {
  //     if (this.infoWindow) {
  //       const { width, height } = this.infoWindow.getBoundingClientRect();
  //       this.infoWindowPositionChange(this.pickedObj, width / 2, height);
  //       console.log("计算中");
  //     } else {
  //       clearInterval(this.infowindowTimer);
  //       console.log("停止计算");
  //     }
  //   }, 1);
  // }
  createInfowindowDom(vueRoot, mapClass, deviceData, component) {
    const Component = this.vue.$Vue.extend(component, {});
    return new Component({
      data() {
        return {
          // 当前vue实例
          vueRoot,
          // 自己写的map类
          mapClass,
          // 数据
          deviceData,
        };
      },
    }).$mount();
  }
  // 获取点击infowindow载体，目标的位置
  getPickdePosition(pickedObj, width = 0, height = 0) {
    // 当前点击目标的位置
    let lnglat;
    if (pickedObj.position?._value) {
      lnglat = this.changeLngLatHeight(pickedObj.position._value);
    } else {
      const a = pickedObj.data.lnglatArr[0];
      const b = pickedObj.data.lnglatArr[1];
      const c = pickedObj.data.lnglatArr[2];
      const d = pickedObj.data.lnglatArr[3];
      lnglat = [
        (a[0] + b[0] + c[0] + d[0]) / 4,
        (a[1] + b[1] + c[1] + d[1]) / 4,
      ];
    }

    const windowPosition = this.getWindowPosition(
      [...lnglat],
      pickedObj.data.shortNum
    );
    // 100是相对调整量，也就是地图以外的参数发生变化
    // const top = `${+windowPosition.y + 100 - 30}px`;
    // const left = `${+windowPosition.x - 10 + 30}px`;
    // const top = `${+windowPosition.y + 100 - height - 20}px`;
    // console.log("height", height);
    const top = `${+windowPosition.y - height - this.infowindowoffsetTop}px`;
    const left = `${+windowPosition.x - width}px`;
    return {
      top,
      left,
    };
  }
  // 删除infoWindow
  clearInfoWindow() {
    if (this.infoWindow) {
      document.querySelector(`#${this.container}`).removeChild(this.infoWindow);
      this.infoWindow = null;
      this.pickedObj = null;
      this.requestAnimationFrameClear();
    }
  }
  // 改变infoWindow的位置
  infoWindowPositionChange(pickedObj, width = 0, height = 0) {
    if (!this.infoWindow) return;
    const { top, left } = this.getPickdePosition(pickedObj, width, height);
    // console.log(top, left);
    this.infoWindow.style.top = top;
    this.infoWindow.style.left = left;
  }
  // 新增设备
  createDevice(movement) {
    let longitudeString = null;
    let latitudeString = null;
    let height = null;
    let cartesian = null;

    //通过指定的椭球或者地图对应的坐标系，将鼠标的二维坐标转换为对应椭球体三维坐标,以球心为原点的，三维直角坐标系里的xyz
    cartesian = this.viewer.camera.pickEllipsoid(
      movement.position,
      this.ellipsoid
    );
    if (cartesian) {
      //将笛卡尔xyz坐标转换为 球体上位置的弧度，也就是经纬度的弧度
      let cartographic = this.ellipsoid.cartesianToCartographic(cartesian);
      //将弧度转为度的十进制度表示,就是将弧度转化为经纬度
      longitudeString = Cesium.Math.toDegrees(cartographic.longitude);
      latitudeString = Cesium.Math.toDegrees(cartographic.latitude);
      //获取相机高度
      // height = Math.ceil(this.viewer.camera.positionCartographic.height);
      // console.log(this.handleType, longitudeString, latitudeString);
      height = this.sliderValue[0];
      // 如果存在nowTarget 则删除
      this.nowTarget && this.removeEntitie(this.nowTarget);
      this.nowTarget = this.createglb("glb/Cesium_Air.glb", [
        longitudeString,
        latitudeString,
        height,
      ]);
    }
  }

  // 设备上图
  /**
   * @description:
   * @param {*} arr 这个是数据
   * @param {*} type 这个是类型 图片 还是模型
   * @param {*} deviceType 这个是图片数据的类型
   * @return {*}
   */
  //  longitude: 114.087623,
  //  latitude: 38.252394,
  addDevice(item, type, component) {
    if (type == "pic") {
      // 当类型是企业的时候
      // if (deviceType == DEVICE_PIC_TYPE.QIYE) {
      // 创建企业的数组
      // const qiyeArr = (this.deviceTilesArr[deviceType] = []);
      const { longitude, latitude, shortNum, deviceType, title, deviceState } =
        item;
      let imageUrl;
      // // 1正常，2警告，3报警,没有的就按原来的算
      // if (deviceState == 1 || !deviceState) {
      //   imageUrl = DEVICE_PIC_URL[deviceType];
      // } else if (deviceState == 2) {
      //   imageUrl = DEVICE_PIC_URL_WRING[deviceType];
      // } else {
      //   imageUrl = DEVICE_PIC_URL_ALARM[deviceType];
      // }
      imageUrl = DEVICE_PIC_URL[deviceType];

      const obj = this.createPicture(
        imageUrl,
        [longitude, latitude, shortNum ? shortNum : 0],
        title,
        item.config
      );
      // 用来传参调接口的id
      obj.billboardId = item.billboardId;
      // 用来区分设备类型的type
      obj.deviceType = deviceType;
      // 用来漫游的经纬度
      obj.lnglat = [longitude, latitude];
      obj.component = component;
      obj.data = item;
      if (!Array.isArray(this.deviceTilesArr[deviceType])) {
        this.deviceTilesArr[deviceType] = [];
      }
      this.deviceTilesArr[deviceType].push(obj);
      // console.log("obj", obj);
      // }
    } else {
      // arr.forEach((item) => {
      //   const entity = createglb();
      // });
    }
  }

  createPicture(imgUrl, latlngArr, title, configA) {
    // 去掉\r\n还有空格
    title = title.replace(/\r\n/g, "");
    title = title.replace(/\n/g, "");
    title = title.replace(/\s/g, "");
    // latlngArr[2] = latlngArr[2]+20;
    let config = configA ? configA : { scale: 0.4, textHeight: -32 };
    const picObj = this.viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(...latlngArr),
      billboard: {
        image: imgUrl, // default: undefined
        show: true, // default
        // pixelOffset: new Cesium.Cartesian2(0, -50), // default: (0, 0)
        // eyeOffset: new Cesium.Cartesian3(0.0, 0.0, 0.0), // default
        // horizontalOrigin: Cesium.HorizontalOrigin.CENTER, // default
        // verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // default: CENTER
        scale: config.scale, // default: 1.0
        // color: Cesium.Color.LIME, // default: WHITE
        // rotation: Cesium.Math.PI_OVER_FOUR, // default: 0.0
        // alignedAxis: Cesium.Cartesian3.ZERO, // default
        // width: 20, // default: undefined
        // height: 20, // default: undefined
        // sizeInMeters: true, //是否开启屋里大小
      },
      label: {
        text: `${title}`,
        showBackground: true,
        fillColor: new Cesium.Color(Cesium.Color.ALICEBLUE),
        backgroundColor: new Cesium.Color(0.165, 0.165, 0.165, 0.5),
        font: "10px sans-serif",
        pixelOffset: new Cesium.Cartesian2(0, config.textHeight),
      },
    });
    // picObj.show = false;
    return picObj;
  }
  deviceFilter(bool, deviceType) {
    this.deviceTilesArr[deviceType].forEach((item) => {
      item.show = bool;
    });
    // 隐藏时，档期那infowindow也需要隐藏
    console.log(this.pickedObj);
    if (!bool && this.pickedObj?.deviceType == deviceType) {
      this.clearInfoWindow();
    }
  }
  deviceAllShow(bool, arr) {
    for (let item in this.deviceTilesArr) {
      //  等于2是小骷髅，不在过滤范围内
      if (item.deviceType != 2) {
        // 当item在传进来的数组之中，就展示，否则隐藏
        if (arr.includes(+item)) {
          this.deviceTilesArr[item].forEach((iten) => (iten.show = bool));
        }
      }
    }
  }

  // pic billboard的隐藏与显示
  entitieShow(bool, type) {
    this.deviceTilesArr[type].forEach((item) => {
      item.show = bool;
    });
    bool && this.flyTo(this.deviceTilesArr[type][0]);
  }

  // 添加挂件
  /**
   * @description:
   * @param {Array} positionArr 经纬度以及高度
   * @return {*}
   */
  createglb(url, positionArr) {
    // 删除viewer上的所有实体
    // 根据经纬度跟高度换算出实体在以地球为基准的卡迪尔坐标系中的位置
    let position = Cesium.Cartesian3.fromDegrees(...positionArr);
    console.log("position", position);

    // 角度转换为弧度
    const h = this.sliderValue[1];
    const p = this.sliderValue[2];
    let heading = Cesium.Math.toRadians(h);
    let pitch = Cesium.Math.toRadians(p);
    let roll = 0;
    // 三个角度的阵
    let hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
    // 根据位置 计算实体在空间中的角度
    let orientation = Cesium.Transforms.headingPitchRollQuaternion(
      position,
      hpr
    );
    // 创建实体
    const entity = this.viewer.entities.add({
      name: url,
      position: position,
      orientation: orientation,
      model: {
        uri: url,
        // 像素
        minimumPixelSize: 10,
        // maximumScale: 0.1,
        // scale: 120,
        // 最大缩放的时候，就一直是129像素
        // maximumScale: 20000000,
        // colorBlendMode: getColorBlendMode(viewModel.colorBlendMode),
        // colorBlendAmount: parseFloat(viewModel.colorBlendAmount),
        silhouetteColor: this.getColor(
          viewModel.silhouetteColor,
          viewModel.silhouetteAlpha
        ),
        silhouetteSize: parseFloat(viewModel.silhouetteSize),
      },
    });

    return entity;
    // console.log(entity);
    // 摄像机跟踪实体
    // this.viewer.trackedEntity = entity;
  }
  // 描边颜色
  getColor(colorName, alpha) {
    var color = Cesium.Color[colorName.toUpperCase()];
    console.log(color);
    return Cesium.Color.fromAlpha(color, parseFloat(alpha));
  }

  // glb模型文件位置变化，高度跟经纬度
  glbPositoinChange(lnglat) {
    if (this.nowTarget) {
      // const lnglatArr = this.changeLngLatHeight(this.nowTarget._value)
      // 如果传了就是自己，没传就用nowTarget的
      const height = this.sliderValue[0];

      let lnglatArr = lnglat
        ? lnglat
        : this.changeLngLatHeight(this.nowTarget.position._value);
      const position = this.changeRelPosition([...lnglatArr, height]);
      this.nowTarget.position = position;
      return position;
    }
  }
  // glb的角度变化,顺带着高度变化直接发生，所以用着一个就行了，因为角度变化需要知道高度
  glbDegChange() {
    if (this.nowTarget) {
      // 会激发高度变化
      const position = this.glbPositoinChange();
      // 角度转换为弧度
      const h = this.sliderValue[1];
      const p = this.sliderValue[2];
      const heading = Cesium.Math.toRadians(h);
      const pitch = Cesium.Math.toRadians(p);
      const roll = 0;
      // 三个角度的阵
      const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
      // 根据位置 计算实体在空间中的角度
      const orientation = Cesium.Transforms.headingPitchRollQuaternion(
        position,
        hpr
      );
      this.nowTarget.orientation = orientation;
    }
  }
  // 工具方法

  // 在球体上的真实位置转化成经纬度
  changeLngLatHeight(llhObj) {
    const cartographic = this.ellipsoid.cartesianToCartographic(llhObj);
    const longitude = Cesium.Math.toDegrees(cartographic.longitude);
    const latitude = Cesium.Math.toDegrees(cartographic.latitude);
    return [longitude, latitude];
  }
  // 把经纬度跟高度转化成真实位置
  changeRelPosition(positionArr) {
    return Cesium.Cartesian3.fromDegrees(...positionArr);
  }

  // 将经纬度转换为屏幕坐标
  getWindowPosition(lntArr, height = 0) {
    let position = Cesium.Cartesian3.fromDegrees(...lntArr, height);
    let chanedc = Cesium.SceneTransforms.wgs84ToWindowCoordinates(
      this.viewer.scene,
      position
    );
    return chanedc;
  }
  // 屏幕坐标转换为经纬度
  getLnglat(movement) {
    let clickPosition = this.viewer.scene.camera.pickEllipsoid(
      movement.position
    );
    // 转经纬度（弧度）坐标
    let radiansPos = Cesium.Cartographic.fromCartesian(clickPosition);
    // 转角度
    return [
      Cesium.Math.toDegrees(radiansPos.longitude),
      Cesium.Math.toDegrees(radiansPos.latitude),
    ];
    console.log(
      "经度：" +
        Cesium.Math.toDegrees(radiansPos.longitude) +
        ", 纬度：" +
        Cesium.Math.toDegrees(radiansPos.latitude)
    );
  }

  // 将经纬度转换为高德地图的经纬度
  gpsToGaode(lnglatArr) {
    window.AMap = AMap;
    console.log("lnglatArr", lnglatArr);
    console.log("12312312312312399999999999999999999999", AMap);

    // var gps = [longitudeString, latitudeString];
    return new Promise((resove) => {
      AMap.convertFrom(lnglatArr, "gps", (status, result) => {
        if (result.info === "ok") {
          var lnglats = result.locations; // Array.<LngLat>
          resove(lnglats);
        }
      });
    });
  }
  // 相机镜头
  zoomTo(tileset) {
    this.viewer.zoomTo(tileset);
  }
  flyTo(obj) {
    this.viewer.scene.camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(...obj.lnglat, 2000), //定位坐标点，建议使用谷歌地球坐标位置无偏差
      duration: 4, //定位的时间间隔
    });
  }
  // 删除一个对象
  removeEntitie(entitie) {
    this.viewer.entities.remove(entitie);
  }
  // 114.13961363922698, 38.39783804514072, 114.146099, 38.398604,

  addDanger(item, component) {
    const polygon = this.viewer.entities.add({
      polygon: {
        hierarchy: new Cesium.PolygonHierarchy(
          Cesium.Cartesian3.fromDegreesArray(item.lnglatArr.flat())
        ),
        // material: Cesium.Color.RED.withAlpha(0.5),
        material: dangerColor[item.colorNum],
        classificationType: Cesium.ClassificationType.BOTH,
        // classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
      },
    });
    polygon.danger = true;
    polygon.show = true;
    polygon.component = component;
    polygon.data = item;
    this.dangerArr.push(polygon);
  }
  dangerTotal(bool, wrapperDom) {
    this.dangerArr.forEach((item) => {
      item.show = bool;
    });
    if (this.infoWindow?.className?.indexOf(wrapperDom) >= 0) {
      this.clearInfoWindow();
    }
  }
  // 所有危险源展示
  dangerAllShow(bool) {
    this.dangerArr.forEach((item) => {
      item.show = bool;
    });
    this.deviceTilesArr[10].forEach((item) => {
      item.show = bool;
    });
  }
  // 危险源与风险分布区切换
  dangeDeviceChange(type, bottomDeviceArr) {
    if (type == 1) {
      this.deviceAllShow(true, bottomDeviceArr);
      this.dangerAllShow(false);
    } else {
      this.deviceAllShow(false, bottomDeviceArr);
      this.dangerAllShow(true);
    }
    this.clearInfoWindow();
  }
  destroy() {
    this.viewer.destroy();
  }
  // 兼容性
  compatibility() {
    // Object.defineProperties(Cesium.Model.prototype, {
    //   _cachedGltf: {
    //   },
    // });
    let fixGltf = (gltf) => {
      if (!gltf.extensionsUsed) {
        return;
      }
      let v = gltf.extensionsUsed.indexOf("KHR_technique_webgl");
      let t = gltf.extensionsRequired.indexOf("KHR_technique_webgl");
      // 中招了。。
      if (v !== -1) {
        gltf.extensionsRequired.splice(t, 1, "KHR_techniques_webgl");
        gltf.extensionsUsed.splice(v, 1, "KHR_techniques_webgl");
        gltf.extensions = gltf.extensions || {};
        gltf.extensions["KHR_techniques_webgl"] = {};
        gltf.extensions["KHR_techniques_webgl"].programs = gltf.programs;
        gltf.extensions["KHR_techniques_webgl"].shaders = gltf.shaders;
        gltf.extensions["KHR_techniques_webgl"].techniques = gltf.techniques;
        let techniques = gltf.extensions["KHR_techniques_webgl"].techniques;

        gltf.materials.forEach(function (mat, index) {
          gltf.materials[index].extensions["KHR_technique_webgl"].values =
            gltf.materials[index].values;
          gltf.materials[index].extensions["KHR_techniques_webgl"] =
            gltf.materials[index].extensions["KHR_technique_webgl"];

          let vtxfMaterialExtension =
            gltf.materials[index].extensions["KHR_techniques_webgl"];

          for (let value in vtxfMaterialExtension.values) {
            let us = techniques[vtxfMaterialExtension.technique].uniforms;
            for (let key in us) {
              if (us[key] === value) {
                vtxfMaterialExtension.values[key] =
                  vtxfMaterialExtension.values[value];
                delete vtxfMaterialExtension.values[value];
                break;
              }
            }
          }
        });

        techniques.forEach(function (t) {
          for (let attribute in t.attributes) {
            let name = t.attributes[attribute];
            t.attributes[attribute] = t.parameters[name];
          }
          for (let uniform in t.uniforms) {
            let name = t.uniforms[uniform];
            t.uniforms[uniform] = t.parameters[name];
          }
        });
      }
    };
    console.log("aaa--------", Cesium.Model.prototype);
    // 记录原始兼容性
    if (this.vue.$store.state.cesium.CesiumModelPrototype == true) return;
    this.vue.$store.commit("SET_CESIUMMODE");

    Object.defineProperties(Cesium.Model.prototype, {
      _cachedGltf: {
        set: function (value) {
          this._vtxf_cachedGltf = value;
          if (this._vtxf_cachedGltf && this._vtxf_cachedGltf._gltf) {
            fixGltf(this._vtxf_cachedGltf._gltf);
          }
        },
        get: function () {
          return this._vtxf_cachedGltf;
        },
      },
    });
  }
}
