<script setup lang="ts">
import { ref, onMounted, onUnmounted, shallowRef, nextTick } from "vue";
import { useI18n } from 'vue-i18n'

import gsap from 'gsap';
import * as THREE from 'three';
import { initThree,clearModel,addModel,getModelInfo,calculateCameraPosition } from './threeTool'

//const props = defineProps({
//})
//const emit = defineEmits([
//])

const threeDom = ref()//threeDom元素

let scene = shallowRef()//场景
let group = shallowRef()//组
let camera = shallowRef()//相机
let renderer = shallowRef()//渲染器
let pointLight = shallowRef();//光
let ambient = shallowRef()//环境光
let controls = shallowRef()//监听鼠标、键盘事件

const animationId = ref(null);
//加载进度
const load = ref({
	state:false,
	progress:0
})
// const textureLoader = ref(new THREE.TextureLoader())//材质
const init = () => {
    //初始化threejs
    if (scene.value) return
    const initResult = initThree(threeDom.value)
    scene.value = initResult.scene
    group.value = initResult.group
    camera.value = initResult.camera
    renderer.value = initResult.renderer
    ambient.value = initResult.ambient
    controls.value = initResult.controls
    pointLight.value = initResult.pointLight

    threeDom.value.ondblclick = (event:any)=>{
        let intersects = openModel(event);
        if(!intersects || intersects.length<=0) return
        
        const clickedObject = intersects[0].object;
        const modelInfo = getModelInfo(clickedObject);
        const { size } = modelInfo;
        const maxSize = Math.max(size.x, size.y, size.z);
        let distanceFactor = 1.2;
        let heightFactor = 0.3;
        let angle = 0;
        if (size.y > size.x * 2) {
            // 高瘦物体，拉远一点，稍微抬高视角
            distanceFactor = 1.5;
            heightFactor = 0.4;
            angle = Math.PI / 6; // 30度
        } else if (size.x > size.y * 2) {
            // 扁平物体，降低视角
            heightFactor = 0.2;
            angle = Math.PI / 8; // 22.5度
        }
        const { position: cameraPos, target } = calculateCameraPosition(
            modelInfo,
            camera.value,
            {
                distanceFactor,
                heightFactor,
                angle
            }
        );
        // 执行相机动画
        animateCamera(
            camera.value.position,
            cameraPos,
            controls.value.target,
            target
        );
    }
}

let openModel = (event:any)=>{
	let mouse = new THREE.Vector2();
	let raycaster = new THREE.Raycaster();
	mouse.x=(event.clientX/window.innerWidth)*2-1;
	mouse.y=-(event.clientY/window.innerHeight)*2+1;
	raycaster.setFromCamera(mouse, camera.value);
	let intersects = raycaster.intersectObjects(scene.value.children);
	return intersects
}
let isTweening = false;

function animateCamera(
    startCameraPos: THREE.Vector3,
    endCameraPos: THREE.Vector3,
    startTarget: THREE.Vector3,
    endTarget: THREE.Vector3
) {
    if (isTweening) return;
    isTweening = true;
    
    let options = {
        cx: startCameraPos.x,
        cy: startCameraPos.y,
        cz: startCameraPos.z,
        tx: startTarget.x,
        ty: startTarget.y,
        tz: startTarget.z
    };
    
    gsap.to(options, {
        cx: endCameraPos.x,
        cy: endCameraPos.y,
        cz: endCameraPos.z,
        tx: endTarget.x,
        ty: endTarget.y,
        tz: endTarget.z,
        duration: 1,
        ease: 'power2.inOut', // 使用更自然的缓动
        onUpdate: () => {
            camera.value.position.set(options.cx, options.cy, options.cz);
            controls.value.target.set(options.tx, options.ty, options.tz);
            controls.value.update();
        },
        onComplete: () => {
            isTweening = false;
        }
    });
}
const setModel = async (url:any)=>{
	clearModel(group,scene)
	await addModel(url,controls,camera,pointLight,group,load)
	// addMaterial()
}
const open = async (url)=>{
	load.value.state = true
	await nextTick(()=>{
		init()
	})
	controls.value.enableDamping = true;
	let animate =  ()=>{
		animationId.value = requestAnimationFrame(animate);
		// renderer.value.render(scene.value, camera.value);
		// model.rotation.x += 0.01; //旋转物体
		var vector = camera.value.position.clone()
		controls.value.update();
		renderer.value.render(scene.value, camera.value);
		// point.position.set(vector.x,vector.y,vector.z);
		// group.rotation.y += 0.01; 
		// composer.render();
	};
	animate();
	await setModel(url)
	load.value.state = false
}

onMounted(()=>{
})
onUnmounted(()=>{
})
defineExpose({open})
</script>
<template>
	<div class="modelBox">
		<div class="model" ref="threeDom">
		</div>
		<div class="icon" v-show="!load.state">
			<SvgIcon name="threeLogo" size="40" size-unit="px" />
		</div>
		<div class="load" v-show="load.state">
			<i class="fi fi-rr-cubes"></i>
			<div class="text">
				<img src="@/assets/images/threeLoading.png" alt="">
				{{ $t('threeModel.loading') }}
			</div>
			<div class="loadBox">
				<div class="schedule" :style="{width:load.progress+'%'}"></div>
			</div>
		</div>
	</div>
	
</template>
<style lang="less" scoped>
	.modelBox{
		width: 100%;
		height: 100%;
		position: relative;
		>.model{
			width: 100%;
			height: 100%;
			position: relative;
			background-color: #f5f5f5;
			border-radius: 1rem;
			border: 1px solid #D9D9D9;
			overflow: hidden;
		}
		> .icon{
			position: absolute;
			bottom: 2.4rem;
			right: 2.4rem;
		}
		> .load{
			position: absolute;
			width: 100%;
			height: 100%;
			top: 0;
			left: 0;
			background: #e6e6e6;
			display: flex;
			align-items: center;
			justify-content: center;
			flex-direction: column;
			color: #fff;
			> .text{
				font-weight: 500;
				font-size: 1.8rem;
				line-height: 100%;
				display: flex;
				align-items: center;
				justify-content: center;
				color: #747474;
				> img{
					margin-right: 1rem;
				}
			}
			> i{
				font-size: 3rem;
			}
			> .loadBox{
				width: 26rem;
				height: 1rem;
				border-radius: 3.3rem;
				background: #fff;
				overflow: hidden;
				margin-top: 1.2rem;
				> .schedule{
					height: 100%;
					border-radius: 3.3rem;
					background: #848484;
				}
			}
		}
	}
	
</style>