<template>
  <div class="three-viewer">
    <div ref="container" class="canvas-container"></div>
    <div class="annotations-container" ref="annotationsContainer"></div>
    
    <!-- 调试面板 -->
    <div v-if="debugMode" class="debug-panel">
      <h3>调试模式</h3>
      <div class="debug-info">
        <p>点击模型查看部件信息</p>
        <div v-if="selectedMeshInfo">
          <p><strong>部件名称:</strong> {{ selectedMeshInfo.name || '未命名' }}</p>
          <p><strong>坐标:</strong></p>
          <pre>{{ JSON.stringify(selectedMeshInfo.position, null, 2) }}</pre>
          <button @click="copyPosition">复制坐标</button>
        </div>
      </div>
      <div class="mesh-list">
        <h4>模型部件列表:</h4>
        <ul>
          <li v-for="(mesh, index) in meshList" :key="index">
            {{ mesh.name || `未命名_${index}` }}
          </li>
        </ul>
      </div>
    </div>
  </div>
</template>

<script>
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; // 导入 GLTFLoader 用于加载 GLTF 模型
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; // 导入 OrbitControls 用于控制相机
// 高亮
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass.js";
import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass.js";
import TextureName from '../../public/models/textureName.json'
import { RoomEnvironment } from 'three/examples/jsm/environments/RoomEnvironment.js'
import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'

