<template>
  <div class="three-viewer">
    <div ref="container" class="canvas-container"></div>
    <div class="annotations-container" ref="annotationsContainer"></div>
  </div>
</template>

<script>
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'

export default {
  name: 'ThreeViewer',
  props: {
    modelPath: {
      type: String,
      required: true
    },
    annotations: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      scene: null,
      camera: null,
      renderer: null,
      labelRenderer: null,
      controls: null,
      model: null,
      annotationObjects: [],
      selectedPart: null
    }
  },
  mounted() {
    this.initThree()
    this.loadModel()
    this.animate()
    window.addEventListener('resize', this.onWindowResize)
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.onWindowResize)
    if (this.renderer) {
      this.renderer.dispose()
    }
    if (this.labelRenderer) {
      this.labelRenderer.domElement.remove()
    }
  },
  methods: {
    initThree() {
      // 场景
      this.scene = new THREE.Scene()
      this.scene.background = new THREE.Color(0xf0f0f0)

      // 相机
      const container = this.$refs.container
      const width = container.clientWidth
      const height = container.clientHeight
      this.camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000)
      this.camera.position.set(5, 5, 5)

      // 渲染器
      this.renderer = new THREE.WebGLRenderer({ antialias: true })
      this.renderer.setSize(width, height)
      this.renderer.setPixelRatio(window.devicePixelRatio)
      this.renderer.shadowMap.enabled = true
      container.appendChild(this.renderer.domElement)

      // 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.controls = new OrbitControls(this.camera, this.renderer.domElement)
      this.controls.enableDamping = true
      this.controls.dampingFactor = 0.05

      // 光照
      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, 5)
      directionalLight.castShadow = true
      this.scene.add(directionalLight)

      // 网格地面
      // const gridHelper = new THREE.GridHelper(10, 10)
      // this.scene.add(gridHelper)
    },

    loadModel() {
      const loader = new GLTFLoader()
      console.log(this.modelPath)
      loader.load(
        this.modelPath,
        (gltf) => {
          this.model = gltf.scene
          
          // 计算模型边界并居中
          const box = new THREE.Box3().setFromObject(this.model)
          const center = box.getCenter(new THREE.Vector3())
          const size = box.getSize(new THREE.Vector3())
          
          this.model.position.sub(center)
          
          // 调整相机位置
          const maxDim = Math.max(size.x, size.y, size.z)
          const fov = this.camera.fov * (Math.PI / 180)
          let cameraZ = Math.abs(maxDim / 2 / Math.tan(fov / 2))
          cameraZ *= 2.5
          
          this.camera.position.set(cameraZ, cameraZ, cameraZ)
          this.camera.lookAt(0, 0, 0)
          this.controls.target.set(0, 0, 0)
          
          this.scene.add(this.model)
          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)
        }
      )
    },

    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) => {
        const angle = angleStep * index
        const x = Math.cos(angle) * radius
        const z = Math.sin(angle) * radius
        const y = 1 + Math.sin(index) * 0.5

        // 创建标注标签
        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(x, y, z)
        label.userData = { annotation, index }
        
        this.scene.add(label)
        this.annotationObjects.push(label)

        // 创建连接线
        const points = [
          new THREE.Vector3(0, 0, 0),
          new THREE.Vector3(x, y, 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)
    },

    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)'
          }
        }
      })
    },

    animate() {
      requestAnimationFrame(this.animate)
      this.controls.update()
      this.renderer.render(this.scene, this.camera)
      this.labelRenderer.render(this.scene, this.camera)
    },

    onWindowResize() {
      const container = this.$refs.container
      const width = container.clientWidth
      const height = container.clientHeight

      this.camera.aspect = width / height
      this.camera.updateProjectionMatrix()

      this.renderer.setSize(width, height)
      this.labelRenderer.setSize(width, height)
    }
  }
}
</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;
}
</style>
