<template>
  <div v-drag="{ draggable: true, scale: containerScale, handle: '.rankIcon' }" class="time-axis-container">
    <div class="expand-btn" @click="changeExpand">{{ timeAxisState.expand ? '收起' : '展开' }}</div>
    <div v-show="timeAxisState.expand" class="time-box">
      <div class="time-picker-box">
        <el-date-picker
          v-model="timeAxisState.startTime"
          type="datetime"
          :editable="false"
          :format="timeAxisState.format"
          :value-format="timeAxisState.format"
          :clearable="false"
        />
        <el-date-picker
          v-model="timeAxisState.endTime"
          type="datetime"
          :editable="false"
          :format="timeAxisState.format"
          :value-format="timeAxisState.format"
          :clearable="false"
        />
      </div>
      <div class="time-list-box">
        <el-timeline>
          <el-timeline-item
            v-for="(activity, index) in timeAxisState.data"
            :key="index"
            :ref="(el) => (timelineItems[index] = el)"
            :class="timeAxisState.activeIndex === index ? 'active' : ''"
            :timestamp="activity.time"
          />
        </el-timeline>
      </div>
      <div class="time-tool">
        <div class="prevIcon" @click="toPrevTime" />
        <div class="playIcon" @click="toPlayTime" />
        <div class="nextIcon" @click="toNextTime(true)" />
        <div class="speed-btn" @click="changeSpeed">{{ timeAxisState.speed === 2 ? 'x1' : 'x2' }}</div>
        <div class="rankIcon" />
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup name="TimeAxis">
import { parseTime } from '@/utils/ruoyi';
import carImg from '@/assets/images/car.png';
import VectorSource from 'ol/source/Vector';
import Feature from 'ol/Feature';
import Point from 'ol/geom/Point';
import Icon from 'ol/style/Icon';
import Style from 'ol/style/Style';
import { LineString } from 'ol/geom';
import VectorLayer from 'ol/layer/Vector';
import { Stroke } from 'ol/style';
import arrowImg from '@/assets/images/arrow.png';

const props = defineProps({
  activeMap: String
});
const containerScale = inject('containerScale');
const getMapUtils = inject('getMapUtils');

const AMapType = ['vectorgraph', 'satellite'];
let mapUtils, map, AMap;
// 轨迹数据
let moveMarker, movePassedPolyline, movePolyline;
let isNewMarkerPause = false;
let trackPathArr = [];
const timelineItems = ref([]);
const timeAxisState = reactive({
  expand: false,
  type: '',
  format: 'YYYY-MM-DD HH:mm',
  startTime: '',
  endTime: '',
  activeIndex: -1,
  playing: false,
  show: false,
  showDialog: false,
  speed: 2,
  data: []
});
let originalData = [];

// 展开收起
const changeExpand = () => {
  timeAxisState.expand = !timeAxisState.expand;
};

// 设置初始时间
const getInitTime = () => {
  // 获取当前时间
  const now = new Date();
  timeAxisState.endTime = parseTime(now.getTime(), '{y}-{m}-{d} {h}:{i}');
  // 计算12小时前的时间
  now.setHours(now.getHours() - 12);
  timeAxisState.startTime = parseTime(now.getTime(), '{y}-{m}-{d} {h}:{i}');
};

// 返回上一个时间点
const toPrevTime = () => {
  if (timeAxisState.type === 'track') {
    prevPauseTime();
  }
};

// 播放
const toPlayTime = () => {
  timeAxisState.playing = !timeAxisState.playing;
  if (timeAxisState.type === 'track') {
    playOrPauseTrack();
  }
};

// 前往下一个时间点
const toNextTime = (flag?: boolean) => {
  if (timeAxisState.type === 'track') {
    nextPauseTime();
  }
};

// 更换倍速
const changeSpeed = () => {
  timeAxisState.speed = timeAxisState.speed === 1 ? 2 : 1;
};

