<template>
  <div
    class="main"
    v-loading.fullscreen.lock="loading"
    element-loading-text="数据加载中..."
    element-loading-spinner="el-icon-loading"
    element-loading-background="rgba(0, 0, 0, 0.8)"
  >
    <div class="shadow-mask"></div>
    <!-- <local-camera
      :border="true"
      ref="groupViewPointCamera"
      video-data="lkqz_0"
      class="main-cameraVideo"
      :class="!boxesShow ? 'main-cameraVideoHidden' : ''"
    >
    </local-camera> -->
    <wMap :mapId="'situation-map'" ref="wMap" />
    <!--左右图表组件-->
    <message-boxes :show="boxesShow" />
    <!--图层切换按钮-->
    <layers-switch
      ref="switch"
      :show="boxesShow"
      @visibleChange="visibleChange"
      :class="[{ generalSwitch: boxesShow }, { rightSwitch: !boxesShow }]"
    />
  </div>
</template>

<script>
import wMap from "../../components/Standard/mapboxMap.vue";
import { initWs } from "../../utils/websocket";
import dict from "../../config/holo/dictionary";
import * as mapTools from "../../utils/mapboxTools";
import mapAssets from "../../config/holo/mapAssets";

import LayersSwitch from "./layersSwitch.vue";
import MessageBoxes from "./messageBoxes.vue";
import { getPasserbyPolygon } from "../../dao/api";
import SituationTime from "./situationTime.vue";
import CameraVideo from "../../components/Standard/cameraVideo.vue";
import LocalCamera from "../../components/Standard/localCamera.vue";

import vehicleDetail from "../mapComponents/generalVehicleDetail.vue";
const VehiclePopup = Vue.extend(vehicleDetail);
import cameraPopup from "./mapPopup/cameraPopup.vue";
const CameraPopup = Vue.extend(cameraPopup);

let map,
  licenseLabel = {},
  //---
  vehiclePopups = {},
  popupVises = {},
  vehiclePopupInstances = {},
  //---
  cameraPopups = {},
  cameraPopupInstances = {},
  vehicleModels = {},
  lastFrameTime = "",
  vehicleModelTypes = {};
