import { AnymatchFn } from 'vite';
import { ref } from 'vue';
import { log } from 'echarts/types/src/util/log.js';
import { cesiumToLongitudeAndLatitude } from './coordinateUtil';

const line = ref<any>(null);
let modelExtiti: any = null;
const isOver = false;

// 创建自定义圆形大头针的函数（使用 Canvas 动态生成）
export function createCustomPinImage() {
  const canvas = document.createElement('canvas');
  const size = 48; // 图标大小
  canvas.width = size;
  canvas.height = size * 2; // 包括杆子部分

  const context = canvas.getContext('2d');

  // 绘制红色圆圈（带白边）
  context.beginPath();
  context.arc(size / 2, size / 2, size / 2 - 4, 0, 2 * Math.PI); // 圆圈
  context.fillStyle = 'white'; // 白色边框
  context.fill();
  context.beginPath();
  context.arc(size / 2, size / 2, size / 2 - 8, 0, 2 * Math.PI); // 红色填充
  context.fillStyle = 'red';
  context.fill();

  // 绘制杆子（白色）
  context.fillStyle = 'white';
  context.fillRect(size / 2 - 2, size, 4, size); // 杆子从圆圈底部向下延伸

  return canvas.toDataURL('image/png'); // 返回 Base64 编码的图片
}

export async function getElevationFromRay(cartographic: any, viewer: any) {
  let ellipsoid;
  let startPoint;
  let surfaceNormal;
  let direction;
  let ray;
  return new Promise((resolve, reject) => {
    ellipsoid = viewer.scene.globe.ellipsoid;
    startPoint = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 200);

    surfaceNormal = viewer.scene.globe.ellipsoid.geodeticSurfaceNormal(startPoint);
    direction = Cesium.Cartesian3.negate(surfaceNormal, new Cesium.Cartesian3());
    ray = new Cesium.Ray(startPoint, direction);
    const intersection = viewer.scene.pickFromRay(ray);
    if (intersection) {
      const cartographicPosition = Cesium.Cartographic.fromCartesian(intersection.position);
      resolve(cartographicPosition.height); // 返回高程
    } else {
      reject('未检测到交点');
    }
  });
}

export function createPolyLine(positions: any, viewer: any) {
  line.value = viewer.entities.add({
    name: 'polyline',
    polyline: {
      show: true, // 显示折线
      positions, // 折线顶点的位置数组
      material: Cesium.Color.fromCssColorString(`rgb(212, 16, 16)`), // 折线颜色
      width: 3, // 折线宽度
      clampToGround: true, // 将折线贴地
      zIndex: 92, // 折线层级索引
      classificationType: Cesium.ClassificationType.BOTH, // 折线分类类型
      heightReference: Cesium.HeightReference.NONE
    }
  });

  return line.value;
}

export function cleanLine(viewer:any,positions:any) {
  viewer.entities.remove(line.value);
  viewer.entities.remove(positions);
}

export function createModel(positions: any, viewer: any) {
  const url = '/src/assets/imgs/car.glb';

  const startPoint = positions[0];

  if (modelExtiti) {
    viewer.entities.remove(modelExtiti);
  }

  const entityOptions = {
    position: startPoint,
    orientation: Cesium.Transforms.headingPitchRollQuaternion(startPoint, new Cesium.HeadingPitchRoll(0, 0, 0)),
    model: {
      uri: url,
      scale: 1.0,
      minimumPixelSize: 100,
      disableDepthTestDistance: 'infinite',
      runAnimations: true,
    }
  };

  // 创建并添加实体
  modelExtiti = viewer.entities.add(entityOptions);

  return modelExtiti;
}

// 辅助函数：开始车辆移动动画
// export function startVehicleMovement(viewer: any, time: any) {
//   // 完全重置时钟（仅在第一次开始动画时）
//   viewer.clock.currentTime = Cesium.JulianDate.now();
//   viewer.clock.shouldAnimate = false;
//   viewer.clock.multiplier = 1;

