/**
 * 点云生成和颜色映射工具类
 * 从 robot_map_editor 移植
 */

import * as THREE from 'three'

/**
 * 将数值映射到 0-1 范围
 * @param {number} val - 输入值
 * @param {number} min - 最小值
 * @param {number} max - 最大值
 * @returns {string} 映射后的值（0-1）
 */
function getRangeNumber(val, min, max) {
  if (val < 0) {
    return Number.parseFloat(
      Math.abs(Math.abs(val) + min) / (max - min)
    ).toFixed(1)
  } else if (val === 0) {
    return Number.parseFloat((val - min) / (max - min)).toFixed(1)
  } else {
    return Number.parseFloat((val - min) / (max - min)).toFixed(1)
  }
}

/**
 * 生成点云粒子系统
 * 核心功能：坐标变换 + 颜色映射
 * 
 * @param {Array} pointsList - 点云数组 [{x, y, z}, ...]
 * @param {Object} transMatrix - 变换矩阵 {r11-r33, tx, ty, tz}
 * @param {string} color - 预留参数（未使用）
 * @returns {Object} {object: THREE.Points, box: THREE.Box3}
 */
function genParticles(pointsList, transMatrix, color) {
  // 定义高度颜色映射
  // Z < -1米: 蓝色 (地下)
  // -1 ~ 5米: 蓝→绿渐变 (地面层)
  // 5 ~ 10米: 绿→黄渐变 (建筑低层)
  // 10 ~ 15米: 黄→红渐变 (建筑高层)
  // Z > 15米: 红色 (高空)
  
  const color1 = new THREE.Color(0x0000ff) // 蓝色
  const color2 = new THREE.Color(0x00ff00) // 绿色
  const color3 = new THREE.Color(0xffff00) // 黄色
  const color4 = new THREE.Color(0xff0000) // 红色
  
  const r1 = color1.r
  const g1 = color1.g
  const b1 = color1.b
  const r4 = color4.r
  const g4 = color4.g
  const b4 = color4.b

  // 坐标变换：传感器坐标系 → 世界坐标系
  // 世界坐标 = 旋转矩阵 × 传感器坐标 + 平移向量
  const positions = new Float32Array(pointsList.length * 3)
  const colors = new Float32Array(pointsList.length * 3)
  
  for (let i = 0; i < pointsList.length; i++) {
    // 应用 3x3 旋转矩阵和平移向量
    positions[i * 3] =
      pointsList[i].x * transMatrix.r11 +
      pointsList[i].y * transMatrix.r12 +
      pointsList[i].z * transMatrix.r13 +
      transMatrix.tx
      
    positions[i * 3 + 1] =
      pointsList[i].x * transMatrix.r21 +
      pointsList[i].y * transMatrix.r22 +
      pointsList[i].z * transMatrix.r23 +
      transMatrix.ty
      
    positions[i * 3 + 2] =
      pointsList[i].x * transMatrix.r31 +
      pointsList[i].y * transMatrix.r32 +
      pointsList[i].z * transMatrix.r33 +
      transMatrix.tz

    // 根据 Z 坐标高度映射颜色
    const positonZ = positions[i * 3 + 2]
    
    if (positonZ < -1) {
      // 蓝色 (地下)
      colors[i * 3] = r1
      colors[i * 3 + 1] = g1
      colors[i * 3 + 2] = b1
      
    } else if (-1 <= positonZ && positonZ < 5) {
      // 蓝→绿渐变 (地面层)
      const percent = getRangeNumber(positonZ, -1, 5)
      const c = color1.clone().lerp(color2, percent)
      colors[i * 3] = c.r
      colors[i * 3 + 1] = c.g
      colors[i * 3 + 2] = c.b
      
    } else if (5 <= positonZ && positonZ < 10) {
      // 绿→黄渐变 (建筑低层)
      const percent = getRangeNumber(positonZ, 5, 10)
      const c = color2.clone().lerp(color3, percent)
      colors[i * 3] = c.r
      colors[i * 3 + 1] = c.g
      colors[i * 3 + 2] = c.b
      
    } else if (10 <= positonZ && positonZ < 15) {
      // 黄→红渐变 (建筑高层)
      const percent = getRangeNumber(positonZ, 10, 15)
      const c = color3.clone().lerp(color4, percent)
      colors[i * 3] = c.r
      colors[i * 3 + 1] = c.g
      colors[i * 3 + 2] = c.b
      
    } else {
      // 红色 (高空)
      colors[i * 3] = r4
      colors[i * 3 + 1] = g4
      colors[i * 3 + 2] = b4
    }
  }

  // 计算点云包围盒（用于地面动态扩展）
  const box = new THREE.Box3().setFromArray(positions)
  
  // 创建几何体
  const geometry = new THREE.BufferGeometry()
  geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3))
  geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3))

  // 创建 ShaderMaterial 定义渲染方式（参考 robot_map_editor）
  const material = new THREE.ShaderMaterial({
    vertexShader: `
      attribute vec3 color;
      varying vec3 vColor;

      void main() {
          vColor = color;
          gl_PointSize = 0.8;
          gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
      }
    `,
    fragmentShader: `
      varying vec3 vColor;

      void main() {
          gl_FragColor = vec4(vColor, 1.0);
      }
    `
  })
  
  const object = new THREE.Points(geometry, material)

  return { object, box }
}

/**
 * 数组相等性比较
 * @param {Array} arr1 - 数组1
 * @param {Array} arr2 - 数组2
 * @returns {boolean} 是否相等
 */
const arraysEqual = (arr1, arr2) => {
  if (arr1.length !== arr2.length) return false
  for (let i = 0; i < arr1.length; i++) {
    if (arr1[i] !== arr2[i]) return false
  }
  return true
}

/**
 * 导出工具对象
 */
const Utils = {
  genParticles,
  arraysEqual
}

export default Utils

