<template>
  <div id="skysceneryContainer">
    <Popup />
  </div>
</template>

<script>
import Popup from "@/components/Popup.vue";
export default {
  name: "Map",
  components: {
    Popup,
  },
  data() {
    return {
      // viewer3DTiles实例《systemConfig.data3DTiles keys,tile》
      viewer3DTiles: {},
      // 3DTiles options集合《systemConfig.data3DTiles keys,options》
      keysByOptions: {},
    };
  },
  mounted() {
    window.SkySceneryConfig = {};
    for (let tileName in systemConfig.data3DTiles) {
      for (let key in systemConfig.data3DTiles[tileName]) {
        let options = systemConfig.data3DTiles[tileName][key];
        this.keysByOptions[tileName + key] = options;
      }
    }
    this.getToken();
  },
  methods: {
    getToken() {
      let that = this;
      let loginInfo = new FormData();
      for (const key in userLoginConfig) {
        if (Object.prototype.hasOwnProperty.call(userLoginConfig, key)) {
          loginInfo.append(key, userLoginConfig[key]);
        }
      }
      fetch(oauthUrl + "/oauth/api/user/login", {
        method: "POST",
        body: loginInfo,
      })
        .then((resp) => resp.json())
        .then((data) => {
          SkySceneryConfig = {
            authUrl: oauthUrl,
            token: data.message,
          };
          that.pushAllScripts();
        });
    },

    pushAllScripts() {
      let that = this;
      that.addScripts(scriptObj.main).then(function () {
        let arr = scriptObj.plugins.map(function (src) {
          return that.addScripts(src);
        });
        Promise.all(arr).then(function () {
          setTimeout(() => {
            if (SkyScenery) {
              that.creatMap();
            } else {
              that.pushAllScripts();
            }
          });
        });
      });
    },

    addScripts(src) {
      return new Promise((resolve, reject) => {
        // 创建一个新的script标签
        var script = document.createElement("script");
        // 设置script标签的src属性为要引入的JavaScript文件的URL
        script.src = src;
        // 将script标签添加到页面的head部分或者其他合适的位置
        document.head.appendChild(script);
        if (script.readyState) {
          // IE
          script.onreadystatechange = function () {
            if (script.readyState === "loaded" || script.readyState === "complete") {
              script.onreadystatechange = null;
              resolve();
            }
          };
        } else {
          // 其他浏览器
          script.onload = function () {
            resolve();
          };
        }
      });
    },
    creatMap() {
      try {
        let that = this;
        window.viewer = new SkyScenery.Viewer("skysceneryContainer", {
          animation: false, //是否创建动画小器件，左下角仪表
          baseLayerPicker: false, //是否显示图层选择器
          imageryProvider: new SkyScenery.SingleTileImageryProvider({
            url: (function createColorCanvas(color) {
              var width = 1,
                height = 1;
              var canvas = document.createElement("canvas");
              canvas.width = width;
              canvas.height = height;
              var ctx = canvas.getContext("2d");
              ctx.fillStyle = color;
              ctx.fillRect(0, 0, width, height);
              return canvas.toDataURL();
            })("#ffffff00"),
            tileWidth: document.createElement("canvas").width,
            tileHeight: document.createElement("canvas").height,
            rectangle: SkyScenery.Rectangle.fromDegrees(-180.0, -90.0, 180.0, 90.0),
          }),
          fullscreenButton: false, //是否显示全屏按钮
          geocoder: false, //是否显示geocoder小器件，右上角查询按钮
          homeButton: false, //是否显示Home按钮
          infoBox: false, //是否显示信息框
          sceneModePicker: false, //是否显示3D/2D选择器
          selectionIndicator: false, //是否显示选取指示器组件
          timeline: false, //是否显示时间轴
          navigationHelpButton: false, //是否显示右上角的帮助按钮
          scene3DOnly: true, //如果设置为true，则所有几何图形以3D模式绘制以节约GPU资源
          infoBox: false, //是否显示点击要素之后显示的信息
          shouldAnimate: false, //是否自动播放
          // contextOptions: {
          //   requestWebgl1: true
          // }
        });
        setTimeout(() => {
          // 根据配置文件中的配置信息加载底图
          systemConfig.imageryProviders.forEach((url) => {
            that.loadTheWorldMapImage(url);
          });

          // 设置地表透明度为 0.5（值在 0 到 1 之间，0 为完全透明，1 为不透明）
          // viewer.scene.globe.translucency.enabled = true;
          // viewer.scene.globe.baseColor = new SkyScenery.Color(1.0, 1.0, 1.0, 0.1);
          viewer.camera.setView({
            destination: SkyScenery.Cartesian3.fromDegrees(
              121.28277083019914,
              31.065009352291785,
              12790.087231596899
            ), // 设置位置
            orientation: {
              heading: SkyScenery.Math.toRadians(356.03124445628373), // 方向
              pitch: SkyScenery.Math.toRadians(-45.31423437919367), // 倾斜角度
              roll: SkyScenery.Math.toRadians(0.0047802614997811636)
            }
          });

          this.$store.commit("createdMap", true);

          // 绑定点击事件
          let handler = new SkyScenery.ScreenSpaceEventHandler(viewer.canvas);
          handler.setInputAction(function (movement) {
            var pick = viewer.scene.pick(movement.position); // 拾取鼠标所在的entity
            if (SkyScenery.defined(pick)) {
              let entity = pick.id;
              if (!entity) return;
              if (entity.type && (entity.type == "layers" || entity.type == "edge")) {
                let cartesian = viewer.camera.pickEllipsoid(
                  movement.position,
                  viewer.scene.globe.ellipsoid
                );
                // 空间坐标转世界坐标(弧度)
                if (!cartesian) return;
                let cartographic = SkyScenery.Cartographic.fromCartesian(cartesian);
                if (!cartographic) return;
                // 弧度转为角度（经纬度）
                let lon = SkyScenery.Math.toDegrees(cartographic.longitude); // 经度值
                let lat = SkyScenery.Math.toDegrees(cartographic.latitude); // 纬度值
                let showEntity = SkyScenery.Cartesian3.fromDegrees(lon, lat);
                showEntity.data = entity.properties.getValue();
                that.$store.state.showEntity = showEntity;
              } else {
              }
            } else {
              that.$store.state.showEntity = null;
            }
          }, SkyScenery.ScreenSpaceEventType.LEFT_CLICK);

          return;
        }, 0);
      } catch (error) {
        console.log("createMap error:", error);
        window.location.reload();
      }
    },

    /**
     * 加载天地图底图
     * @author LiuMengxiang
     * 加载影像底图和影像注记
     */
    async loadTheWorldMapImage(url) {
      // if (url.indexOf("//t0.") != -1) {
      //   url = url.replace("//t0.", "//t{s}.");
      // }
      // viewer.imageryLayers.addImageryProvider(
      //   new SkyScenery.WebMapTileServiceImageryProvider({
      //     url:
      //       url +
      //       "?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=" +
      //       systemConfig.tdt_tk,
      //     layer: "img",
      //     style: "default",
      //     tileMatrixSetID: "w",
      //     format: "image/jpeg",
      //     subdomains: ["0", "1", "2", "3", "4", "5", "6", "7"],
      //     show: true,
      //     minimumLevel: 1,
      //     maximumLevel: 18
      //   })
      // );
      // let layer = await SkyScenery.ArcGisMapServerImageryProvider.fromUrl(
      //   "https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer"
      // );
      let layer = new SkyScenery.ArcGisMapServerImageryProvider({
        url:
          "https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer",
      });
      viewer.imageryLayers.addImageryProvider(layer);
    },

    // 加载geojson数据
    addGeoJson(url, options) {
      // options = {
      //   point: {
      //     imgUrl: ""
      //   },
      //   polyline: {
      //     color: "#ffffff",
      //     width: 3,
      //     alpha: 0.7
      //   },
      //   polygon: {
      //     outerColor: "#ffffff",
      //     outerWidth: 3,
      //     innerColor: "#ffffff",
      //     alpha: 0.7
      //   }
      // };

      SkyScenery.GeoJsonDataSource.load(url).then(function (dataSource) {
        viewer.dataSources.add(dataSource);
        var entities = dataSource.entities.values;
        for (var i = 0; i < entities.length; i++) {
          var entity = entities[i];
          if (entity.billboard) {
            entity.billboard = undefined;
            entity.billboard = new SkyScenery.BillboardGraphics({
              image: options.point.imgUrl,
              width: 50,
              height: 50,
              pixelOffset: new SkyScenery.Cartesian2(0, -25),
              heightReference: SkyScenery.HeightReference.CLAMP_TO_GROUND,
            });
          }
          if (entity.polyline) {
            entity.polyline.width = options.polyline.width;
            entity.polyline.material = SkyScenery.Color.fromCssColorString(
              options.polyline.color
            ).withAlpha(options.polyline.alpha); // 颜色
          }
          if (entity.polygon) {
            entity.polygon.height = 0.2;
            entity.polygon.outline = true; // 边框是否显示
            entity.polygon.outlineColor = SkyScenery.Color.fromCssColorString(
              options.polygon.outerColor
            ); // 边框颜色
            entity.polygon.outlineWidth = options.polygon.outerWidth; // 边框宽度
            entity.polygon.material = SkyScenery.Color.fromCssColorString(
              options.polygon.innerColor
            ).withAlpha(options.polygon.alpha); // 填充色
          }
        }
      });
    },

    /**
     * 加载动态围墙
     * options = {
     *    maxH: 100,
     *    color: "#00c4ff80",
     *    duration: 3000,
     * }
     */
    addDynamicWall(positions, options) {
      console.log("addDynamicWall", positions, options);
      return viewer.entities.add({
        name: "立体墙效果",
        wall: {
          positions: positions.map(function (item) {
            return SkyScenery.Cartesian3.fromDegrees(item[0], item[1]);
          }),
          // 设置高度
          maximumHeights: new Array(positions.length).fill(options.maxH || 100),
          minimumHeights: new Array(positions.length).fill(0),
          material: new SkyScenery.DynamicWallMaterialProperty({
            color: SkyScenery.Color.fromCssColorString(options.color || "#00c4ff80"), // "#"
            trailImage: "/static/image/color.png",
            duration: options.duration || 3000, // 3000
          }),
        },
      });
    },

    /**
     * 加载3Dtiles
     * @author LiuMengxiang
     * @param {*} url 3Dtiles的systemConfig.data3DTiles keys
     * @param {*} flyto 是否自动飞行到3Dtiles
     */
    async add3DTiles(keys, flyto) {
      let that = this;
      if (this.viewer3DTiles[keys]) {
        this.viewer3DTiles[keys].show = true;
        if (flyto) {
          viewer.zoomTo(this.viewer3DTiles[keys]);
        }
      } else {
        let option = {
          url: this.keysByOptions[keys].url + "/tileset.json",
          skipLevelOfDetail: true, //开启跳级加载
          maximumMemoryUsage: 1024, //最大内存占用  推荐显存的一般
          preferLeaves: true,
          maximumScreenSpaceError: 16,
          maximumNumberOfLoadedTiles: 2000,
        };

        // Common settings for the dynamicScreenSpaceError optimization
        // const tile = await SkyScenery.Cesium3DTileset.fromUrl(
        //   this.keysByOptions[keys].url + "/tileset.json",
        //   option
        // );
        var tile = new SkyScenery.Cesium3DTileset(option);
        // 可以通过viewer.scene来访问场景对象进行进一步设置
        viewer.scene.postProcessStages.fxaa.enabled = true; // 启用FXAA（快速近似抗锯齿）
        viewer.scene.primitives.add(tile);

        // // 设置相机视角
        // if (flyto) {
        //   viewer.zoomTo(tile);
        // }

        tile.readyPromise.then(function () {
          // 设置相机视角
          if (flyto) {
            viewer.zoomTo(tile);
          }
        });
        this.viewer3DTiles[keys] = tile;
        setTimeout(() => {
          this.update3DTilesStyleByKeys(
            this.viewer3DTiles[keys],
            Object.assign({}, this.keysByOptions[keys])
          );
        });
      }
    },
    /**
     * 修改3DTiles样式
     */
    update3DTilesStyleByKeys(tileset, options) {
      try {
        tileset.readyPromise.then(function () {
          // 设置样式
          var cartographic = SkyScenery.Cartographic.fromCartesian(
            tileset.boundingSphere.center
          );
          var lon = SkyScenery.Math.toDegrees(cartographic.longitude);
          var lat = SkyScenery.Math.toDegrees(cartographic.latitude);
          var height = cartographic.height;
          var surface = SkyScenery.Cartesian3.fromDegrees(lon, lat, height);
          var offset = SkyScenery.Cartesian3.fromDegrees(
            lon + options.lon,
            lat + options.lat,
            height + options.height
          );

          var translation = SkyScenery.Cartesian3.subtract(
            offset,
            surface,
            new SkyScenery.Cartesian3()
          );
          tileset.modelMatrix = SkyScenery.Matrix4.fromTranslation(translation);

          var m = tileset._root.transform;

          if (options.rx != 0) {
            const mx = SkyScenery.Matrix3.fromRotationX(
              SkyScenery.Math.toRadians(options.rx)
            );
            const rotate = SkyScenery.Matrix4.fromRotationTranslation(mx);
            SkyScenery.Matrix4.multiply(m, rotate, m);
          }

          if (options.ry != 0) {
            const my = SkyScenery.Matrix3.fromRotationY(
              SkyScenery.Math.toRadians(options.ry)
            );
            const rotate = SkyScenery.Matrix4.fromRotationTranslation(my);
            SkyScenery.Matrix4.multiply(m, rotate, m);
          }

          if (options.rz != 0) {
            const mz = SkyScenery.Matrix3.fromRotationZ(
              SkyScenery.Math.toRadians(options.rz)
            );
            const rotate = SkyScenery.Matrix4.fromRotationTranslation(mz);
            SkyScenery.Matrix4.multiply(m, rotate, m);
          }

          if (options.scale != 1) {
            const _scale = SkyScenery.Matrix4.fromUniformScale(options.scale);
            SkyScenery.Matrix4.multiply(m, _scale, m);
          }
          tileset._root.transform = m;
        });
      } catch (error) {
        console.error(error);
      }
    },
    /**
     * 修改3DTiles样式(测试)
     */
    update3DTilesStyle(keys, options) {
      if (this.viewer3DTiles[keys]) {
        let tileset = this.viewer3DTiles[keys];
        this.update3DTilesStyleByKeys(tileset, options);
      } else {
        console.log("update3DTilesStyle未找到3DTiles模型实例!keys:", keys);
      }
    },
    adjust3DTilesPosition(tileset, options) {
      var cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center);
      var lon = Cesium.Math.toDegrees(cartographic.longitude);
      var lat = Cesium.Math.toDegrees(cartographic.latitude);
      var height = cartographic.height;
      var surface = Cesium.Cartesian3.fromDegrees(lon, lat, height);
      var offset = Cesium.Cartesian3.fromDegrees(
        lon + options.lon,
        lat + options.lat,
        height + options.height
      );

      var translation = Cesium.Cartesian3.subtract(
        offset,
        surface,
        new Cesium.Cartesian3()
      );
      tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);

      // var m = Cesium.Transforms.eastNorthUpToFixedFrame(surface);
      var m = tileset._root.transform;

      if (options.rx != 0) {
        const mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(options.rx));
        const rotate = Cesium.Matrix4.fromRotationTranslation(mx);
        Cesium.Matrix4.multiply(m, rotate, m);
      }

      if (options.ry != 0) {
        const my = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(options.ry));
        const rotate = Cesium.Matrix4.fromRotationTranslation(my);
        Cesium.Matrix4.multiply(m, rotate, m);
      }

      if (options.rz != 0) {
        const mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(options.rz));
        const rotate = Cesium.Matrix4.fromRotationTranslation(mz);
        Cesium.Matrix4.multiply(m, rotate, m);
      }

      if (options.scale != 1) {
        const _scale = Cesium.Matrix4.fromUniformScale(options.scale);
        Cesium.Matrix4.multiply(m, _scale, m);
      }
      tileset._root.transform = m;
    },
    /**
     * 删除3DTiles
     * @author LiuMengxiang
     * @param tiles 3DTiles实例
     */
    remove3Dtiles(keys) {
      if (this.viewer3DTiles[keys]) {
        viewer.scene.primitives.remove(this.viewer3DTiles[keys]);
      }
    },
    /**
     * 隐藏3DTiles(测试)
     * @author LiuMengxiang
     * @param tiles 3DTiles实例
     */
    hide3DTiles(keys) {
      if (this.viewer3DTiles[keys]) {
        this.viewer3DTiles[keys].show = false;
      }
    },
    /**
     * 根据首页下拉框值判断3DTiles加载状态
     * @author LiuMengxiang
     * @param cascaderValue 首页
     */
    HomeHandleChangeCascader(cascaderValue) {
      if (this.$store.state.initMap) {
        // 暂存首页下拉框选中值
        let homeVs = [];
        cascaderValue.forEach((item) => {
          homeVs.push(item[0] + item[1]);
        });
        // 遍历所有的3Dtiles
        for (let keys in this.keysByOptions) {
          // 如果选中的话
          if (homeVs.length > 0 && homeVs.indexOf(keys) != -1) {
            this.add3DTiles(keys, true);
          } else {
            this.hide3DTiles(keys);
          }
        }
      } else {
        setTimeout(() => {
          this.HomeHandleChangeCascader(cascaderValue);
        }, 1000);
      }
    },
  },
};
</script>

<style lang="less" scoped>
#skysceneryContainer {
  width: 100%;
  height: 100%;
}
</style>