//   const trail = line.value;
//   const trailCoordinates = trail.polyline.positions.getValue();

//   if (!trailCoordinates || trailCoordinates.length === 0) return;

//   const positionProperty = new Cesium.SampledPositionProperty();

//   let totalDistance = 0;
//   for (let i = 0; i < trailCoordinates.length - 1; i++) {
//     totalDistance += Cesium.Cartesian3.distance(trailCoordinates[i], trailCoordinates[i + 1]);
//   }

//   const timeInterval = time;
//   // 生成新的时间采样点
//   for (let i = 0; i < trailCoordinates.length; i++) {
//     const time = Cesium.JulianDate.addSeconds(viewer.clock.currentTime, i * timeInterval, new Cesium.JulianDate());

//     console.log(time);

//     positionProperty.addSample(time, trailCoordinates[i]);
//   }

//   // 设置插值算法
//   positionProperty.setInterpolationOptions({
//     interpolationDegree: 1,
//     interpolationAlgorithm: Cesium.HermitePolynomialApproximation
//   });

//   // 应用位置和方向属性
//   modelExtiti.position = positionProperty;
//   modelExtiti.orientation = new Cesium.VelocityOrientationProperty(positionProperty);

//   // 启动动画
//   viewer.clock.shouldAnimate = true;

//   // 设置结束时间
//   const stopTime = Cesium.JulianDate.addSeconds(
//     viewer.clock.currentTime,
//     stopNewTime, // 增加2秒缓冲
//     new Cesium.JulianDate()
//   );

//   // 添加时钟监听事件，检测是否到达终点
//   const clockTickEventRemovalCallback = viewer.clock.onTick.addEventListener((clock: any) => {
//     if (Cesium.JulianDate.compare(clock.currentTime, stopTime) >= 0) {
//       // 只停止动画，不重置位置
//       viewer.clock.shouldAnimate = false;

//       // 重置所有车辆实体位置到起点
//       if (modelExtiti && line.value && line.value.polyline && line.value.polyline.positions) {
//         const coordinates = line.value.polyline.positions.getValue();
//         if (coordinates && coordinates.length > 0) {
//           modelExtiti.position = coordinates[0];
//         }
//       }

//       // 重置时钟
//       viewer.clock.currentTime = Cesium.JulianDate.now();
//       // 移除监听器
//       clockTickEventRemovalCallback();
//     }
//   });
// }
// 辅助函数：开始车辆移动动画
// export function startVehicleMovement(viewer: any, totalDuration: number) {
//   // 完全重置时钟
//   viewer.clock.currentTime = Cesium.JulianDate.now();
//   viewer.clock.shouldAnimate = false;
//   viewer.clock.multiplier = 1; // 使用1倍速以确保时间准确性

//   const trail = line.value;
//   const trailCoordinates = trail.polyline.positions.getValue();

//   if (!trailCoordinates || trailCoordinates.length === 0) return;

//   const positionProperty = new Cesium.SampledPositionProperty();

//   // 计算总距离
//   let totalDistance = 0;
//   for (let i = 0; i < trailCoordinates.length - 1; i++) {
//     totalDistance += Cesium.Cartesian3.distance(trailCoordinates[i], trailCoordinates[i + 1]);
//   }

//   // 根据总距离和指定时间计算每段路径的时间间隔
//   let accumulatedTime = 0;

//   // 添加第一个采样点（起点）
//   positionProperty.addSample(viewer.clock.currentTime, trailCoordinates[0]);

//   // 为剩余的每个点添加采样点，根据距离比例分配时间
//   for (let i = 1; i < trailCoordinates.length; i++) {
//     // 计算当前段的距离
//     const segmentDistance = Cesium.Cartesian3.distance(trailCoordinates[i - 1], trailCoordinates[i]);

//     // 根据距离比例计算当前段所需的时间
//     const segmentDuration = (segmentDistance / totalDistance) * totalDuration;
//     accumulatedTime += segmentDuration;