export default {
  name: 'ThreeViewerDebug',
  props: {
    modelPath: {
      type: [String, Number],
      default: '',
    },
    annotations: {
      type: Array,
      default: () => []
    },
    debugMode: {
      type: Boolean,
      default: false
    }
  },
  computed: {
    textureObj() {
      return this.$store && this.$store.state.textureObj || {}
    },
  },
  watch: {
    modelPath: {
      handler(v) {
        if(v) {
          if (this.scene) {
            this.scene.clear();
            this.scene = null;
          }
          // 2. 销毁渲染器
          if (this.renderer) {
            this.renderer.dispose();
            this.renderer.forceContextLoss();
            this.renderer = null;
          }
          // 3. 销毁相机
          this.camera = null;
          // 4. 清空画布DOM容器的内容
          if(this.sceneDomElement){
              this.sceneDomElement.innerHTML = '';
          }
          this.cleanup();
          setTimeout(() => {
            this.init()
          }, 300)
        }
      },
      immediate: true
    },
  },
  data() {
    return {
      scene: null,          // Three.js场景
      camera: null,         // 相机
      renderer: null,       // 渲染器
      controls: null,       // 轨道控制器
      model: null,          // 加载的3D模型
      frameId: null,        // 动画帧ID
      sceneDomElement: null, // 容器DOM元素
      parent: null, // 容器
      maxDim: null,
      highlightColor: null, //高亮颜色
      composer: null,
      pmremGenerator: null,
      labelRenderer: null,
      annotationObjects: [],
      selectedPart: null,
      partMeshMap: {},
      meshList: [],
      selectedMeshInfo: null,
      raycaster: new THREE.Raycaster(),
      mouse: new THREE.Vector2()
    };
  },
  mounted () {
    // this.onWindowResize(); // 初始化后立即调用一次
    // 添加窗口大小变化监听
    // window.addEventListener('resize', this.onWindowResize);
    this.resizeObserver = new ResizeObserver(this.onWindowResize);
    this.resizeObserver.observe(this.$refs.container);

    window.addEventListener('click', this.onMouseClick, false);
    this.highlightColor = new THREE.Color(0xff0000); // 高亮颜色为红色
  },
  beforeDestroy() {
    this.cleanup();
    window.removeEventListener('click', this.onMouseClick, false);
    window.removeEventListener('resize', this.onWindowResize);

    // 断开ResizeObserver
    if (this.resizeObserver) {
      this.resizeObserver.disconnect();
    }
    if (this.labelRenderer) {
      this.labelRenderer.domElement.remove()
    }
  },
  destroyed() {
    cancelAnimationFrame(this.frameId);
    if (this.sceneDomElement && this.renderer) {
      this.sceneDomElement.removeChild(this.renderer.domElement);
    }
    if (this.renderer) {
      this.renderer.dispose();
    }
    if (this.scene) {
      this.scene.clear();
    }
  },
  methods: {
    cleanup() {
      if (this.frameId) {
        cancelAnimationFrame(this.frameId);
      }
      if (this.scene) {
        this.scene.clear();
        this.scene = null;
      }
      if (this.renderer) {
        this.renderer.dispose();
        this.renderer = null;
      }
      if (this.labelRenderer) {
        this.labelRenderer.domElement.remove();
        this.labelRenderer = null;
      }
      if (this.sceneDomElement) {
        this.sceneDomElement.innerHTML = '';
      }
    },
    init() {
      if (this.sceneDomElement && this.renderer) {
        this.sceneDomElement.removeChild(this.renderer.domElement);
      }
      // 获取容器元素
      this.sceneDomElement = this.$refs.container;
      // 1.  创建一个新的场景
      this.scene = new THREE.Scene();

      // 2. 创建相机
      const width = this.sceneDomElement.clientWidth;
      const height = this.sceneDomElement.clientHeight;
      this.camera = new THREE.PerspectiveCamera(55, width / height, 0.1, 1000);

      // 3. 创建渲染器
      this.renderer = new THREE.WebGLRenderer({
        antialias: true,
        // alpha: true,
      });
      this.renderer.shadowMap.enabled = true

      // CSS2D渲染器（用于标注）
      this.labelRenderer = new CSS2DRenderer()
      this.labelRenderer.setSize(width, height)
      this.labelRenderer.domElement.style.position = 'absolute'
      this.labelRenderer.domElement.style.top = '0'
      this.labelRenderer.domElement.style.pointerEvents = 'none'
      this.$refs.annotationsContainer.appendChild(this.labelRenderer.domElement)

      // 设置画布分辨率 提高画质
      this.renderer.setPixelRatio(window.devicePixelRatio);
      // 渲染器开启阴影效果
      this.renderer.shadowMap.enabled = true

      this.renderer.setSize(width, height);
      this.renderer.outputEncoding = THREE.sRGBEncoding; // 设置颜色编码
      this.sceneDomElement.appendChild(this.renderer.domElement);

      this.scene.background = new THREE.Color( 0xcccccc );
      this.scene.fog = new THREE.Fog( 0xa0a0a0, 10, 50 );

      const hemiLight = new THREE.HemisphereLight( 0xffffff, 0x8d8d8d, 3 );
      hemiLight.position.set( 0, 20, 0 );
      this.scene.add( hemiLight );

      const dirLight = new THREE.DirectionalLight( 0xffffff, 3 );
      dirLight.position.set( 3, 10, 10 );
      dirLight.castShadow = true;
      dirLight.shadow.camera.top = 2;
      dirLight.shadow.camera.bottom = - 2;
      dirLight.shadow.camera.left = - 2;
      dirLight.shadow.camera.right = 2;
      dirLight.shadow.camera.near = 0.1;
      dirLight.shadow.camera.far = 40;
      this.scene.add( dirLight );


      // //4. 添加光源
      // const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); // 创建环境光
      // this.scene.add(ambientLight); // 将环境光添加到场景中

      // const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); // 平行光
      // directionalLight.position.set(5, 10, 7);
      // directionalLight.castShadow = true // 让平行光产生阴影
      
      // // 配置阴影属性 - 提高质量减少锯齿
      // directionalLight.shadow.mapSize.width = 4096
      // directionalLight.shadow.mapSize.height = 4096
      // directionalLight.shadow.camera.near = 0.5
      // directionalLight.shadow.camera.far = 50
      // directionalLight.shadow.camera.left = -10
      // directionalLight.shadow.camera.right = 10
      // directionalLight.shadow.camera.top = 10
      // directionalLight.shadow.camera.bottom = -10
      // directionalLight.shadow.bias = -0.0001 // 减少阴影失真
      // directionalLight.shadow.normalBias = 0.02 // 减少阴影痤疮
      
      // this.scene.add(directionalLight);

      // // 环境光
      // this.pmremGenerator = new THREE.PMREMGenerator(this.renderer)
      // this.pmremGenerator.compileEquirectangularShader()
      // const env = this.pmremGenerator.fromScene(new RoomEnvironment(this.renderer), 0.04).texture
      // this.scene.environment = env

      // 添加地面
      this.createGround()

      // 5. 添加轨道控制器
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableDamping = true; // 启用阻尼效果
      this.controls.dampingFactor = 0.25; // 阻尼系数

      // 6. 加载3D模型
      this.loadModel();

      // 7. 开始动画循环
      this.animate();

    },

    loadModel() {
      const loader = new GLTFLoader();
      const textureLoader = new THREE.TextureLoader();
      loader.load(
        this.modelPath,
        // 'https://skeps-bucket.oss-cn-shenzhen.aliyuncs.com/2026%2FFile%2F4d3a9525-c415-4ab2-b916-d87b4b86ebcbSK010020001001BLQ_%E4%BA%A4%E6%B5%81%E9%81%BF%E9%9B%B7%E5%99%A8%2C%E5%B8%A6%E6%94%AF%E6%92%91%E4%BB%B6%E5%9B%BA%E5%AE%9A%E9%97%B4%E9%9A%99.glb',
        (gltf) => {
          // 移除旧模型
          if (this.model) {
            this.scene.remove(this.model);
          }
          this.model = gltf.scene;

          this.scene.add(this.model);

          // 收集所有mesh信息
          this.partMeshMap = {};
          this.meshList = [];

          // 遍历模型所有子元素
          this.model.traverse((child) => {
            if (child.isMesh) {
              // console.log(7777)
              child.material.emissiveMap = child.material.map;
              child.castShadow = true; // 让模型产生阴影
              child.receiveShadow = true; // 让模型接受阴影

              // child.material.emissive = child.material.color;
              let name = child.material.name.split('.')[0]
              let path = TextureName[name]

              if(path) {
                if(this.textureObj[name]) {
                  child.material = this.textureObj[name]
                  child.material.needsUpdate = true;
                } else {
                  let texture = textureLoader.load(`/models/texture/${encodeURIComponent(path)}.jpg`)
                  texture.wrapS = THREE.RepeatWrapping;
                  texture.wrapT = THREE.RepeatWrapping;
                  texture.repeat.set( 1, 1 );
                  let material = null
                  if(name.includes('金属')) {
                    material = new THREE.MeshStandardMaterial({
                      map: texture,
                      // color: 0x049EF4,
                      // emissive: 0x000000,
                      metalness: 0.55,  // 金属感
                      roughness: 0.05   // 粗糙度，0为镜面反射
                    })
                  } else {
                    material = new THREE.MeshPhongMaterial( {
                      // ...child.material,
                      map: texture,
                      emissiveMap: child.material.map,
                      shininess: 0,
                    } );
                  }
                  child.material = material
                  child.material.needsUpdate = true;
                  this.textureObj[name] = material
                  // this.$store.commit('set_textureObj', this.textureObj)
                }
              }

              // 存储mesh引用
              const meshInfo = {
                name: child.name,
                mesh: child,
                parent: child.parent
              };
              
              this.meshList.push(meshInfo);
              
              if (child.name) {
                this.partMeshMap[child.name] = child;
              }
            }
          });

          // 计算模型包围盒并居中
          const box = new THREE.Box3().setFromObject(this.model);
          const center = box.getCenter(new THREE.Vector3());
          const size = box.getSize(new THREE.Vector3());

          // 根据模型大小调整相机
          const maxDim = Math.max(size.x, size.y, size.z);
          this.maxDim = maxDim
          this.camera.position.z = this.maxDim * 1;
          this.camera.near = maxDim / 100;
          this.camera.far = maxDim * 100;
          this.camera.updateProjectionMatrix();

          // 创建一个父对象用于旋转
          // this.parent = new THREE.Object3D(); // 创建一个新的 Object3D 作为父对象
          // this.parent.add(this.model); // 将模型添加到父对象

          this.scene.add(this.model); // 将父对象添加到场景

          // 让控制器聚焦到模型中心 聚焦中心
          this.controls.target.copy(center);

          this.controls.enableRotate = true;
          // this.controls.minPolarAngle = Math.PI / 2; // 限制向下旋转的角度
          // this.controls.maxPolarAngle = Math.PI / 2; // 限制向上旋转的角度

      this.controls.update();
      
      // 调整地面位置到模型底部
      if (this.ground) {
        this.ground.position.y = box.min.y - 0.01
      }
      
      this.createAnnotations()
      this.$emit('model-loaded')
        },
        (progress) => {
          const percent = (progress.loaded / progress.total) * 100
          this.$emit('loading-progress', percent)
        },
        (error) => {
          console.error('模型加载失败:', error);
          this.$emit('model-error', error)
        }
      );
    },

    animate() {
      this.frameId = requestAnimationFrame(this.animate);
      if(this.parent && this.isPlay) {
        this.parent.rotation.y += 0.001; // 沿 Y 轴旋转父对象
      }
      // 更新控制器
      if (this.controls) {
        this.controls.update();
      }

      // 渲染场景
      if (this.renderer && this.scene && this.camera) {
        this.renderer.render(this.scene, this.camera);
      }

      if (this.composer) {
        this.composer.render(this.scene, this.camera);
      }
      
      if(this.labelRenderer && this.scene && this.camera) {
        this.labelRenderer.render(this.scene, this.camera)
      }
    },

    // 响应式调整大小
    onWindowResize() {
      if (this.camera && this.renderer) {
        const width = this.sceneDomElement.clientWidth;
        const height = this.sceneDomElement.clientHeight;
        this.camera.aspect = width / height;
        this.camera.updateProjectionMatrix();
        this.renderer.setSize(width, height);
      }
    },
     outlineObj(selectedObjects) {
      let outlinePass;
      let renderPass;
      let unrealBloomPass;

      // 创建一个EffectComposer（效果组合器）对象，然后在该对象上添加后期处理通道。
      // 用于模型边缘高亮
      this.composer = new EffectComposer(this.renderer);
      this.composer.renderTarget1.texture.outputColorSpace = THREE.sRGBEncoding;
      this.composer.renderTarget2.texture.outputColorSpace = THREE.sRGBEncoding;
      this.composer.renderTarget1.texture.encoding = THREE.sRGBEncoding;
      this.composer.renderTarget2.texture.encoding = THREE.sRGBEncoding;

      // 新建一个场景通道  为了覆盖到原来的场景上
      renderPass = new RenderPass(this.scene, this.camera);
      this.composer.addPass(renderPass);
      // 物体边缘发光通道
      outlinePass = new OutlinePass(
        new THREE.Vector2(this.sceneDomElement.clientWidth, this.sceneDomElement.clientHeight),
        this.scene,
        this.camera,
        selectedObjects
      );
      outlinePass.selectedObjects = selectedObjects;
      outlinePass.edgeStrength = 10.0; // 边框的亮度
      outlinePass.edgeGlow = 0.5; // 光晕[0,1]
      outlinePass.usePatternTexture = false; // 是否使用父级的材质
      outlinePass.edgeThickness = 1.0; // 边框宽度
      outlinePass.downSampleRatio = 1; // 边框弯曲度
      outlinePass.pulsePeriod = 5; // 呼吸闪烁的速度
      outlinePass.visibleEdgeColor.set(parseInt(0x00ff00)); // 呼吸显示的颜色
      outlinePass.hiddenEdgeColor = new THREE.Color(0, 0, 0); // 呼吸消失的颜色
      outlinePass.clear = true;
      this.composer.addPass(outlinePass);
      // 自定义的着色器通道 作为参数
      // effectFXAA = new ShaderPass(FXAAShader);
      // effectFXAA.uniforms.resolution.value.set(
      //   1 / window.innerWidth,
      //   1 / window.innerHeight
      // );
      // effectFXAA.renderToScreen = true;
      // composer.addPass(effectFXAA);
      // // 抗锯齿
      // smaaPass = new SMAAPass();
      // composer.addPass(smaaPass);
      // // 发光效果
      unrealBloomPass = new UnrealBloomPass();
      unrealBloomPass.strength = 0.1;
      unrealBloomPass.radius = 0;
      unrealBloomPass.threshold = 1;
      this.composer.addPass(unrealBloomPass);

      // this.scene.background = new THREE.Color(0x1b1824);
    },
    // 创建标签
    createAnnotations() {
      // 清除旧标注
      this.annotationObjects.forEach(obj => {
        this.scene.remove(obj)
      })
      this.annotationObjects = []

      // 创建标注点的预设位置（圆形分布）
      const radius = 2
      const angleStep = (Math.PI * 2) / this.annotations.length

      this.annotations.forEach((annotation, index) => {
        let position = annotation.position && annotation.position[0] ? annotation.position[0] : { x: 0, y: 0, z: 0 }
        let position2 = { x: position.x + 0.1, y: position.y + 0.05, z: position.z }
        // 创建标注标签
        const labelDiv = document.createElement('div')
        labelDiv.className = 'annotation-label'
        labelDiv.textContent = `${index + 1} ${annotation.name}`
        labelDiv.style.cssText = `
          background: rgba(64, 158, 255, 0.9);
          color: white;
          padding: 5px 10px;
          border-radius: 4px;
          font-size: 12px;
          cursor: pointer;
          white-space: nowrap;
          pointer-events: auto;
        `
        labelDiv.addEventListener('click', () => {
          this.onAnnotationClick(annotation, index)
        })

        const label = new CSS2DObject(labelDiv)
        label.position.set(position2.x, position2.y, position2.z)
        label.userData = { annotation, index }
        
        this.scene.add(label)
        this.annotationObjects.push(label)

        // 创建连接线
        const points = [
          new THREE.Vector3(position.x, position.y, position.z),
          new THREE.Vector3(position2.x, position2.y, position2.z)
        ]
        const geometry = new THREE.BufferGeometry().setFromPoints(points)
        const material = new THREE.LineBasicMaterial({ 
          color: 0x409eff,
          transparent: true,
          opacity: 0.5
        })
        const line = new THREE.Line(geometry, material)
        this.scene.add(line)
        this.annotationObjects.push(line)
      })
    },
    onAnnotationClick(annotation, index) {
      this.highlightPart(index)
      this.$emit('annotation-click', annotation, index)
    },

    // 创建地面
    createGround() {
      // 创建圆形地面几何体，避免菱形格子
      const groundGeometry = new THREE.CircleGeometry(25, 64)
      
      // 创建地面材质 - 使用 ShadowMaterial 只显示阴影
      const groundMaterial = new THREE.ShadowMaterial({
        opacity: 0.25,
        color: 0x000000
      })
      
      // 创建地面网格
      this.ground = new THREE.Mesh(groundGeometry, groundMaterial)
      this.ground.rotation.x = -Math.PI / 2 // 旋转地面使其水平
      this.ground.position.y = 0
      this.ground.receiveShadow = true // 地面接收阴影
      
      this.scene.add(this.ground)
    },

    highlightPart(index) {
      // 重置之前的高亮
      if (this.selectedPart !== null) {
        this.annotationObjects.forEach((obj, i) => {
          if (obj.isLine) {
            obj.material.opacity = 0.5
          } else if (obj.element) {
            obj.element.style.background = 'rgba(64, 158, 255, 0.9)'
            obj.element.style.transform = 'scale(1)'
          }
        })
      }

      // 高亮选中的部件
      this.selectedPart = index
      this.annotationObjects.forEach((obj, i) => {
        const objIndex = Math.floor(i / 2)
        if (objIndex === index) {
          if (obj.isLine) {
            obj.material.opacity = 1
            obj.material.color.setHex(0xff6b00)
          } else if (obj.element) {
            obj.element.style.background = 'rgba(255, 107, 0, 0.95)'
            obj.element.style.transform = 'scale(1.1)'
          }
        }
      })
    },
    
    onMouseClick(event) {
      if (!this.debugMode || !this.sceneDomElement) return;

      const rect = this.sceneDomElement.getBoundingClientRect();
      this.mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
      this.mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;

      this.raycaster.setFromCamera(this.mouse, this.camera);
      const intersects = this.raycaster.intersectObjects(this.model.children, true);

      if (intersects.length > 0) {
        const mesh = intersects[0].object;
        const point = intersects[0].point;
        
        this.selectedMeshInfo = {
          name: mesh.name,
          position: {
            x: parseFloat(point.x.toFixed(3)),
            y: parseFloat(point.y.toFixed(3)),
            z: parseFloat(point.z.toFixed(3))
          }
        };
        
        console.log('点击的部件:', this.selectedMeshInfo);
      }
    },

    copyPosition() {
      if (this.selectedMeshInfo) {
        const text = JSON.stringify(this.selectedMeshInfo.position, null, 2);
        navigator.clipboard.writeText(text).then(() => {
          this.$message.success('坐标已复制到剪贴板');
        });
      }
    },
  }
}
</script>