export default {
  name: "home1",
  components: {
    LocalCamera,
    CameraVideo,
    SituationTime,
    wMap,
    MessageBoxes,
    LayersSwitch,
  },
  props: {},
  computed: {},
  data() {
    return {
      showMapTimer: null,

      loading: true,
      boxesShow: false,

      bounds: [],
      situationTimeVal: "",
      selectVehicle: null,
      lastLocation: [],
      sockets: [],
      licenseState: true,
      layerShowRenders: true,
      msgStart: true,
    };
  },
  watch: {},
  mounted() {
    this.initDictAndLoad();
  },
  methods: {
    setBigView() {
      map?.flyTo(map_config.alt1);
    },
    setSmallView() {
      let viewTimer = setInterval(() => {
        if (map) {
          map.flyTo(map_config.alt2);
          clearInterval(viewTimer);
        }
      }, 100);
    },
    showCrossCamera() {
      let allCameras = situation_intersectionGroups.cameras;
      mapTools.addOrUpdateHomeCameraLayer(
        map,
        "homeCameraLayer",
        allCameras,
        this.homeCameraLayerClick
      );
      if (map.getLayer("homeCameraLayer")) map.moveLayer("homeCameraLayer");
      for (let item of allCameras) {
        if (item.isShow) {
          this.homeCameraLayerClick({ features: [{ properties: item }] });
        }
      }
    },
    // 标记相机与行人区域
    getPasserbyPolygons() {
      getPasserbyPolygon().then((res) => {
        console.log("getPasserbyPolygon", res);
        let allCrossData = { waitingState: [] };
        for (let cross of res.content) {
          allCrossData.waitingState.push(...cross.waitingState);
        }
        console.log("all.....", allCrossData);
        mapTools.addOrUpdateWaitingPolygon(
          map,
          "waitingPolygon",
          allCrossData.waitingState
        );
        if (map.getLayer("vehicle3D")) map.moveLayer("vehicle3D");
        if (map.getLayer("vehiclePic")) map.moveLayer("vehiclePic");
      });
    },
    homeCameraLayerClick(e) {
      console.log("e", e.features);
      let prop = e.features[0].properties;
      let mark = prop.cameraName;
      cameraPopups[`popup${mark}`] = new mapboxgl.Popup({
        closeButton: true,
        closeOnClick: false,
        anchor: "top",
        offset: prop.offset || [0, 0],
        maxWidth: "none",
      });
      cameraPopups[`popup${mark}`]
        .setLngLat(prop.wkt.split(","))
        .setHTML(`<div id="home_camera_popup${mark}"></div>`)
        .addTo(map)
        .addClassName("groupCrossCamera");
      cameraPopupInstances[`popup${mark}`] = new CameraPopup({
        propsData: {
          model: prop,
        },
      });
      cameraPopupInstances[`popup${mark}`].$mount(`#home_camera_popup${mark}`);
      cameraPopups[`popup${mark}`].on("close", () => {
        cameraPopupInstances[`popup${mark}`]?.$destroy();
        delete cameraPopupInstances[`popup${mark}`];
        delete cameraPopups[`popup${mark}`];
      });
    },
    setMsgState(bool) {
      this.boxesShow = bool;
    },

    initDictAndLoad() {
      let needDicts = [
        "CarColor",
        "CarType",
        "PlateColor",
        "CrossInfo",
        "EventType",
      ];
      let queue = [];
      for (let item of needDicts) {
        queue.push(
          this.$store.dispatch("QUERY_DICT", {
            type: item,
          })
        );
      }
      Promise.all(queue).then(() => {
        this.init();
      });
    },
    init() {
      map = this.$refs.wMap.initMap();
      map.on("style.load", () => {
        this.loading = false;
        this.showMapTimer = setInterval(() => {
          if (map) {
            console.log(
              `center:[${map?.getCenter().lng},${
                map?.getCenter().lat
              }],zoom:${map?.getZoom()},bearing:${map?.getBearing()},pitch:${map?.getPitch()}`
            );
          }
        }, 5000);
        for (let key in mapAssets.mapIcons) {
          if (map) {
            map.loadImage(mapAssets.mapIcons[key], (error, image) => {
              if (map && !map.hasImage(key)) map.addImage(key, image);
            });
          }
        }
        map.addControl(
          new mapboxgl.NavigationControl({ showZoom: false }),
          "bottom-right"
        );
        this.refreshBounds();
        // document
        //   .getElementsByClassName("mapboxgl-ctrl-bottom-right")[0]
        //   .classList.add("mapboxgl-ctrl-bottom-right-hide-box");
        map.addLayer({
          id: "vehicle3D",
          type: "custom",
          renderingMode: "3d",
          onAdd: (map, mbxContext) => {
            window.tb = new Threebox(map, mbxContext, {
              defaultLights: true,
              enableSelectingObjects: true, //3D objects selection
            });
            for (let item of this.$store.state.dicts.CarType) {
              let targetType = dict.carTypeGlbMap[item.code];
              let options = {
                obj: `gltf/car${targetType}.glb`,
                type: "gltf",
                units: "meters",
                scale: 0.8,
                adjustment: { x: 0.5, y: 1, z: -0.5 },
                bbox: true,
              };
              window.tb.loadObj(options, (model) => {
                vehicleModelTypes[`car${item.code}`] = model;
              });
            }
          },
          render: function (gl, matrix) {
            window.tb.update();
          },
        });
        // 请求camera位置 标记图层 展示视频流
        this.getPasserbyPolygons();
        this.showCrossCamera();
        this.setBigView();
        this.initWebS();
      });
      map.on("zoomend", () => {
        this.refreshBounds();
      });
      map.on("moveend", () => {
        this.refreshBounds();
      });
    },
    initWebS() {
      // 注册车辆实时ws
      let socket = initWs({
        name: "callCar",
        url: ws_config.BASE_URL,
        callback: this.callCar,
      });
      socket.ws.onopen = () => {
        if (socket.ws.readyState === 1) {
          socket.ws.send('{ dataType: "BIG_SCREEN_GROUP_DATA"}');
          this.sockets.push(socket);
        }
      };
    },
    removeLayers(names) {
      if (map) {
        for (let layerId of names.split(",")) {
          if (map.getLayer(layerId)) {
            map.removeLayer(layerId);
          }
          if (map.getSource(layerId)) {
            map.removeSource(layerId);
          }
        }
      }
    },
    hideTb() {
      if (window.tb) {
        for (let key in vehicleModels) {
          window.tb.clear(key, true);
        }
        for (let key in licenseLabel) {
          window.tb.clear(key, true);
        }
        window.tb.update();
        vehicleModels = {};
        this.lastLocation = [];
        this.videoListData = [];
        this.currentNearestCrossId = "";
        this.modelsEmpty = true;
      }
    },
    clearLicense() {
      if (!this.licenseState) {
        for (let key in licenseLabel) {
          window.tb.clear(key, null);
        }
        licenseLabel = {};
      }
    },
    //---
    addVehicleLicenses(option) {
      if (option.picLicense) {
        let ele = document.createElement("div");
        ele.style.color = "white";
        ele.innerText = option.picLicense;
        ele.style.backgroundImage = `url('${
          mapAssets.mapIcons[`license${option.licenseColor}`]
        }')`;
        ele.style.backgroundSize = "100% 100%";
        ele.style.fontSize = "8px";
        ele.style.textAlign = "center";
        ele.style.padding = "2px 4px 8px 4px";
        let license = window.tb.label({
          htmlElement: ele,
          alwaysVisible: true,
          topMargin: 2,
        });
        license.setCoords([option.longitude, option.latitude, 4]);
        license.userData.data = { picLicense: option.picLicense };
        window.tb.add(license, `license${option.id}`);
        licenseLabel[`license${option.id}`] = license;
      }
    },
    // 选中模型改变
    onSelectedChangeVehicle(e) {
      if (e.detail.selected) {
        this.removeVehiclePopup();
        this.clearSelectVehicle();
        setTimeout(() => {
          this.selectVehicle = e.detail.userData.data;
          this.addCheckDetail(this.selectVehicle);
        }, 0);
      }
    },
    removeVehiclePopup() {
      for (let key in vehiclePopups) {
        vehiclePopups[key]?.remove();
      }
      vehiclePopups = {};
      popupVises = {};
      vehiclePopupInstances = {};
    },
    // 清理选中车辆数据及其对应的轨迹
    clearSelectVehicle() {},
    // 车辆详情弹窗内容
    addCheckDetail(data) {
      if (vehiclePopups[`popup${data.id}`]) {
        if (popupVises[`popup${data.id}`]) {
          vehiclePopups[`popup${data.id}`].setLngLat([
            data.longitude,
            data.latitude,
          ]);
          vehiclePopupInstances[`popup${data.id}`].$props.model = data;
        }
      } else {
        // 创建popup及初始化选中车辆轨迹
        vehiclePopups[`popup${data.id}`] = new mapboxgl.Popup({
          closeButton: true,
          anchor: "bottom",
          offset: [0, -20],
        });
        vehiclePopups[`popup${data.id}`]
          .setLngLat([data.longitude, data.latitude])
          .setHTML(`<div id="vehicle_popup${data.id}"></div>`)
          .addTo(map)
          .addClassName("vehicleDetailPopup");
        vehiclePopups[`popup${data.id}`].on("close", () => {
          vehiclePopups[`popup${data.id}`] = null;
          delete vehiclePopups[`popup${data.id}`];
          popupVises[`popup${data.id}`] = false;
          delete popupVises[`popup${data.id}`];
          this.clearSelectVehicle();
        });
        popupVises[`popup${data.id}`] = true;
        vehiclePopupInstances[`popup${data.id}`] = new VehiclePopup({
          propsData: {
            model: data,
          },
        });
        vehiclePopupInstances[`popup${data.id}`].$mount(
          `#vehicle_popup${data.id}`
        );
      }
    },
    //---

    callCar(msg) {
      lastFrameTime = new Date().getTime();
      let zoom = map?.getZoom();
      // 车牌号状态
      if (!this.licenseState && Object.keys(licenseLabel).length) {
        for (let key in licenseLabel) {
          window.tb.clear(key, null);
        }
        licenseLabel = {};
      }
      if (this.layerShowRenders) {
        // 筛选可见区域
        for (let i = 0; i < msg.length; i++) {
          if (!msg[i].picLicense) {
            msg[i].picLicense = "";
          }
          let pt = turf.point([msg[i].longitude, msg[i].latitude]);
          let poly = turf.polygon(this.bounds);
          if (!turf.booleanPointInPolygon(pt, poly)) {
            msg.splice(i, 1);
            i = i - 1;
          }
        }
        if (msg.length > 0) {
          if (
            this.lastLocation.length &&
            new Date(msg[0].dateTime).getTime() <
              new Date(this.lastLocation[0].dateTime).getTime()
          ) {
            this.$refs.groupViewPointCamera?.setTime();
          }
          if (this.msgStart) {
            this.$refs.groupViewPointCamera?.setTime();
            this.msgStart = false;
          }
          //   console.log("车辆总数", msg.length);
          // 第一帧 || 时间戳不相同 => 放行
          if (
            this.lastLocation.length === 0 ||
            this.lastLocation[0].dateTime !== msg[0].dateTime
          ) {
            this.situationTimeVal = msg[0].dateTime;
            // zoom 大于 18
            if (zoom >= 17) {
              this.removeLayers("vehiclePic,vehiclePoint");
            }
            // zoom 小于 18：隐藏 threebox ；大于17且小于18的部分使用图片图层 其余部分使用圆点
            if (zoom < 17) {
              this.hideTb();
              // if (zoom > 17) {
              //   this.removeLayers("vehiclePoint");
              //   mapTools.addOrUpdateVehiclePic(map, "vehiclePic", msg);
              // } else {
                this.clearLicense();
                this.removeLayers(
                  "lightLayer,lightLayerText,vehicleSelectWave,license,licenseBack,vehiclePic"
                );
                mapTools.addOrUpdateVehicle(map, "vehiclePoint", msg);
              // }
            }
            let allData = this.diff(this.lastLocation, msg);
            for (let item of allData) {
              // 如果选中车辆存在 则弹窗更新  否则删除弹窗
              if (this.selectVehicle && item.id === this.selectVehicle.id) {
                if (["add", "com"].includes(item.dill)) {
                  if (popupVises[`popup${item.id}`]) {
                    this.addCheckDetail(item);
                  }
                } else {
                  this.removeLayers("vehicleSelectWave");
                  this.removeVehiclePopup();
                  this.clearSelectVehicle();
                }
              }
              if (zoom > 17) {
                // 新增
                if (this.modelsEmpty) {
                  item.dill = "add";
                  this.modelsEmpty = false;
                }
                if (
                  item.dill === "add" ||
                  (item.dill === "com" && !vehicleModels[item.id])
                ) {
                  this.addVehicleModels(item);
                  if (this.licenseState) this.addVehicleLicenses(item);
                } else {
                  //   console.log("模型总数", Object.keys(vehicleModels).length);
                  for (let key in vehicleModels) {
                    if (vehicleModels[key].userData.data?.id === item.id) {
                      if (item.dill === "del") {
                        if (licenseLabel[`license${item.id}`]) {
                          window.tb.clear(`license${item.id}`, true);
                          delete licenseLabel[`license${item.id}`];
                        }
                        if (vehicleModels[key]) {
                          window.tb.clear(item.id, true);
                          delete vehicleModels[key];
                        }
                      }
                      if (item.dill === "com") {
                        // 车型中途变化 清除并重新创建
                        if (
                          vehicleModels[key].userData.data.originalType !==
                          item.originalType
                        ) {
                          if (vehicleModels[key]) {
                            window.tb.clear(item.id, true);
                            delete vehicleModels[key];
                          }
                          if (licenseLabel[`license${item.id}`]) {
                            window.tb.clear(`license${item.id}`, true);
                            delete licenseLabel[`license${item.id}`];
                          }
                          this.addVehicleModels(item);
                          if (this.licenseState) this.addVehicleLicenses(item);
                        } else {
                          if (licenseLabel[`license${item.id}`]) {
                            // 如果车牌model存在且未改变 则setCoords
                            if (
                              licenseLabel[`license${item.id}`].userData.data
                                .picLicense == item.picLicense
                            ) {
                              licenseLabel[`license${item.id}`].setCoords([
                                item.longitude,
                                item.latitude,
                                4,
                              ]);
                            }
                            // 否则先删除当前车牌 再创建更新后的车牌
                            else {
                              window.tb.clear(`license${item.id}`, true);
                              delete licenseLabel[`license${item.id}`];
                              this.addVehicleLicenses(item);
                            }
                          } else {
                            if (this.licenseState)
                              this.addVehicleLicenses(item);
                          }
                          this.setModel(vehicleModels[key], item, true);
                        }
                      }
                    }
                  }
                }
              }
            }
            this.lastLocation = msg;
          }
        }
      }
    },
    // 比较websocket车辆前后两次数据差异
    diff(oldData, newData) {
      // id 只在 newData 中存在且不在 oldData 中存在的即为 add
      const add = newData.filter((e) => !oldData.find((c) => c.id === e.id));
      // id 只在 oldData 中存在且不在 newData 中存在的即为 del
      const del = oldData.filter((e) => !newData.find((c) => c.id === e.id));
      const com = newData.filter((e) => oldData.find((c) => c.id === e.id));
      add.forEach((a) => (a.dill = "add"));
      del.forEach((d) => (d.dill = "del"));
      com.forEach((c) => (c.dill = "com"));
      return [...add, ...del, ...com];
    },
    // 更新经纬度-角度-详细信息-弹窗信息
    setModel(model, options, setColor) {
      if (setColor) {
        model.traverse((child) => {
          if (child.isMesh && child.name.includes("_19")) {
            child.material = child.material.clone();
            let colorDesc = this.$store.state.dicts.CarColor.find((item) => {
              return item.code == options.originalColor;
            });
            let realColor = colorDesc
              ? dict.colorMatch[colorDesc.name]
              : "#fff";
            child.material.color.set(realColor);
          }
        });
      }
      model.setCoords([options.longitude, options.latitude]);
      model.userData.data = options;
      model.setRotation({ x: 90, y: 360 - options.courseAngle - 90, z: 0 });
    },
    addVehicleModels(option) {
      if (vehicleModelTypes[`car${option.originalType}`]) {
        let model = vehicleModelTypes[`car${option.originalType}`].duplicate();
        this.setModel(model, option, true);
        model.addEventListener(
          "SelectedChange",
          this.onSelectedChangeVehicle,
          false
        );
        vehicleModels[option.id] = model;
        window.tb.add(model, option.id);
      }
    },
    refreshBounds() {
      let mapBounds = map.getBounds();
      let leftDownXy = [mapBounds._sw.lng, mapBounds._sw.lat];
      let rightUpXy = [mapBounds._ne.lng, mapBounds._ne.lat];
      let mid1 = [mapBounds._sw.lng, mapBounds._ne.lat];
      let mid2 = [mapBounds._ne.lng, mapBounds._sw.lat];
      this.bounds = [[leftDownXy, mid1, rightUpXy, mid2, leftDownXy]];
    },
    // 根据 name 关闭 websocket
    closeWs(name) {
      return new Promise((resolve) => {
        for (let key in this.sockets) {
          if (this.sockets[key].name === name) {
            this.sockets[key].ws.onclose = () => {
              this.sockets.splice(key, 1);
              resolve();
            };
            this.sockets[key].ws.close();
          }
        }
        resolve();
      });
    },
    closeAllWs() {
      this.layerShowRenders = false;
      const closePromises = this.sockets.map((socket, index) => {
        return new Promise((resolve) => {
          if (socket.ws.readyState !== 1) {
            resolve();
          } else {
            socket.ws.onclose = () => {
              resolve();
            };
            socket.ws.close();
          }
        });
      });
      return Promise.all(closePromises).then(() => {
        // for (let key in this.layers) {
        //   for (let layer of this.layers[key]) {
        //     this.removeLayers(layer);
        //   }
        // }
        this.sockets = [];
      });
    },

    visibleChange() {
      this.boxesShow = !this.boxesShow;
    },
  },
  beforeDestroy() {
    if (this.showMapTimer) {
      clearInterval(this.showMapTimer);
    }
    this.closeAllWs();
    window.tb.dispose();
    window.tb = null;
    map = null;
  },
};
</script>