//     // 创建对应的时间点
//     const time = Cesium.JulianDate.addSeconds(viewer.clock.currentTime, accumulatedTime, new Cesium.JulianDate());

//     positionProperty.addSample(time, trailCoordinates[i]);
//   }

//   // 设置插值算法
//   positionProperty.setInterpolationOptions({
//     interpolationDegree: 1,
//     interpolationAlgorithm: Cesium.HermitePolynomialApproximation
//   });

//   // 应用位置和方向属性
//   modelExtiti.position = positionProperty;
//   modelExtiti.orientation = new Cesium.VelocityOrientationProperty(positionProperty);

//   // 启动动画
//   viewer.clock.shouldAnimate = true;

//   // 设置结束时间（使用计算出的总时间）
//   const stopTime = Cesium.JulianDate.addSeconds(
//     viewer.clock.currentTime,
//     totalDuration, // 精确使用指定的总时间
//     new Cesium.JulianDate()
//   );

//   // 添加时钟监听事件，检测是否到达终点
//   const clockTickEventRemovalCallback = viewer.clock.onTick.addEventListener((clock: any) => {
//     if (Cesium.JulianDate.compare(clock.currentTime, stopTime) >= 0) {
//       // 停止动画
//       viewer.clock.shouldAnimate = false;

//       // 重置所有车辆实体位置到起点
//       if (modelExtiti && line.value && line.value.polyline && line.value.polyline.positions) {
//         const coordinates = line.value.polyline.positions.getValue();
//         if (coordinates && coordinates.length > 0) {
//           modelExtiti.position = coordinates[0];
//         }
//       }

//       // 重置时钟
//       viewer.clock.currentTime = Cesium.JulianDate.now();
//       // 移除监听器
//       clockTickEventRemovalCallback();
//     }
//   });
// }

// export function startVehicleMovement(viewer: any, totalDuration: number) {
//   // 完全重置时钟
//   viewer.clock.currentTime = Cesium.JulianDate.now();
//   viewer.clock.shouldAnimate = false;
//   viewer.clock.multiplier = 1; // 使用1倍速以确保时间准确性

//   const trail = line.value;
//   if (!trail || !trail.polyline || !trail.polyline.positions) {
//     console.error('路线数据不存在或无效');
//     return;
//   }

//   const trailCoordinates = trail.polyline.positions.getValue();

//   if (!trailCoordinates || trailCoordinates.length === 0) {
//     console.error('路线坐标数据不存在或为空');
//     return;
//   }

//   const positionProperty = new Cesium.SampledPositionProperty();

//   // 计算总距离
//   let totalDistance = 0;
//   for (let i = 0; i < trailCoordinates.length - 1; i++) {
//     totalDistance += Cesium.Cartesian3.distance(trailCoordinates[i], trailCoordinates[i + 1]);
//   }

//   // 根据总距离和指定时间计算每段路径的时间间隔
//   let accumulatedTime = 0;

//   // 添加第一个采样点（起点）
//   positionProperty.addSample(viewer.clock.currentTime, trailCoordinates[0]);

//   // 为剩余的每个点添加采样点，根据距离比例分配时间
//   for (let i = 1; i < trailCoordinates.length; i++) {
//     // 计算当前段的距离
//     const segmentDistance = Cesium.Cartesian3.distance(trailCoordinates[i - 1], trailCoordinates[i]);

//     // 根据距离比例计算当前段所需的时间
//     const segmentDuration = (segmentDistance / totalDistance) * totalDuration;
//     accumulatedTime += segmentDuration;

//     // 创建对应的时间点
//     const time = Cesium.JulianDate.addSeconds(viewer.clock.currentTime, accumulatedTime, new Cesium.JulianDate());

//     positionProperty.addSample(time, trailCoordinates[i]);
//   }

//   // 设置插值算法
//   positionProperty.setInterpolationOptions({
//     interpolationDegree: 1,
//     interpolationAlgorithm: Cesium.HermitePolynomialApproximation
//   });