// 外部数据传入，开始播放
const initDataToPlay = (obj) => {
  timeAxisState.type = obj.type;
  originalData = obj.data;
  timeAxisState.data = obj.data;
  trackPathArr = [];
  timeAxisState.data.forEach((item) => {
    trackPathArr.push(item.lnglat);
  });
  // 路线轨迹
  if (timeAxisState.type === 'track') {
    mapUtils = getMapUtils();
    map = mapUtils?.getMap();
    if (AMapType.includes(props.activeMap)) {
      AMap = mapUtils?.getAMap();
      trackPlayback1();
    } else {
      trackPlayback2();
    }
  }
};
// 高德地图轨迹
const trackPlayback1 = () => {
  clearObj();
  // 绘制轨迹
  movePolyline = new AMap.Polyline({
    map: map,
    path: trackPathArr,
    showDir: true,
    strokeColor: '#28F', //线颜色
    // strokeOpacity: 1,     //线透明度
    strokeWeight: 6, //线宽
    // strokeStyle: "solid"  //线样式
  });

  movePassedPolyline = new AMap.Polyline({
    map: map,
    strokeColor: '#AF5', //线颜色
    strokeWeight: 6 //线宽
  });

  startPlay();
};

let carLayer, carFeature, traceFeature, traceFeature2;
let lastTime;
let distance = 0;
let animationFlag = false;
let route,
  lastRoute = [];
let first = 0;

