import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';

export default class model3DLayer {
  constructor(id,accessToken,opt) {
    this.id = id;
    this.type = 'custom';
    this.renderingMode = '3d';
    this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 5 );
    this.camera.position.set( 0.1, 0.05, 0.15 );
    this.scene = new THREE.Scene();
    this.modelURL = opt.modelURL == undefined ? "":opt.modelURL;
    this.models = []; // 存储多个模型实例
    this.modelPoints = opt.modelPoints; // 修改为多个点的数组
  }
  onAdd(map, gl) {
    // create two three.js lights to illuminate the model
    const directionalLight = new THREE.DirectionalLight(0xffffff);
    directionalLight.position.set(0, -70, 100).normalize();
    this.scene.add(directionalLight);
    const directionalLight2 = new THREE.DirectionalLight(0x000000);
    directionalLight2.position.set(0, 70, 100).normalize();
    this.scene.add(directionalLight2);

// use the three.js GLTF loader to add the 3D model to the three.js scene
    const loader = new GLTFLoader();
    loader.load(
      this.modelURL,
      (gltf) => {
        const model = gltf.scene;
        // 遍历每个模型点
        this.modelPoints.forEach((ev) => {  // Use arrow function here
          const modelClone = model.clone(); // 克隆模型
          modelClone.traverse((child) => {
            if (child.isMesh) {
              const materials = Array.isArray(child.material) ? child.material : [child.material];
              materials.forEach((material) => {
                //material.color.set(0xff0000);
                // 克隆材质，以便每个模型都有独立的材质
                const newMaterial = material.clone(); // 完全克隆原始材质

                // 如果有纹理，克隆纹理
                /*if (material.map) {
                  newMaterial.map = material.map.clone();
                  newMaterial.map.needsUpdate = true; // 更新纹理
                }*/
                ev.contentList.forEach((item) => { // Use arrow function here as well
                  if (child.name.indexOf(item.key) !== -1) {
                    // Create a canvas and draw text
                    const canvas = document.createElement('canvas');
                    canvas.width = item.width;
                    canvas.height = item.height;
                    const context = canvas.getContext('2d');
                    context.fillStyle = '#fff'; // 白色
                    context.fillRect(0, 0, canvas.width, canvas.height);
                    // 平移到画布中心，旋转时以画布中心为基点
                    context.translate(canvas.width / 2, canvas.height / 2);
                    context.rotate(Math.PI); // 旋转180度
                    context.scale(-1, 1);
                    // 设置文本样式
                    context.fillStyle = item.fontColor;
                    context.font = item.font; // 'bold 70px Arial'; // 字体大小
                    context.textAlign = 'center';
                    context.textBaseline = 'middle';
                    const text = item.text;
                    console.info(text);
                    context.fillText(text, 0, 0);
                    const newTexture = new THREE.CanvasTexture(canvas);
                    newMaterial.map = newTexture;
                    newMaterial.needsUpdate = true;
                  }
                });
                newMaterial.transparent = false; // 确保不透明
                newMaterial.needsUpdate = true; // 确保材质更新
                // 将新的材质应用到模型
                child.material = newMaterial;
              });
            }
          });
          console.info(modelClone);
          this.models.push(modelClone); // 保存克隆模型
          this.scene.add(modelClone); // 添加克隆模型到场景
        });
      }
    );
    this.map = map;
// use the Mapbox GL JS map canvas for three.js
    this.renderer = new THREE.WebGLRenderer({
      canvas: map.getCanvas(),
      context: gl,
      antialias: true
    });
    this.renderer.autoClear = false;
    this.raycaster = new THREE.Raycaster();
    this.mouse = new THREE.Vector2();
    this.selectedObject = null;
    this.map.getCanvas().addEventListener('click', (event) => {
      this.handleClick(event);
    });

  }
  render(gl, matrix) {
    // 将传入的 matrix 作为投影矩阵（应用到摄像机）
    const m = new THREE.Matrix4().fromArray(matrix); // 获取地图的投影矩阵
    // 遍历所有模型并应用变换矩阵
    this.models.forEach((modelClone, index) => {
      const modelPoint = this.modelPoints[index];

      // 将地理坐标转换为墨卡托坐标
      const modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat(modelPoint.point);
      const modelTransform = {
        translateX: modelAsMercatorCoordinate.x,
        translateY: modelAsMercatorCoordinate.y,
        translateZ: modelAsMercatorCoordinate.z,
        rotateX: modelPoint.modelRotate[0],
        rotateY: modelPoint.modelRotate[1],
        rotateZ: modelPoint.modelRotate[2],
        scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits() * modelPoint.scaleSize
      };

      // 构建模型的世界变换矩阵（包含平移、缩放、旋转）
      const translationMatrix = new THREE.Matrix4().makeTranslation(
        modelTransform.translateX,
        modelTransform.translateY,
        modelTransform.translateZ
      );

      const scaleMatrix = new THREE.Matrix4().makeScale(
        modelTransform.scale,
        -modelTransform.scale,  // 在 Y 轴上翻转
        modelTransform.scale
      );

      const rotationX = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(1, 0, 0), modelTransform.rotateX);
      const rotationY = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), modelTransform.rotateY);
      const rotationZ = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 0, 1), modelTransform.rotateZ);

      // 组合平移、缩放、旋转矩阵
      const modelMatrix = new THREE.Matrix4()
        .multiplyMatrices(translationMatrix, scaleMatrix)
        .multiply(rotationX)
        .multiply(rotationY)
        .multiply(rotationZ);

      // 将模型的变换矩阵应用
      modelClone.matrix = m.clone().multiply(modelMatrix); // 使用地图的投影矩阵与模型矩阵结合
      modelClone.matrixAutoUpdate = false; // 禁止自动更新
    });
    // 重置渲染器状态并渲染场景
    this.renderer.resetState();
    this.renderer.render(this.scene, this.camera);

    // 触发地图的重绘
    this.map.triggerRepaint();
  }
  handleClick(event) {
    const rect = map.getCanvas().getBoundingClientRect();
    const mouseX = event.clientX - rect.left;
    const mouseY = event.clientY - rect.top;

    if (mouseX >= 0 && mouseX <= rect.width && mouseY >= 0 && mouseY <= rect.height) {
      this.mouse.x = (mouseX / rect.width) * 2 - 1;
      this.mouse.y = - (mouseY / rect.height) * 2 + 1;
      this.mouseClicked = true;
    }

    this.raycaster.ray.origin.copy(this.camera.position);
    this.raycaster.ray.direction.set(this.mouse.x, this.mouse.y, 1).unproject(this.camera).sub(this.camera.position).normalize();

    const distance = 1000; // 1 公里
    const farthestPoint = this.raycaster.ray.origin.clone().add(this.raycaster.ray.direction.clone().multiplyScalar(distance));
    const box = new THREE.Box3().setFromPoints([this.raycaster.ray.origin, farthestPoint]);

    // 过滤场景中的模型
    const intersects = this.scene.children.filter(child => {
      const boxChild = new THREE.Box3().setFromObject(child);
      return box.intersectsBox(boxChild);
    });

    console.info(intersects);
    if (intersects.length > 0) {
      console.log('Intersects:', intersects); // 输出所有相交的对象
      const selectedModel = intersects[0].object; // 获取选中的模型
      console.log('Selected model:', selectedModel);

      // 检查选中的模型是否存在并有材质
      if (selectedModel && selectedModel.material) {
        const highlightColor = 0xffff00; // 高亮颜色，黄色
        if (Array.isArray(selectedModel.material)) {
          selectedModel.material.forEach(material => {
            material.emissive.set(highlightColor); // 设置发光颜色
            material.color.set(highlightColor); // 设置颜色
          });
        } else {
          selectedModel.material.emissive.set(highlightColor); // 设置发光颜色
          selectedModel.material.color.set(highlightColor); // 设置颜色
        }

        // 可选：添加边框效果
        const outlineMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff });
        const outlineMesh = new THREE.Mesh(selectedModel.geometry, outlineMaterial);
        outlineMesh.scale.multiplyScalar(1.05);
        selectedModel.add(outlineMesh);
      } else {
        console.warn('Selected model does not have a material:', selectedModel);
      }
    } else {
      console.warn('No intersections found.');
    }
  }
} 模型不显示，帮我修改该代码