//   // 确保modelExtiti存在
//   if (!modelExtiti) {
//     console.error('车辆模型不存在');
//     return;
//   }

//   // 应用位置和方向属性
//   modelExtiti.position = positionProperty;

//   // 使用VelocityOrientationProperty让模型跟随路径方向
//   const velocityOrientation = new Cesium.VelocityOrientationProperty(positionProperty);

//   // 如果模型车头方向与速度方向有偏差，可以通过调整模型的初始朝向来解决
//   // 例如：如果模型车头朝向左侧，需要顺时针旋转90度，可以设置headingOffset为Math.PI/2
//   const headingOffset = Cesium.Math.toRadians(90); // 默认0度，可以根据实际模型调整

//   // 如果需要应用朝向偏移，可以使用以下方式
//   // 创建一个回调函数来调整朝向
//   modelExtiti.orientation = new Cesium.CallbackProperty(time => {
//     const velocityQuaternion = velocityOrientation.getValue(time);
//     if (!velocityQuaternion) return undefined;

//     // 创建一个旋转四元数来调整朝向
//     const rotation = Cesium.Quaternion.fromAxisAngle(
//       Cesium.Cartesian3.UNIT_Z, // 绕Z轴旋转
//       headingOffset
//     );

//     // 应用旋转到速度方向
//     return Cesium.Quaternion.multiply(velocityQuaternion, rotation, new Cesium.Quaternion());
//   }, false);

//   // 启动动画
//   viewer.clock.shouldAnimate = true;

//   // 设置结束时间（使用计算出的总时间）
//   const stopTime = Cesium.JulianDate.addSeconds(
//     viewer.clock.currentTime,
//     totalDuration + 2, // 精确使用指定的总时间
//     new Cesium.JulianDate()
//   );

//   // 添加时钟监听事件，检测是否到达终点
//   const clockTickEventRemovalCallback = viewer.clock.onTick.addEventListener((clock: any) => {
//     if (Cesium.JulianDate.compare(clock.currentTime, stopTime) >= 0) {
//       // 停止动画
//       viewer.clock.shouldAnimate = false;

//       // 重置所有车辆实体位置到起点
//       if (modelExtiti && line.value && line.value.polyline && line.value.polyline.positions) {
//         const coordinates = line.value.polyline.positions.getValue();
//         if (coordinates && coordinates.length > 0) {
//           modelExtiti.position = coordinates[0];
//         }
//       }

//       // 重置时钟
//       viewer.clock.currentTime = Cesium.JulianDate.now();
//       // 移除监听器
//       clockTickEventRemovalCallback();
//     }
//   });
// }

function densifyPoints(positions: any[], stepSize: number = 2.0) {
  if (positions.length < 2) return positions;

  const densified: any[] = [];
  
  for (let i = 0; i < positions.length - 1; i++) {
    const start = positions[i];
    const end = positions[i + 1];
    
    // 计算两点间距离
    const distance = Cesium.Cartesian3.distance(start, end);
    
    // 放入起始点
    densified.push(start);
    
    // 如果距离过大，计算需要插入多少个点
    if (distance > stepSize) {
      const count = Math.ceil(distance / stepSize);
      for (let j = 1; j < count; j++) {
        // 线性插值计算中间点
        const t = j / count;
        const newPoint = Cesium.Cartesian3.lerp(start, end, t, new Cesium.Cartesian3());
        densified.push(newPoint);
      }
    }
  }
  
  // 别忘了把最后一个点放进去
  densified.push(positions[positions.length - 1]);
  
  return densified;
}