const trackPlayback2 = () => {
  if (!!carLayer) {
    clearObj();
  } else {
    const source = new VectorSource();
    carLayer = new VectorLayer({
      source: source
    });
    map.addLayer(carLayer);
  }

  const angle = getAngle(trackPathArr[0], trackPathArr[1]);
  lastTime = Date.now();
  carFeature = new Feature({
    geometry: new Point(trackPathArr[0]),
    zIndex: 999
  });
  const icon = new Icon({
    crossOrigin: 'anonymous',
    src: carImg,
    width: 13,
    height: 26,
    anchor: [0.5, 0.5],
    rotation: angle
  });
  carFeature.setStyle(
    new Style({
      image: icon
    })
  );
  route = new Feature({
    geometry: new LineString(trackPathArr[0])
  });
  traceFeature = new Feature({
    geometry: new LineString(trackPathArr),
    zIndex: 8
  });
  traceFeature.setStyle(arrowStyleFunction);
  traceFeature2 = new Feature({
    geometry: new LineString(trackPathArr[0]),
    zIndex: 9
  });
  lastRoute = [trackPathArr[0]];
  traceFeature2.setStyle(
    new Style({
      stroke: new Stroke({
        color: '#AF5',
        width: 6
      })
    })
  );
  carLayer.getSource().addFeatures([carFeature, traceFeature, traceFeature2]);
  carLayer.on('postrender', move);
  timeAxisState.activeIndex = 0;
  timeAxisState.playing = true;
  // 触发地图渲染
  const geo = carFeature.getGeometry().clone();
  carFeature.setGeometry(geo);
};
const move = (e) => {
  if (!timeAxisState.playing) return;
  const time = e.frameState.time;
  // 时间戳差（毫秒）
  const elapsedTime = time - lastTime;
  // 距离(其实是比例的概念)
  distance = distance + ((timeAxisState.speed === 2 ? 1 : 2) * 200 * elapsedTime) / 1e6;
  if (distance >= 1) {
    if (timeAxisState.activeIndex < trackPathArr.length - 1) {
      // 一段走完后
      lastRoute.push(traceFeature2.getGeometry().getCoordinates());
      console.log(lastRoute);
      timeAxisState.activeIndex += 1;
      distance = 0;
    } else if (first === 0) {
      // 所有走完后有时会0.9->1.2导致路没走完
      first = 1;
      distance = 1;
    } else {
      first = 0;
      distance = 0;
      animationFlag = false;
      stopAnimation();
      return;
    }
  }
  const arr = trackPathArr.slice(timeAxisState.activeIndex, timeAxisState.activeIndex + 2);
  route = new Feature({
    geometry: new LineString(arr)
  });
  // 保存当前时间
  lastTime = time;
  // 上次坐标
  const lastCoord = carFeature.getGeometry().getCoordinates();
  // 获取新位置的坐标点
  let curCoord = route.getGeometry().getCoordinateAt(distance);
  if (isNaNCoord(curCoord)) {
    curCoord = trackPathArr[0];
  }
  // 设置新坐标
  carFeature.getGeometry().setCoordinates(curCoord);
  // 获取当前轨迹坐标数组
  const currentCoords = traceFeature2.getGeometry().getCoordinates();
  currentCoords.push(curCoord);
  traceFeature2.getGeometry().setCoordinates(currentCoords);
  map.getView().setCenter(curCoord);
  // 设置角度
  carFeature.getStyle().getImage().setRotation(getAngle(lastCoord, curCoord));
  // 调用地图渲染
  map.render();
};
const isNaNCoord = (coord) => {
  return JSON.stringify(coord) === '[null,null]'; // NaN 在 JSON.stringify 中会被转换为 null
};
const stopAnimation = () => {
  if (carLayer) {
    carLayer.un('postrender', move);
  }
};
const getAngle = (point1, point2) => {
  // 处理无效输入或非数组情况
  if (!point1 || !point2 || !point1.length || !point2.length) {
    return 0;
  }

  const dx = point2[0] - point1[0];
  const dy = point2[1] - point1[1];

  // 处理两点相同的情况
  if (dx === 0 && dy === 0) {
    return 0;
  }

  // 使用 Math.atan2 计算角度，并确保结果在 0 到 2π 之间
  let angle = Math.atan2(dx, dy);
  if (angle < 0) {
    angle += 2 * Math.PI;
  }

  return angle;
};
// 箭头样式生成函数
const arrowStyleFunction = (feature, resolution) => {
  const geometry = feature.getGeometry();
  const styles = [
    // 基础线样式
    new Style({
      stroke: new Stroke({
        color: '#2196F3',
        width: 6
      })
    })
  ];

  // 计算箭头间隔（每50像素一个箭头）
  const length = geometry.getLength();
  const pixelInterval = 50;
  const geoInterval = pixelInterval * resolution;
  const arrowCount = Math.floor(length / geoInterval);

  // 生成箭头样式
  for (let i = 0; i <= arrowCount; i++) {
    const ratio = i / arrowCount;
    const coord = geometry.getCoordinateAt(ratio);

    // 获取线段方向
    const prevCoord = geometry.getCoordinateAt(Math.max(0, ratio - 0.001));
    const dx = coord[0] - prevCoord[0];
    const dy = coord[1] - prevCoord[1];
    const rotation = Math.atan2(dy, dx);

    // styles.push(
    //   new Style({
    //     geometry: new Point(coord),
    //     image: new Icon({
    //       src: arrowImg, // 替换为实际箭头图标路径
    //       anchor: [0.75, 0.5], // 图标锚点
    //       rotateWithView: true, // 随地图旋转
    //       rotation: -rotation, // 方向校准
    //       scale: 0.05
    //     }),
    //     zIndex: 10
    //   })
    // );
  }
  return styles;
};
// 创建新标点 moveTo调用第二次不生效，重新生成marker
const createMarker = () => {
  if (moveMarker) {
    // 不停止remove还是有
    moveMarker.stopMove();
    moveMarker.remove();
  }

  const icon = new AMap.Icon({
    size: new AMap.Size(13, 26),
    image: carImg
  });
  moveMarker = new AMap.Marker({
    map: map,
    position: trackPathArr[timeAxisState.activeIndex],
    icon: icon,
    anchor: 'center'
  });
  moveMarker.on('moving', (e) => {
    // 更新已通过路径
    const position = e.target.getPosition();
    const position2 = trackPathArr.slice(0, timeAxisState.activeIndex);
    position2.push(position);
    movePassedPolyline.setPath(position2);
    map.setCenter(position, true);
  });
  // 监听移动结束事件，继续播放
  moveMarker.on('moveend', () => {
    if (timeAxisState.playing) {
      createMarker();
      playNextNode();
    }
  });
};

