<template>
  <div class="app-container home">
    <!-- Cesium地图容器 -->
    <div id="cesiumContainer" class="cesium-container"></div>

    <!-- 人员实时追踪控制面板 -->
    <div class="tracking-panel">
      <div class="panel-header">
        <h3>人员实时追踪</h3>
        <select v-model="selectedPerson" @change="onPersonSelect">
          <option value="">选择人员</option>
          <option
            v-for="person in personnelList"
            :key="person.perName"
            :value="person.perName"
          >
            {{ person.perName }}
          </option>
        </select>
      </div>

      <!-- 时间轴组件 -->
      <div class="timeline-container">
        <div class="time-info">
          <span>当前时间: {{ currentTimeDisplay }}</span>
        </div>
        <input
          type="range"
          v-model.number="currentTimeIndex"
          :min="0"
          :max="timePoints.length - 1"
          @input="onTimelineChange"
          class="timeline-slider"
        />
        <div class="time-labels">
          <span>{{ formatTime(timePoints[0]) }}</span>
          <span>{{ formatTime(timePoints[timePoints.length - 1]) }}</span>
        </div>
      </div>

      <!-- 控制面板按钮 -->
      <div class="control-buttons">
        <button @click="startTracking" :disabled="isTracking">开始追踪</button>
        <button @click="stopTracking" :disabled="!isTracking">停止追踪</button>
        <button @click="showFullPath">显示完整轨迹</button>
        <button @click="clearTrails">清除轨迹</button>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "Index",
  data() {
    return {
      // 版本号
      version: "3.8.9",
      // Cesium查看器实例
      viewer: null,
      tileset: null,
      personnelList: [],
      personModelInterval: null,
      trackingInterval: null,
      bgEntities: {}, // 所有的key都对应一个实体对象。而人员的实体对应的key不是数字。

      // 轨迹追踪相关数据
      selectedPerson: "", // 选中的人员
      timePoints: [], // 时间点数组
      currentTimeIndex: 0, // 当前时间索引
      personTrajectories: {}, // 人员轨迹数据 { 人员名称: [{time, lng, lat, height}] }
      trailEntities: {}, // 轨迹实体
      isTracking: false, // 是否正在实时追踪
      currentTimeDisplay: "", // 当前显示时间
    };
  },
  mounted() {
    // 组件挂载后初始化地图
    this.initCesium();
    // 初始化时间点数据
    this.initTimePoints();
  },
  beforeDestroy() {
    // 组件销毁前清理地图资源
    if (this.viewer) {
      this.viewer.destroy();
      this.viewer = null;
    }
    if (this.personModelInterval) {
      clearInterval(this.personModelInterval);
    }
    if (this.trackingInterval) {
      clearInterval(this.trackingInterval);
    }
  },
  methods: {
    // 新增：清除实体
    clearEntities() {
      if (this.viewer && this.bgEntities) {
        for (let key in this.bgEntities) {
          this.viewer.entities.remove(this.bgEntities[key]);
          delete this.bgEntities[key];
        }
      }
    },
    // 初始化时间点数据（生成过去1小时的时间点，每5分钟一个）
    initTimePoints() {
      const now = new Date();
      const points = [];

      // 生成过去1小时的时间点，每5分钟一个
      for (let i = 60; i >= 0; i -= 5) {
        const time = new Date(now.getTime() - i * 60 * 1000);
        points.push(time);
      }

      this.timePoints = points;
      this.currentTimeIndex = points.length - 1; // 默认显示最新时间
      this.currentTimeDisplay = this.formatTime(points[points.length - 1]);

      // 初始化人员轨迹数据
      this.initPersonTrajectories();
    },

    // 初始化人员轨迹数据
    initPersonTrajectories() {
      // 将笛卡尔坐标转换为经纬度坐标作为基准点
      const cartographic = Cesium.Cartographic.fromCartesian({
        x: -2686273.730145489,
        y: 4293961.185794622,
        z: 3863430.5618300107,
      });
      const baseLongitude = Cesium.Math.toDegrees(cartographic.longitude);
      const baseLatitude = Cesium.Math.toDegrees(cartographic.latitude);
      const baseHeight = cartographic.height + 1;

      // 为每个人生成轨迹数据
      this.personnelList.forEach((person) => {
        const trajectories = [];
        let currentLng = baseLongitude + (Math.random() - 0.5) * 0.0001;
        let currentLat = baseLatitude + (Math.random() - 0.5) * 0.0001;

        this.timePoints.forEach((time) => {
          // 生成平滑的移动路径
          currentLng += (Math.random() - 0.5) * 0.00002;
          currentLat += (Math.random() - 0.5) * 0.00002;

          trajectories.push({
            time,
            lng: currentLng,
            lat: currentLat,
            height: baseHeight,
          });
        });

        this.personTrajectories[person.perName] = trajectories;
      });
    },

    // 格式化时间显示
    formatTime(date = new Date()) {
      const hours = date.getHours().toString().padStart(2, "0");
      const minutes = date.getMinutes().toString().padStart(2, "0");
      return `${hours}:${minutes}`;
    },

    // 人员选择变化处理
    onPersonSelect() {
      this.clearTrails();
      if (this.selectedPerson) {
        this.updatePersonPositionByTimeIndex(this.currentTimeIndex);
        this.showFullPath();
      }
    },

    // 时间轴变化处理
    onTimelineChange() {
      this.currentTimeDisplay = this.formatTime(
        this.timePoints[this.currentTimeIndex]
      );
      this.updatePersonPositionByTimeIndex(this.currentTimeIndex);
    },

    // 根据时间索引更新人员位置
    updatePersonPositionByTimeIndex(index) {
      if (
        !this.selectedPerson ||
        !this.personTrajectories[this.selectedPerson]
      ) {
        return;
      }

      const trajectory = this.personTrajectories[this.selectedPerson][index];
      if (!trajectory) return;

      // 更新人员实体位置
      const personEntity = this.bgEntities[this.selectedPerson];
      if (personEntity) {
        const position = Cesium.Cartesian3.fromDegrees(
          trajectory.lng,
          trajectory.lat,
          trajectory.height
        );
        personEntity.position.setValue(position);

        // 更新描述信息，包含时间
        personEntity.description = `<div><h4>${
          this.selectedPerson
        }</h4><p>时间: ${this.formatTime(trajectory.time)}</p></div>`;
      }

      // 移动相机到人员位置
      if (this.isTracking) {
        this.viewer.camera.flyTo({
          destination: Cesium.Cartesian3.fromDegrees(
            trajectory.lng,
            trajectory.lat,
            trajectory.height + 100
          ),
          duration: 0.5,
        });
      }
    },

    // 开始实时追踪
    startTracking() {
      if (!this.selectedPerson) {
        alert("请先选择要追踪的人员");
        return;
      }

      this.isTracking = true;
      this.currentTimeIndex = this.timePoints.length - 1;

      // 设置定时器模拟时间流逝
      this.trackingInterval = setInterval(() => {
        // 模拟新时间点的到来
        const now = new Date();
        this.timePoints.push(now);

        // 为每个人员生成新的位置数据
        this.personnelList.forEach((person) => {
          if (!this.personTrajectories[person.perName]) {
            this.personTrajectories[person.perName] = [];
          }

          const lastPos =
            this.personTrajectories[person.perName][
              this.personTrajectories[person.perName].length - 1
            ];
          let newLng = lastPos.lng + (Math.random() - 0.5) * 0.00002;
          let newLat = lastPos.lat + (Math.random() - 0.5) * 0.00002;

          this.personTrajectories[person.perName].push({
            time: now,
            lng: newLng,
            lat: newLat,
            height: lastPos.height,
          });
        });

        // 更新到最新时间
        this.currentTimeIndex = this.timePoints.length - 1;
        this.currentTimeDisplay = this.formatTime(now);
        this.updatePersonPositionByTimeIndex(this.currentTimeIndex);

        // 如果选择了当前人员，显示最新轨迹
        if (this.selectedPerson) {
          this.updateTrailDisplay();
        }
      }, 5000); // 每5秒更新一次
    },

    // 停止实时追踪
    stopTracking() {
      this.isTracking = false;
      if (this.trackingInterval) {
        clearInterval(this.trackingInterval);
        this.trackingInterval = null;
      }
    },

    // 显示完整轨迹
    showFullPath() {
      if (
        !this.selectedPerson ||
        !this.personTrajectories[this.selectedPerson]
      ) {
        return;
      }

      this.clearTrails();
      this.updateTrailDisplay();
    },

    // 更新轨迹显示
    updateTrailDisplay() {
      const trajectories = this.personTrajectories[this.selectedPerson];
      if (!trajectories || trajectories.length < 2) return;

      // 创建轨迹点数组
      const positions = [];
      trajectories.forEach((point) => {
        positions.push(
          Cesium.Cartesian3.fromDegrees(point.lng, point.lat, point.height)
        );
      });

      // 创建轨迹线
      const trailEntity = this.viewer.entities.add({
        polyline: {
          positions: positions,
          width: 3,
          material: new Cesium.PolylineGlowMaterialProperty({
            glowPower: 0.5,
            color: Cesium.Color.YELLOW,
          }),
          clampToGround: false,
        },
      });

      this.trailEntities[this.selectedPerson] = trailEntity;

      // 添加轨迹点标记
      trajectories.forEach((point, index) => {
        // 只显示部分点，避免过多标记影响性能
        if (
          index % Math.ceil(trajectories.length / 10) === 0 ||
          index === trajectories.length - 1
        ) {
          const pointEntity = this.viewer.entities.add({
            position: Cesium.Cartesian3.fromDegrees(
              point.lng,
              point.lat,
              point.height + 5
            ),
            point: {
              pixelSize: 5,
              color:
                index === trajectories.length - 1
                  ? Cesium.Color.RED
                  : Cesium.Color.GREEN,
              outlineColor: Cesium.Color.WHITE,
              outlineWidth: 2,
            },
            description: `<div><p>时间: ${this.formatTime(
              point.time
            )}</p></div>`,
          });

          if (!this.trailEntities[`${this.selectedPerson}_point_${index}`]) {
            this.trailEntities[`${this.selectedPerson}_point_${index}`] =
              pointEntity;
          }
        }
      });
    },

    // 清除轨迹
    clearTrails() {
      for (let key in this.trailEntities) {
        this.viewer.entities.remove(this.trailEntities[key]);
      }
      this.trailEntities = {};
    },

    // 1. 提取通用实体创建函数
    createEntity(item, type) {
      const isPerson = type === "person";
      const idField = isPerson ? "perName" : "vehicleName";
      const labelColor = isPerson ? Cesium.Color.YELLOW : Cesium.Color.CYAN;
      const iconPath = isPerson
        ? "/poi-marker-default.png"
        : "/poi-marker-vehicle.png";

      let lng = Number(item.lng);
      let lat = Number(item.lat);
      let height = Number(item.height);
      let position = Cesium.Cartesian3.fromDegrees(lng, lat, height);

      console.log(item[idField], position);

      // 创建实体
      let entity = this.viewer.entities.add({
        position: position,
        label: {
          text: item[idField],
          font: "16px",
          backgroundColor: Cesium.Color.fromCssColorString("#173349"),
          showBackground: true,
          fillColor: labelColor,
          depthTestAgainstTerrain: false,
          pixelOffset: new Cesium.Cartesian2(0, -35),
        },
        billboard: {
          image: iconPath,
          scale: 0.5,
          heightReference: Cesium.HeightReference.CLAMP_TO_3D_TILE,
        },
        description: `<div><h4>${item[idField]}${item.status}</h4></div>`,
        fixedFrame: Cesium.Transforms.eastNorthUpToFixedFrame(position),
      });

      entity.info = item;
      entity.type = type;
      this.bgEntities[item[idField]] = entity;

      return entity;
    },

    // 2. 提取实体更新函数
    updateEntity(entity, item) {
      let position = Cesium.Cartesian3.fromDegrees(
        item.lng,
        item.lat,
        item.height
      );
      entity.position.setValue(position);
      entity.fixedFrame = Cesium.Transforms.eastNorthUpToFixedFrame(position);
    },

    // 3. 提取批量创建实体的函数
    createEntities(entityList, type) {
      const isPerson = type === "person";
      const idField = isPerson ? "perName" : "vehicleName";

      for (let item of entityList) {
        this.createEntity(item, type);
      }
    },

    // 4. 提取批量更新实体的函数（增量更新模式）
    updateEntities(entityList, type) {
      const isPerson = type === "person";
      const idField = isPerson ? "perName" : "vehicleName";

      for (let item of entityList) {
        let entity = this.bgEntities[item[idField]];
        if (entity && entity.type === type) {
          // 更新现有实体
          this.updateEntity(entity, item);
        } else {
          // 创建新实体
          this.createEntity(item, type);
        }
      }
    },

    // 5. 提取定时器逻辑为可重用函数
    setupEntityUpdateInterval(type, dataGenerator, interval = 10000) {
      // 清除现有定时器
      if (this.intervaler) {
        clearInterval(this.intervaler);
        this.intervaler = null;
      }

      // 设置新的定时器
      this.intervaler = setInterval(() => {
        console.log(`开始获取实时${type === "person" ? "人员" : "车辆"}数据`);

        // 生成或获取最新数据
        if (typeof dataGenerator === "function") {
          dataGenerator();
        }

        const entityList =
          type === "person" ? this.personnelList : this.vehicleList;

        // 更新实体（这里可以选择清除重建或增量更新）
        // 方案1：清除所有实体后重建
        this.clearEntities();
        this.createEntities(entityList, type);

        // 方案2：增量更新（推荐，性能更好）
        // this.updateEntities(entityList, type);
      }, interval);
    },

    createPersonModel() {
      // 清除现有定时器
      if (this.personModelInterval) {
        clearInterval(this.personModelInterval);
        this.personModelInterval = null;
      }

      // 清除现有实体
      this.clearEntities();

      // 立即生成并显示人员实体
      console.log("立即创建人员实体");
      this.personCardList((list) => {
        console.log("人员数据", this.personnelList);
        this.createEntities(this.personnelList, "person");
      });

      // 设置定时刷新
      this.setupEntityUpdateInterval("person", () => {
        this.personCardList(() => {
          console.log("人员数据", this.personnelList);
        });
      });

      // this.personModelInterval = setInterval(() => {
      //   console.log("开始获取实时数据");
      //   if (this.bgEntities) {
      //     for (let key in this.bgEntities) {
      //       if (isNaN(parseFloat(key))) {
      //         // 非数字键名的是人员实体
      //         this.viewer.entities.remove(this.bgEntities[key]);
      //         delete this.bgEntities[key];
      //       }
      //     }
      //   }

      //   // 从API获取最新的人员定位数据
      //   this.personCardList((list) => {
      //     console.log("人员数据", this.personnelList);
      //     // 创建新实体
      //     for (let item of this.personnelList) {
      //       let lng = Number(item.lng);
      //       let lat = Number(item.lat);
      //       let height = Number(item.height);
      //       let position = Cesium.Cartesian3.fromDegrees(lng, lat, height);
      //       console.log(item.perName, position);
      //       // 创建人员标记
      //       let entity = this.viewer.entities.add({
      //         position: position,
      //         label: {
      //           text: item.perName,
      //           font: "16px",
      //           backgroundColor: Cesium.Color.fromCssColorString("#173349"),
      //           showBackground: true,
      //           fillColor: Cesium.Color.YELLOW,
      //           depthTestAgainstTerrain: false, // 禁用地形深度测试
      //           pixelOffset: new Cesium.Cartesian2(0, -35),
      //         },
      //         billboard: {
      //           image: "/poi-marker-default.png",
      //           scale: 0.5,
      //         },
      //         description: `<div><h4>${item.perName}${item.status}</h4></div>`,
      //         fixedFrame: Cesium.Transforms.eastNorthUpToFixedFrame(position),
      //       });
      //       entity.info = item; // 添加 info 属性
      //       this.bgEntities[item.perName] = entity; // 存储新实体
      //     }

      //     // 如果已经选择了人员，更新其位置和轨迹
      //     if (this.selectedPerson) {
      //       this.updatePersonPositionByTimeIndex(this.currentTimeIndex);
      //     }
      //   });
      // }, 10000); // 每10秒刷新一次
    },

    personCardList(fn) {
      // 将笛卡尔坐标转换为经纬度坐标
      const cartographic = Cesium.Cartographic.fromCartesian({
        x: -2686273.730145489,
        y: 4293961.185794622,
        z: 3863430.5618300107,
      });
      const baseLongitude = Cesium.Math.toDegrees(cartographic.longitude);
      const baseLatitude = Cesium.Math.toDegrees(cartographic.latitude);
      const baseHeight = cartographic.height + 1;

      console.log("人员经纬度基准点:", {
        longitude: baseLongitude,
        latitude: baseLatitude,
        height: baseHeight,
      });

      // 清除现有的人员列表
      this.personnelList = [];

      // 生成10个不同的经纬度坐标
      const maxOffset = 0.00005;

      for (let index = 0; index < 10; index++) {
        // 生成随机偏移量
        const lngOffset = (Math.random() - 0.5) * 2 * maxOffset;
        const latOffset = (Math.random() - 0.5) * 2 * maxOffset;

        this.personnelList.push({
          lng: baseLongitude + lngOffset,
          lat: baseLatitude + latOffset,
          height: baseHeight,
          perName: "张三" + index,
          status: "online", // 在线
          avatar: "/static/images/avatars/zhangsan.png", // 头像
        });
      }

      // 初始化轨迹数据（如果尚未初始化）
      if (Object.keys(this.personTrajectories).length === 0) {
        this.initPersonTrajectories();
      }

      fn(this.personnelList);
    },

    /**
     * 初始化Cesium地图
     */
    async initCesium() {
      Cesium.Ion.defaultAccessToken =
        "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0ZDAxZGFhYy02MjJlLTRiNzktODNhZi00N2VjZGY0NTk4YmIiLCJpZCI6Mjc0NDAxLCJpYXQiOjE3NjMzNDYwNTR9.ZQW2DZ4KaMGbHuwrtIbyI6EdSSvgMJUHmmD74eZW7PQ";
      try {
        // 创建Cesium Viewer实例
        this.viewer = new Cesium.Viewer("cesiumContainer", {
          // 设置地图提供者，这里使用默认的Bing Maps
          imageryProvider: new Cesium.BingMapsImageryProvider({
            url: "https://dev.virtualearth.net",
            key: "AgcbDCAOb9zMfquaT4Z-MdHfx--9wUNrLRiiS7rIElFx8f-4lLulxZ0QnhqX5Lm6",
            mapStyle: Cesium.BingMapsStyle.AERIAL,
          }),
          // 配置是否显示各种控件
          animation: false, // 动画控件
          baseLayerPicker: true, // 底图选择器
          fullscreenButton: false, // 全屏按钮
          geocoder: false, // 地址搜索
          homeButton: false, // 主页按钮
          infoBox: false, // 信息框
          sceneModePicker: false, // 场景模式选择器
          selectionIndicator: false, // 选择指示器
          timeline: false, // 时间线
          navigationHelpButton: false, // 导航帮助按钮
          navigationInstructionsInitiallyVisible: false,
          // 设置初始视图位置
          center: Cesium.Cartesian3.fromDegrees(104.06, 30.67, 10000000),
        });

        this.viewer.scene.camera.setView({
          // 视角-环翠
          duration: 1,
          destination: {
            x: -2739843.563038797,
            y: 4357442.794747324,
            z: 3880768.3292693933,
          },
          orientation: {
            heading: 6.037000745578596,
            pitch: -1.2499586064720978,
            roll: 0.000005306352659495417,
          },
        });

        // 隐藏Cesium logo
        this.viewer._cesiumWidget._creditContainer.style.display = "none";

        const VUE_APP_GIS =
          "http://192.168.2.11:8080/Apps/assets/media/gaoquyingji";
        try {
          const tileset = await Cesium.Cesium3DTileset.fromUrl(
            VUE_APP_GIS + "/tiles/01_guanwei/tileset.json"
          );
          this.viewer.scene.primitives.add(tileset);

          console.log("倾斜摄影模型加载成功tileset", tileset);

          if (tileset) {
            this.tileset = tileset;
            this.locateToTileset();
          }
        } catch (error) {
          console.error(`加载倾斜摄影模型失败: ${error}`);
        }

        console.log("Cesium地图初始化成功");
      } catch (error) {
        console.error("Cesium地图初始化失败:", error);
      }
    },

    /**
     * 获取倾斜摄影模型的经纬度并将摄像机视角转向模型上方
     */
    locateToTileset() {
      if (!this.tileset || !this.viewer) {
        console.error("模型或视图未准备就绪");
        return;
      }

      try {
        // 获取模型的边界球
        const boundingSphere = this.tileset.boundingSphere;

        if (!boundingSphere) {
          console.error("无法获取模型边界");
          return;
        }

        // 获取模型中心点的笛卡尔坐标
        const center = boundingSphere.center;

        // 将笛卡尔坐标转换为经纬度坐标
        const cartographic = Cesium.Cartographic.fromCartesian(center);
        const longitude = Cesium.Math.toDegrees(cartographic.longitude);
        const latitude = Cesium.Math.toDegrees(cartographic.latitude);
        const height = cartographic.height;

        console.log("倾斜摄影模型中心点经纬度:", {
          longitude: longitude,
          latitude: latitude,
          height: height,
        });

        // 计算合适的观察距离 - 基于模型半径的倍数
        const distance = boundingSphere.radius * 2.5; // 可以根据需要调整倍数

        // 设置相机位置在模型上方
        const cameraPosition = Cesium.Cartesian3.fromRadians(
          cartographic.longitude,
          cartographic.latitude,
          height + distance // 相机高度为模型最高点加上观察距离
        );

        // 计算相机看向模型中心的方向
        const heading = Cesium.Math.toRadians(0); // 方向角
        const pitch = Cesium.Math.toRadians(-90); // 俯仰角 - 负数表示向下看
        const roll = Cesium.Math.toRadians(0); // 翻滚角

        // 使用flyTo方法平滑过渡到目标位置
        this.viewer.camera.flyTo({
          destination: cameraPosition,
          orientation: {
            heading: heading,
            pitch: pitch,
            roll: roll,
          },
          duration: 2, // 过渡时间2秒
          complete: () => {
            console.log("相机已成功定位到模型上方");
            this.createPersonModel(); // 定位后创建人员模型
          },
        });
      } catch (error) {
        console.error("定位到模型上方失败:", error);
      }
    },
  },
};
</script>

