<template>
  <div ref="containerRef" class="container"></div>
</template>

<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from 'vue';
import {
  AxesHelper,
  Color,
  PerspectiveCamera,
  Scene,
  WebGLRenderer,
  AmbientLight,
  DirectionalLight,
  PointLight,
  MeshStandardMaterial,
  Vector2,
  Raycaster,
  CanvasTexture,
  SpriteMaterial,
  Sprite,
  Box3,
  Vector3,
  HemisphereLight
} from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { GLTFLoader, GLTF } from 'three/examples/jsm/loaders/GLTFLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';

const containerRef = ref<HTMLDivElement>();

// 场景
const scene = new Scene();

// 创建摄像机
const camera = new PerspectiveCamera(
  45,
  containerRef.value?.clientWidth! / containerRef.value?.clientHeight!,
  0.1,
  1000
);
camera.position.set(-10, 10, 20);
camera.lookAt(scene.position);

// 渲染器
const renderer = new WebGLRenderer({
  antialias: true, // 启用抗锯齿
  alpha: true, // 启用透明背景
  preserveDrawingBuffer: true // 保持绘图缓冲区
});
renderer.setClearColor(new Color('#131519'));
renderer.setSize(containerRef.value?.clientWidth!, containerRef.value?.clientHeight!);
renderer.shadowMap.enabled = true;
renderer.setPixelRatio(window.devicePixelRatio || 1); // 设置像素比率

// 轨道摄像机
const orbitControls = new OrbitControls(camera, renderer.domElement);
orbitControls.autoRotate = false;
orbitControls.autoRotateSpeed = 5;
orbitControls.dampingFactor = 0.1;
orbitControls.enableDamping = true;
orbitControls.enableRotate = true;
orbitControls.minDistance = 10;
orbitControls.maxPolarAngle = Math.PI * 0.5;

// 物体
scene.add(new AxesHelper(20));

// 环境光：增强整体亮度
const ambientLight = new AmbientLight('#ffffff', 1.2); // 强度从 0.6 提高到 1.0
scene.add(ambientLight);

// 平行光
const directionalLight = new DirectionalLight('#ffffff', 1.4); // 强度从 0.2 提高到 0.8
scene.add(directionalLight);
directionalLight.position.set(20, 20, 10);

// // 点光源
const pointLight = new PointLight('#ffffff', 1.4, 1800); // 强度从 0.5 提高到 1.0
scene.add(pointLight);
pointLight.position.set(0, 40, 0);

// 创建一个悬浮的框
const canvas = document.createElement('canvas');
canvas.width = 250;
canvas.height = 250;
const ctx = canvas.getContext('2d');
if (ctx) {
  ctx.fillStyle = 'rgba(0,0,0,.7)';
  ctx.fillRect(0, 0, 200, 100);
  ctx.fillStyle = 'white';
  ctx.font = '21px 黑体';
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  ctx.fillText('遥测：100111', 100, 30);
  ctx.fillText('温度：25℃', 90, 65);
}
const scaleFactor = 5;
const texture = new CanvasTexture(canvas);
const material = new SpriteMaterial({ map: texture });

const sprite1 = new Sprite(material);
sprite1.scale.set(scaleFactor, scaleFactor, scaleFactor);
sprite1.position.set(-9.644502679789724, 5.815449539931501 + 0.5, 21.66345220492572);

function animate() {
  requestAnimationFrame(animate);
  orbitControls.update();
  renderer.render(scene, camera);
}

const arr = [
  'Layer0073',
  'Layer0043',
  'Layer0097',
  'Layer0098',
  'Layer0096',
  'Layer0099',
  'Layer00100',
  'Layer0095',
  'Layer0072'
];

let pitchObj = ref<any>();
let pitchMaterial = ref<any>();

// ResizeObserver 监听容器尺寸变化
let resizeObserver: ResizeObserver | null = null;

onMounted(() => {
  const container = containerRef.value!;
  container.appendChild(renderer.domElement);

  // 初始化摄像机和渲染器尺寸
  camera.aspect = container.clientWidth / container.clientHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(container.clientWidth, container.clientHeight);

  // 监听容器尺寸变化
  resizeObserver = new ResizeObserver(() => {
    camera.aspect = container.clientWidth / container.clientHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(container.clientWidth, container.clientHeight);
  });
  resizeObserver.observe(container);

  const loader = new GLTFLoader();
  const dracoLoader = new DRACOLoader();
  loader.setDRACOLoader(dracoLoader);
  loader.load('/models/pipeline/new_model.glb', (gltf: GLTF) => {
    gltf.scene.children.forEach((child) => {
      console.log(child.name, child);
      //特殊处理平面
      if (child.name === '平面') {
        child.position.set(child.position.x, child.position.y - 45, child.position.z);
        child.material = new MeshStandardMaterial({
          color: new Color('#FFFFFF')
        });
      }
      if (child.children && child.children.length > 0) {
        child.traverse((child1: any) => {
          if (child1.isMesh && arr.includes(child1.name)) {
            const box = new Box3().setFromObject(child1);
            const worldPosition = new Vector3();
            child1.getWorldPosition(worldPosition);

            const sprite = new Sprite(material.clone());
            sprite.scale.set(scaleFactor, scaleFactor, scaleFactor);
            sprite.position.set(
              worldPosition.x * 0.05,
              (worldPosition.y + box.min.y / 4) * 0.05,
              worldPosition.z * 0.05
            );

            scene.add(sprite);
          }
        });
      }
    });

    gltf.scene.scale.set(0.05, 0.05, 0.05);
    scene.add(gltf.scene);
  });

  // 创建射线检测器
  const raycaster = new Raycaster();
  const mouse = new Vector2();

  // 添加点击事件监听
  renderer.domElement.addEventListener('mousedown', (event: MouseEvent) => {
    const rect = container.getBoundingClientRect();
    const x = event.clientX - rect.left;
    const y = event.clientY - rect.top;

    mouse.x = (x / container.clientWidth) * 2 - 1;
    mouse.y = -(y / container.clientHeight) * 2 + 1;

    raycaster.setFromCamera(mouse, camera);

    const intersects = raycaster.intersectObjects(scene.children, true);
    console.log(intersects);
    if (intersects.length > 0) {
      console.log('点击了物体', intersects[0].object.name);
      if (arr.includes(intersects[0].object.name)) {
        if (pitchObj.value) pitchObj.value.material = pitchMaterial.value;

        pitchObj.value = intersects[0].object;
        pitchMaterial.value = intersects[0].object.material.clone();
        console.log(intersects[0]);
        intersects[0].object.material = new MeshStandardMaterial({
          color: new Color('#973939')
        });
      } else {
        if (pitchObj.value && pitchMaterial.value) pitchObj.value.material = pitchMaterial.value;
      }
    }
  });

  animate();
});

onUnmounted(() => {
  if (resizeObserver) {
    resizeObserver.disconnect();
    resizeObserver = null;
  }
});
</script>

<style scoped>
.container {
  width: 100%;
  height: 100%;
}
</style>