// 轨迹 开始/暂停
const playOrPauseTrack = () => {
  if (AMapType.includes(props.activeMap)) {
    if (timeAxisState.playing) {
      if (timeAxisState.activeIndex >= timeAxisState.data.length - 1) {
        // 重新播放
        timeAxisState.activeIndex = 0;
        timeAxisState.playing = true;
        createMarker();
        movePassedPolyline.setPath([]);
        nextTick(() => {
          playNextNode();
        });
      } else if (isNewMarkerPause) {
        playNextNode();
      } else {
        moveMarker.resumeMove();
      }
    } else {
      moveMarker.pauseMove();
    }
    isNewMarkerPause = false;
  } else {
    if (!!timeAxisState.playing) {
      lastTime = Date.now();
      // 触发地图渲染
      const geo = carFeature.getGeometry().clone();
      carFeature.setGeometry(geo);
    }
  }
};
// 轨迹开始播放
const startPlay = () => {
  timeAxisState.activeIndex = 0;
  createMarker();
  timeAxisState.playing = true;
  playNextNode();
};
// 轨迹 上一步
const prevPauseTime = () => {
  if (timeAxisState.activeIndex <= 0) return;
  // 更新索引
  timeAxisState.playing = false;
  timeAxisState.activeIndex -= 1;
  if (AMapType.includes(props.activeMap)) {
    moveMarker.stopMove();
    createMarker();
    movePassedPolyline.setPath(trackPathArr.slice(0, timeAxisState.activeIndex + 1));
    isNewMarkerPause = true;
  } else {
    // 设置新坐标
    const curCoord = trackPathArr[timeAxisState.activeIndex];
    carFeature.getGeometry().setCoordinates(curCoord);
    // 获取当前轨迹坐标数组
    const currentCoords = lastRoute[timeAxisState.activeIndex];
    lastRoute = lastRoute.slice(0, timeAxisState.activeIndex + 1);
    traceFeature2.getGeometry().setCoordinates(currentCoords);
    map.getView().setCenter(curCoord);
  }
};
const nextPauseTime = () => {
  if (timeAxisState.activeIndex <= 0) return;
  // 更新索引
  timeAxisState.playing = false;
  timeAxisState.activeIndex += 1;
  if (AMapType.includes(props.activeMap)) {
    createMarker();
    movePassedPolyline.setPath(trackPathArr.slice(0, timeAxisState.activeIndex + 1));
    isNewMarkerPause = true;
  } else {
    // 设置新坐标
    const curCoord = trackPathArr[timeAxisState.activeIndex];
    carFeature.getGeometry().setCoordinates(curCoord);
    // 获取当前轨迹坐标数组
    const currentCoords = lastRoute[lastRoute.length - 1].concat([curCoord]);
    lastRoute.push(currentCoords);
    traceFeature2.getGeometry().setCoordinates(currentCoords);
    map.getView().setCenter(curCoord);
  }
};
// 轨迹播放下一个节点
const playNextNode = () => {
  if (timeAxisState.activeIndex >= timeAxisState.data.length - 1) {
    timeAxisState.playing = false;
    return;
  }
  // 更新索引
  timeAxisState.activeIndex += 1;

  // 移动到目标节点
  moveMarker.moveTo(trackPathArr[timeAxisState.activeIndex], {
    duration: timeAxisState.speed === 1 ? 2000 : 1000
  });
};

// 滚动到可见到当前点位置
watch(
  () => timeAxisState.activeIndex,
  (index) => {
    nextTick(() => {
      const itemRef = timelineItems.value[index];
      if (itemRef) {
        const itemEl = itemRef.$el;
        console.log(itemEl);
        itemEl.scrollIntoView({
          behavior: 'smooth'
        });
      }
    });
  }
);

// 清除元素
const clearObj = () => {
  if (AMapType.includes(props.activeMap)) {
    if (moveMarker) {
      // 不停止remove还是有
      moveMarker.stopMove();
      moveMarker.remove();
    }
    movePolyline?.remove();
    movePassedPolyline?.remove();
  } else {
    if (!!carFeature) {
      carLayer.getSource().removeFeature(carFeature);
    }
    if (!!traceFeature) {
      carLayer.getSource().removeFeature(traceFeature);
    }
    if (!!traceFeature2) {
      carLayer.getSource().removeFeature(traceFeature2);
    }
  }
};

onMounted(() => {
  getInitTime();
});

onUnmounted(() => {
  clearObj();
});

defineExpose({ initDataToPlay });
</script>