export async function startVehicleMovement(viewer: any, totalDuration: number) {
  // 1. 重置
  viewer.clock.currentTime = Cesium.JulianDate.now();
  viewer.clock.shouldAnimate = false;
  viewer.clock.multiplier = 1;

  const trail = line.value;
  if (!trail || !trail.polyline || !trail.polyline.positions) return;

  const rawCoordinates = trail.polyline.positions.getValue();
  if (!rawCoordinates || rawCoordinates.length === 0) return;

  // =========================================================
  // ✅ 核心改进 1：路径加密
  // 先把只有几个顶点的折线，变成几百个密集的点
  // 这样每个点都能去探测模型高度，车子就能贴合起伏了
  // =========================================================
  const denseCoordinates = densifyPoints(rawCoordinates, 2.0); // 每隔2米插入一个点

  let clampedPositions: any[] = [];

  try {
    // =========================================================
    // ✅ 核心改进 2：批量计算高度
    // 现在计算的是加密后那几百个点的高度
    // =========================================================
    // 提示：clampToHeightMostDetailed 支持的点的数量有限，
    // 如果路线非常非常长（几十公里），可能需要分段计算，但一般几千个点没问题。
    const updatedPositions = await viewer.scene.clampToHeightMostDetailed(denseCoordinates);

    clampedPositions = updatedPositions.map((pos: any) => {
      const cartographic = Cesium.Cartographic.fromCartesian(pos);
      // 💡 稍微抬高 0.5 - 1.0 米，防止车轮半截入土
      return Cesium.Cartesian3.fromRadians(
        cartographic.longitude, 
        cartographic.latitude, 
        cartographic.height + 0.8
      );
    });
  } catch (error) {
    console.warn("高度贴合计算失败或部分失败:", error);
    clampedPositions = denseCoordinates;
  }

  // =========================================================
  // 下面的逻辑和之前一样，构建 SampledProperty
  // =========================================================

  const positionProperty = new Cesium.SampledPositionProperty();
  let totalDistance = 0;
  
  for (let i = 0; i < clampedPositions.length - 1; i++) {
    totalDistance += Cesium.Cartesian3.distance(clampedPositions[i], clampedPositions[i + 1]);
  }

  let accumulatedTime = 0;
  positionProperty.addSample(viewer.clock.currentTime, clampedPositions[0]);

  for (let i = 1; i < clampedPositions.length; i++) {
    const segmentDistance = Cesium.Cartesian3.distance(clampedPositions[i - 1], clampedPositions[i]);
    const segmentDuration = (segmentDistance / totalDistance) * totalDuration;
    accumulatedTime += segmentDuration;

    const time = Cesium.JulianDate.addSeconds(viewer.clock.currentTime, accumulatedTime, new Cesium.JulianDate());
    positionProperty.addSample(time, clampedPositions[i]);
  }

  // 因为点很密集，线性插值(LinearApproximation)其实比 Hermite 更稳，不容易出现“过冲”导致的抖动
  // 当然 Hermite 也可以，看效果决定
  positionProperty.setInterpolationOptions({
    interpolationDegree: 1,
    interpolationAlgorithm: Cesium.LinearApproximation 
  });

  if (!modelExtiti) return;

  modelExtiti.position = positionProperty;

  // 姿态计算
  const velocityOrientation = new Cesium.VelocityOrientationProperty(positionProperty);
  const headingOffset = Cesium.Math.toRadians(90); // 按需调整

  modelExtiti.orientation = new Cesium.CallbackProperty((time: any) => {
    const velocityQuaternion = velocityOrientation.getValue(time);
    if (!velocityQuaternion) return undefined;
    const rotation = Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_Z, headingOffset);
    return Cesium.Quaternion.multiply(velocityQuaternion, rotation, new Cesium.Quaternion());
  }, false);

  viewer.clock.shouldAnimate = true;

  // 结束清理逻辑
  const stopTime = Cesium.JulianDate.addSeconds(viewer.clock.currentTime, totalDuration, new Cesium.JulianDate());
  const removeListener = viewer.clock.onTick.addEventListener((clock: any) => {
    if (Cesium.JulianDate.compare(clock.currentTime, stopTime) >= 0) {
      viewer.clock.shouldAnimate = false;
      viewer.clock.currentTime = Cesium.JulianDate.now();
      // 可以在这重置位置
      // modelExtiti.position = clampedPositions[0]; 
      removeListener();
    }
  });
}