<template>
  <div :id="id" class="container">
    <SimpleLoading v-if="loading" />


  </div>
</template>

<script setup lang="ts">
import { RandomUtils } from '@imengyu/imengyu-utils';
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { nextTick, onBeforeUnmount, onMounted, ref } from 'vue';
import SimpleLoading from '../small/SimpleLoading.vue';

const id = RandomUtils.genNonDuplicateIDHEX(12);
let renderer : THREE.WebGLRenderer|undefined;
let scene : THREE.Scene|undefined;
let camera : THREE.Camera|undefined;
let controls : OrbitControls|undefined;
const loader = new GLTFLoader();
const props = defineProps({
  path: {
    type: String,
    default: ''
  }
})

function init() {
  const container = document.getElementById(id);
  if (!container) {
    console.error('container not found');
    return;
  }

  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera( 75, container.clientWidth / container.clientHeight, 0.1, 1000 );
  camera.position.set(10, 10, 10);

  const color = 0xFFFFFF;
  const light0 = new THREE.AmbientLight(color, 1);
  scene.add(light0);


  const light = new THREE.DirectionalLight(color, 5);
  light.position.set(0, 15, -20);
  light.target.position.set(0, 0, 0);
  scene.add(light);
  scene.add(light.target);

  const light2 = new THREE.DirectionalLight(color, 5);
  light2.position.set(0, 15, 20);
  light2.target.position.set(0, 0, 0);
  scene.add(light2);
  scene.add(light2.target);

  function animate() {
    if (controls)
      controls.update();
    if (renderer && scene && camera)
      renderer.render(scene, camera);
  }

  renderer = new THREE.WebGLRenderer({ alpha: true });
  renderer.setAnimationLoop(animate);
  renderer.setSize(container.clientWidth, container.clientHeight);

  controls = new OrbitControls(camera, renderer.domElement);
  controls.autoRotate = true;
  controls.autoRotateSpeed = 1;
  controls.update();

  container.appendChild(renderer.domElement);

  setTimeout(() => {
    if (props.path)
      loadPath(props.path);
    else {
      const geometry = new THREE.BoxGeometry( 1, 1, 1 );
      const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
      const cube = new THREE.Mesh( geometry, material );
      scene!.add( cube );
    }
  }, 200);
}

const loading = ref(false);

function loadPath(path: string) {
  console.log('load model', path);
  loading.value = true;
  return new Promise<void>((resolve, reject) => {
    if (!scene) {
      reject('scene not init');
      return;
    }
    loader.load(path, function ( gltf ) {
      if (!scene) {
        reject('scene not init');
        return;
      }

      const model = gltf.scene;
      if (!camera) {
        reject('camera not init');
        return;
      }

      scene.add(model)

      // 计算包围盒
      const box = new THREE.Box3().setFromObject(model);
      const size = box.getSize(new THREE.Vector3());
      const center = box.getCenter(new THREE.Vector3());

      // 调整模型位置（可选：让模型居中）
      model.position.sub(center);

      // 计算摄像机距离
      const maxDim = Math.max(size.x, size.y, size.z);
      const fov = 60 * (Math.PI / 180);
      let cameraZ = Math.abs(maxDim / 2 / Math.tan(fov / 2));

      // 设置摄像机
      camera.position.set(0, 0, cameraZ);
      camera.lookAt(0, 0, 0);

      if (controls) {
        controls.target.set(0, 0, 0);
        controls.update();
      }

      resolve();
    }, undefined, reject);
  }).finally(() => {
    loading.value = false;
  });
}

defineExpose({
  loadPath,
})

onBeforeUnmount(() => {
  if (renderer) {
    renderer.setAnimationLoop(null);
    renderer = undefined;
  }
});
onMounted(() => {
  nextTick(init);
});
</script>

<style scoped lang="scss">
.container {
  width: 100%;
  height: 100%;
  position: relative;

  :deep(.simple-loading) {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
}
</style>
