<template>
  <div class="div3D" ref="div3D" v-loading="loading" element-loading-text="渲染模型..."></div>

  <!-- 固定位置的控制按钮 -->
  <div class="control-buttons">
    <el-button
      type="warning"
      @click="tranlate(new Vector3(28, 10, -10), new Vector3(0, 0, 0))"
      :icon="Refresh"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
//导入 threejs
import {
  AxesHelper,
  Color,
  PerspectiveCamera,
  Scene,
  WebGLRenderer,
  EquirectangularReflectionMapping,
  Group,
  Vector3,
  AmbientLight,
  DirectionalLight,
  PointLight
} from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
import gsap from 'gsap';
import { Star, Bell, MagicStick, Refresh, Compass } from '@element-plus/icons-vue';

const loading = ref(true); // 添加 loading 状态
const div3D = ref<HTMLDivElement>();
//场景
const scene = new Scene();

//相机
const camera = new PerspectiveCamera(
  45,
  div3D.value?.clientWidth! / div3D.value?.clientHeight!,
  0.05,
  200
); // 初始比例设为1
camera.position.set(30, 15, -15);
camera.lookAt(0, 0, 0);
scene.add(camera);

//渲染器
const render = new WebGLRenderer({
  antialias: true, // 关闭抗锯齿提升性能
  powerPreference: 'high-performance', // 使用高性能GPU
  stencil: false, // 如果不需要模板缓冲区
  depth: true,
  logarithmicDepthBuffer: true // 对大场景有帮助
});
render.setClearColor(new Color('#131519'));
// 启用渲染优化
render.shadowMap.enabled = false; // 如果不需要阴影

//添加控制器
const controls = new OrbitControls(camera, render.domElement);
// 禁用滚轮缩放
// controls.enableZoom = false;
// controls.autoRotate = false;
// controls.enablePan = false; // 禁用右键平移
controls.autoRotateSpeed = 1;
controls.dampingFactor = 0.2;
controls.rotateSpeed = 0.3; // 降低旋转速度（默认为 1.0）
controls.enableDamping = true;
controls.enableRotate = true;
controls.minDistance = 1; // 允许更近距离观察模型细节
// 设置视角限制：向上45度，向下45度
// 从正前方开始计算，向上最大45度，向下最大45度
controls.minPolarAngle = Math.PI / 4; // 向上最多45度 (π/4)
controls.maxPolarAngle = (Math.PI * 3) / 4; // 向下最多45度 (3π/4)

// 大场景优化配置
const startTime = Date.now();
const loader = new GLTFLoader();
const dracoLoader = new DRACOLoader();
loader.setDRACOLoader(dracoLoader);
let meshArr: Group[] = [];
// public\models\nitrogenInjection\nitrogenInjection.gltf
loader.load('/models/substation/substation.gltf', (gltf: any) => {
  // 保存模型引用
  loadedModel = gltf.scene;
  scene.add(gltf.scene);
  const loadTime = Date.now() - startTime;

  // 立即渲染一帧
  // controls.update();
  render.render(scene, camera);

  console.log(`大场景模型已加载并显示，总耗时：${loadTime}ms`);
  loading.value = false;
});

// // 环境光：增强整体亮度
// 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 rgbELoader = new RGBELoader().load(
  '/models/texture/Alex_Hart-Nature_Lab_Bones_2k.hdr',
  (envMap: any) => {
    envMap.mapping = EquirectangularReflectionMapping;
    scene.environment = envMap;
    envMapTexture = envMap; // 保存引用
  }
);

//补间动画
const timeline1 = gsap.timeline();
const timeline2 = gsap.timeline();

// 保存模型引用以便清理
let loadedModel: any = null;
let envMapTexture: any = null;

//相机移动
function tranlate(position: Vector3, target: Vector3) {
  timeline1.to(camera.position, {
    x: position.x,
    y: position.y,
    z: position.z,
    duration: 1,
    ease: 'power2.inOut'
  });

  timeline2.to(controls.target, {
    x: target.x,
    y: target.y,
    z: target.z,
    duration: 1,
    ease: 'power2.inOut'
  });
}

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

// 监听容器大小变化
function handleResize() {
  if (!div3D.value) return;

  const container = div3D.value;
  const width = container.clientWidth;
  const height = container.clientHeight;

  // 更新相机比例
  camera.aspect = width / height;
  camera.updateProjectionMatrix();

  // 更新渲染器大小
  render.setSize(width, height);
}

function init() {
  requestAnimationFrame(init);
  controls.update();
  render.render(scene, camera);
}

onMounted(() => {
  // 初始化时设置正确大小
  handleResize();

  // 启动渲染循环
  init();

  // 将渲染器添加到容器
  div3D.value?.appendChild(render.domElement);

  // 添加容器大小监听
  const resizeObserver = new ResizeObserver(handleResize);
  if (div3D.value) {
    resizeObserver.observe(div3D.value);
  }

  // 保存观察器引用以便销毁
  (window as any)._resizeObserver = resizeObserver;
});

onUnmounted(() => {
  console.log('开始清理 Three.js 资源...');

  // 1. 停止渲染循环（通过标记）
  // requestAnimationFrame 会自动停止

  // 2. 清理 ResizeObserver
  if ((window as any)._resizeObserver) {
    (window as any)._resizeObserver.disconnect();
    delete (window as any)._resizeObserver;
  }

  // 3. 停止 GSAP 动画
  timeline1.pause();
  timeline1.clear();
  timeline2.pause();
  timeline2.clear();
  gsap.globalTimeline.clear();

  // 4. 移除 DOM 元素
  if (div3D.value && render.domElement.parentNode === div3D.value) {
    div3D.value.removeChild(render.domElement);
  }

  // 5. 清理控制器
  controls.dispose();

  // 6. 清理模型
  if (loadedModel) {
    loadedModel.traverse((child: any) => {
      if (child.isMesh) {
        // 清理几何体
        if (child.geometry) {
          child.geometry.dispose();
        }

        // 清理材质
        if (child.material) {
          const materials = Array.isArray(child.material) ? child.material : [child.material];

          materials.forEach((material: any) => {
            // 清理材质属性
            [
              'map',
              'normalMap',
              'roughnessMap',
              'metalnessMap',
              'emissiveMap',
              'aoMap',
              'displacementMap'
            ].forEach((key) => {
              if (material[key]) {
                material[key].dispose();
              }
            });

            // 清理材质本身
            material.dispose();
          });
        }
      }
    });

    // 从场景中移除模型
    scene.remove(loadedModel);
  }

  // 7. 清理环境贴图
  if (envMapTexture) {
    envMapTexture.dispose();
  }

  // 8. 清理灯光
  scene.traverse((child: any) => {
    if (child.isLight) {
      child.dispose();
    }
  });

  // 9. 清理场景
  while (scene.children.length > 0) {
    scene.remove(scene.children[0]);
  }

  // 10. 清理渲染器
  render.dispose();
  render.forceContextLoss();
  render.domElement.remove();

  // 11. 清空场景引用
  scene.clear();

  console.log('Three.js 资源清理完成');
});
</script>

<style scoped>
.div3D {
  margin: 0;
  padding: 0;
  /* width: 500px;
  height: 500px; */
  width: 100%;
  height: 100%;
  position: relative;
}

.control-buttons {
  position: absolute;
  top: 50%;
  left: 2%;
  transform: translateY(-50%); /* 垂直居中 */
  transform: translateZ(0);
  display: flex;
  flex-direction: column;
  gap: 20px;
  z-index: 100;
  align-items: flex-start; /* 确保所有按钮左对齐 */
}
</style>