<style scoped lang="scss">
.home {
  width: 100%;
  height: 100vh;
  position: relative;
  overflow: hidden;

  font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 13px;
  color: #676a6c;
  overflow-x: hidden;

  .update-log {
    ol {
      display: block;
      list-style-type: decimal;
      margin-block-start: 1em;
      margin-block-end: 1em;
      margin-inline-start: 0;
      margin-inline-end: 0;
      padding-inline-start: 40px;
    }
  }

  // Cesium容器样式
  .cesium-container {
    width: 87vw;
    height: 87vh;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
  }

  // 追踪控制面板样式
  .tracking-panel {
    position: absolute;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%);
    width: 80%;
    background: rgba(0, 0, 0, 0.8);
    border-radius: 8px;
    padding: 15px;
    color: white;
    z-index: 100;

    .panel-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 15px;

      h3 {
        margin: 0;
        font-size: 18px;
      }

      select {
        padding: 5px 10px;
        border-radius: 4px;
        border: none;
        background: #333;
        color: white;
      }
    }

    .timeline-container {
      margin-bottom: 15px;

      .time-info {
        margin-bottom: 10px;
        text-align: center;
      }

      .timeline-slider {
        width: 100%;
        margin-bottom: 10px;
      }

      .time-labels {
        display: flex;
        justify-content: space-between;
        font-size: 12px;
      }
    }

    .control-buttons {
      display: flex;
      justify-content: center;
      gap: 10px;

      button {
        padding: 8px 16px;
        border-radius: 4px;
        border: none;
        background: #173349;
        color: white;
        cursor: pointer;

        &:hover:not(:disabled) {
          background: #1e4763;
        }

        &:disabled {
          background: #555;
          cursor: not-allowed;
        }
      }
    }
  }
}
</style>