<style lang="less" scoped>
.rightSwitch {
  left: 15px;
  transition: 0.5s all ease;
}

.generalSwitch {
  left: 545px;
  transition: 0.5s all ease;
}

.legendsGeneral {
  right: 730px;
  position: absolute;
  bottom: 8px;
  transition: 0.5s all ease;
  z-index: 11;
}

.legendsHidden {
  right: 20px;
}

.main {
  height: 100%;
  position: relative;
}
.shadow-mask {
  position: absolute;
  width: 100%;
  height: 100%;
  left: 0;
  top: 0;
  z-index: 9;
  pointer-events: none;
  // background: linear-gradient(
  //     180deg,
  //     rgba(0, 0, 0, 0.01) 0%,
  //     rgba(0, 0, 0, 0.3) 100%
  //   ),
  //   radial-gradient(50% 48.61%, rgba(0, 0, 0, 0.01) 0%, rgba(0, 0, 0, 0.2) 100%);
}

.timeCenter {
  left: 50%;
  transform: translateX(-50%);
  top: 0;
}

.main-cameraVideo {
  position: absolute;
  width: 400px;
  height: 300px;
  right: 550px;
  bottom: 30px;
  z-index: 11;
  transition: 0.5s all ease;
}

.main-cameraVideoHidden {
  transition: 0.5s all ease;

  right: 30px;
}
</style>
<style lang="less">
.groupCrossCamera .mapboxgl-popup-close-button {
  right: 4px;
}
.mapboxgl-ctrl-bottom-right {
  bottom: 20px !important;
  right: 688px !important;
  z-index: 11 !important;
  transition: 0.5s all ease;
}

.mapboxgl-ctrl-bottom-right-hide-box {
  right: 20px !important;
  transition: 0.5s all ease;
}

.videoItem {
  display: flex;
  align-items: center;
  overflow: hidden;
}

.mapboxgl-ctrl-group {
  background-color: transparent !important;
  border-radius: 6px;
}

.mapboxgl-ctrl-icon {
  filter: drop-shadow(#cccccc 10000px 0);
  transform: translateX(-10000px);
}

.mapboxgl-ctrl-group button + button {
  border-top: unset;
}

.mapboxgl-ctrl button.mapboxgl-ctrl-compass .mapboxgl-ctrl-icon {
  background-image: url("../../assets/images/sc/mapArrow.png") !important;
  background-size: 100% 100%;
}

.mapboxgl-ctrl-compass {
  width: 124px !important;
  height: 132px !important;
}
</style>