<style lang="scss" scoped>
.time-axis-container {
  position: absolute;
  bottom: 40px;
  left: 10px;
  z-index: 2;
  color: #fff;
  font-size: 14px;
  height: 40px;
  display: flex;
  &::before {
    content: '';
    position: absolute;
    top: 50%;
    left: -6px;
    transform: translateY(-50%);
    width: 3px;
    height: 45px;
    background: url('@/assets/images/timeAxis/timeLeft.png') no-repeat;
    background-size: 100% 100%;
  }
  &::after {
    content: '';
    position: absolute;
    top: 50%;
    right: -6px;
    transform: translateY(-50%);
    width: 3px;
    height: 45px;
    background: url('@/assets/images/timeAxis/timeRight.png') no-repeat;
    background-size: 100% 100%;
  }
  .expand-btn {
    width: 18px;
    height: 40px;
    background: url('@/assets/images/timeAxis/timeBtn.png') no-repeat;
    background-size: 100% 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 0 16px;
    cursor: pointer;
    font-size: 12px;
  }
  .time-box {
    width: 668px;
    height: 47px;
    background: url('@/assets/images/timeAxis/timeAxis.png') no-repeat;
    background-size: 100% 100%;
    display: flex;
  }
  .time-picker-box {
    width: 100px;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    :deep(.el-date-editor.el-input) {
      width: 100px;
      height: 18px;
      font-size: 12px;
      &:first-child {
        margin-top: -7px;
      }
    }
    :deep(.el-input__wrapper) {
      background-color: transparent;
      border: unset;
      box-shadow: unset;
      padding: 0 2px;
    }
    :deep(.el-input__inner) {
      color: #b5dbfc;
      cursor: pointer;
    }
    :deep(.el-input__prefix) {
      display: none;
    }
  }
  .time-list-box {
    flex: 1;
    display: flex;
    align-items: flex-end;
    overflow-x: auto;
    overflow-y: hidden;
    padding: 0 8px;
    -webkit-overflow-scrolling: touch; /* 在移动设备上启用平滑滚动 */
    scrollbar-width: none; /* Firefox */
    -ms-overflow-style: none; /* Internet Explorer 10+ */
    &::-webkit-scrollbar {
      display: none; /* Chrome, Safari 和基于 WebKit 的浏览器 */
    }
    .active {
      :deep(.el-timeline-item__node) {
        background-color: #ff0000;
        box-shadow: 0 0 4px 4px #f68686;
      }
    }
    :deep(.el-timeline) {
      display: flex;
      align-items: center;
      width: 100%;
      height: 100%;
      padding-left: 5px;
      padding-top: 12px;
    }
    :deep(.el-timeline-item__tail) {
      height: 5px;
      //background-color: #1f54b6;
      background-image: linear-gradient(to bottom, #1064d6 10%, #1876be 50%, #1064d6 90%);
      width: 100%;
      position: absolute;
      top: 3px;
    }
    :deep(.el-timeline-item__wrapper) {
      top: 10px;
      left: -11px;
      padding-left: 0;
    }
    :deep(.el-timeline-item__timestamp) {
      font-size: 12px;
      color: #ffffff;
      font-family: 'PingFang SC', sans-serif;
      margin-top: 5px;
    }
    :deep(.el-timeline-item__node) {
      background-color: #ffffff;
      box-shadow: 0 0 4px 4px #569eff;
      width: 5px !important;
      height: 5px !important;
      top: 3px;
      left: 3px;
    }
    :deep(.el-timeline-item) {
      width: 46px;
      min-width: 46px;
    }
  }
  .time-tool {
    width: 120px;
    display: flex;
    align-items: center;
    padding: 0 5px;
    .speed-btn {
      margin-right: 5px;
      color: #ffffff;
      cursor: pointer;
      font-size: 12px;
      padding-bottom: 6px;
      font-family: 'PingFang SC', sans-serif;
    }
    .prevIcon {
      width: 18px;
      height: 20px;
      background: url('@/assets/images/timeAxis/prev.png') no-repeat;
      background-size: 100% 100%;
      cursor: pointer;
    }
    .playIcon {
      width: 32px;
      height: 32px;
      background: url('@/assets/images/timeAxis/play.png') no-repeat;
      background-size: 100% 100%;
      cursor: pointer;
    }
    .nextIcon {
      width: 18px;
      height: 20px;
      background: url('@/assets/images/timeAxis/next.png') no-repeat;
      background-size: 100% 100%;
      cursor: pointer;
    }
    .rankIcon {
      width: 20px;
      height: 20px;
      background: url('@/assets/images/timeAxis/rank.png') no-repeat;
      background-size: 100% 100%;
      cursor: pointer;
      margin-left: 17px;
    }
  }
}
</style>