<style scoped>
.three-viewer {
  width: 100%;
  height: 100%;
  position: relative;
}

.canvas-container {
  width: 100%;
  height: 100%;
}

.annotations-container {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.debug-panel {
  position: absolute;
  top: 10px;
  right: 10px;
  background: rgba(255, 255, 255, 0.95);
  padding: 15px;
  border-radius: 8px;
  max-width: 300px;
  max-height: 80%;
  overflow-y: auto;
  box-shadow: 0 2px 8px rgba(0,0,0,0.2);
  pointer-events: auto;
}

.debug-panel h3 {
  margin: 0 0 10px 0;
  font-size: 16px;
  color: #303133;
}

.debug-panel h4 {
  margin: 10px 0 5px 0;
  font-size: 14px;
  color: #606266;
}

.debug-info {
  margin-bottom: 15px;
  padding-bottom: 15px;
  border-bottom: 1px solid #dcdfe6;
}

.debug-info p {
  margin: 5px 0;
  font-size: 13px;
  color: #606266;
}

.debug-info pre {
  background: #f5f7fa;
  padding: 8px;
  border-radius: 4px;
  font-size: 12px;
  margin: 5px 0;
}

.debug-info button {
  margin-top: 8px;
  padding: 5px 12px;
  background: #409eff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
}

.debug-info button:hover {
  background: #66b1ff;
}

.mesh-list ul {
  margin: 0;
  padding-left: 20px;
  max-height: 300px;
  overflow-y: auto;
}

.mesh-list li {
  font-size: 12px;
  color: #606266;
  margin: 3px 0;
  word-break: break-all;
}
</style>
