import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'

export const initThree = (threeDom)=>{
	const scene = new THREE.Scene();
	const group = new THREE.Group()
	scene.add(group)

	//创建相机对象
	// this.camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
	const camera = new THREE.PerspectiveCamera(45, threeDom.offsetWidth / threeDom.offsetHeight, 0.1, 10000);
	camera.position.set(0, 90, 6); //设置相机位置
	camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
		/**
	 * 创建渲染器对象
	 */
		let width = threeDom.offsetWidth; //窗口宽度
	let height = threeDom.offsetHeight; //窗口高度
	const renderer = new THREE.WebGLRenderer({
		antialias: true,
		logarithmicDepthBuffer: true,//深度缓存 防止模型闪烁重影
	});

	renderer.toneMapping = THREE.ACESFilmicToneMapping;//设置色调
	renderer.toneMappingExposure = 1.3;

	renderer.shadowMap.enabled = true;
	renderer.setPixelRatio(window.devicePixelRatio);
	renderer.setSize(width, height); //设置渲染区域尺寸
	renderer.setClearColor(0xffffff, 1); //设置背景颜色 
	threeDom.innerHTML = '';
	threeDom.appendChild(renderer.domElement);

	// 设置渲染器大小
	//环境光
	let ambient = new THREE.AmbientLight(0xffffff,.8);
	scene.add(ambient);
	let controls = new OrbitControls(camera,renderer.domElement)//监听鼠标、键盘事件;
	// controls.minDistance = 500; // 设置相机与焦点的最小距离
	// controls.maxDistance = 4000; // 设置相机与焦点的最大距离
	controls.mouseButtons = {
		// LEFT:THREE.MOUSE.PAN, // 左键 拖动(默认旋转：ROTATE)
		LEFT:THREE.MOUSE.ROTATE, // 左键 拖动(默认旋转：ROTATE)
		MIDDLE:THREE.MOUSE.DOLLY, // 滑轮 缩放
		RIGHT:THREE.MOUSE.PAN // 右键 旋转（默认拖动：PAN）
		// RIGHT:THREE.MOUSE.ROTAafTE // 右键 旋转（默认拖动：PAN）
	}
	/**
	 * 光源设置
	 */
	//点光源
	/**
	 * AmbientLight	环境光
		PointLight	点光源
		DirectionalLight	平行光，比如太阳光
		SpotLight	聚光源
		*/
	//设置环境光全亮
	const pointLight = new THREE.AmbientLight(0xffffff,.2);
	scene.add(pointLight);
	// const pointLight = new THREE.AmbientLight(0xffffff,1.0);
	// pointLight.intensity = 1.2//光源强度
	// pointLight.castShadow = true//开启阴影
	// pointLight.shadow.mapSize = new THREE.Vector2(width, height)
	// scene.add(pointLight); //点光源添加到场景中
	// pointLight.position.set(400, 200, 300); //点光源位置
	// pointLight.position.y = 100;
	// pointLight.position.z = 50;
	// pointLight.position.x = 100;

	// let floorGeometry = new THREE.PlaneGeometry(5000, 3000)//地板大小
	// let floorMaterial = new THREE.MeshPhongMaterial({ color: "#7e7ab0", })
	// let floorMesh = new THREE.Mesh(floorGeometry, floorMaterial);
	// floorMesh.rotation.x = -0.5 * Math.PI;
	// floorMesh.receiveShadow = true;
	// floorMesh.position.y = -0.001;
	// scene.add(floorMesh);
	const textureLoader = new THREE.TextureLoader();
	// const texture = textureLoader.load('/3dModel/sketch-thick.jpg');
	scene.background = new THREE.Color("#fff");
	return {scene,group,camera,renderer,ambient,controls,pointLight}
}
export const clearModel = (group,scene)=>{
	const oldGroup:any = group.value;
	group.value = new THREE.Group();
	scene.value.add(group.value);
	scene.value.remove(oldGroup);
}

// 计算模型包围盒
export const getModelInfo = (model: THREE.Object3D) => {
    const box = new THREE.Box3().setFromObject(model);
    const center = box.getCenter(new THREE.Vector3());
    const size = box.getSize(new THREE.Vector3());
    const maxSize = Math.max(size.x, size.y, size.z);
    return {
        box,
        center,
        size,
        maxSize
    };
};
// 根据模型信息计算相机位置
export const calculateCameraPosition = (
    modelInfo: ReturnType<typeof getModelInfo>,
    camera: THREE.PerspectiveCamera,
    options?: {
        distanceFactor?: number;  // 距离系数，默认1.5
        heightFactor?: number;    // 高度偏移系数，默认0.3
        angle?: number;           // 观察角度，默认正前方
    }
) => {
    const { center, size, maxSize } = modelInfo;
    const fov = camera.fov * (Math.PI / 180);
    
    const distanceFactor = options?.distanceFactor ?? 1.5;
    const heightFactor = options?.heightFactor ?? 0.3;
    
    // 计算合适的相机距离
    const distance = (maxSize / 2) / Math.tan(fov / 2) * distanceFactor;
    
    // 根据角度计算相机位置
    const angle = options?.angle ?? 0; // 0表示正前方
    
    return {
        position: new THREE.Vector3(
            center.x + distance * Math.sin(angle),
            center.y + size.y * heightFactor,
            center.z + distance * Math.cos(angle)
        ),
        target: center.clone(),
        distance,
        center,
        size
    };
};
// 根据模型信息计算光源位置
export const calculateLightPosition = (
    modelInfo: ReturnType<typeof getModelInfo>,
    options?: {
        xFactor?: number;  // X轴偏移系数，默认0.5
        yFactor?: number;  // Y轴偏移系数，默认0.8
        zFactor?: number;  // Z轴偏移系数，默认0.5
    }
) => {
    const { center, size } = modelInfo;
    
    const xFactor = options?.xFactor ?? 0.5;
    const yFactor = options?.yFactor ?? 0.8;
    const zFactor = options?.zFactor ?? 0.5;
    
    return new THREE.Vector3(
        center.x + size.x * xFactor,
        center.y + size.y * yFactor,
        center.z + size.z * zFactor
    );
};
export const addModel = async (
    url: any,
    controls: OrbitControls,
    camera: THREE.PerspectiveCamera,
    pointLight: THREE.DirectionalLight,
    group: THREE.Group,
    load: any
) => {
    await new Promise((resolve, reject) => {
        var fbxLoader = new GLTFLoader();
        let drac = new DRACOLoader()
        drac.setDecoderPath('/draco/')
        fbxLoader.setDRACOLoader(drac)
        
        fbxLoader.load(url,
            (obj: any) => {
                let scene = obj.scene;
				scene.traverse((child: any) => {
                    if (child.isMesh) {
                        // 如果是基础材质，转换为标准材质
                        if (child.material instanceof THREE.MeshBasicMaterial) {
                            const oldMat = child.material;
                            child.material = new THREE.MeshStandardMaterial({
                                map: oldMat.map,
                                color: oldMat.color,
                                roughness: 0.4,
                                metalness: 0
                            });
                        } 
                        // 如果是标准材质，调整粗糙度
                        else if (child.material instanceof THREE.MeshStandardMaterial) {
                            child.material.roughness = 0.4;
                            child.material.metalness = 0;
                        }
                    }
                });
                // 获取模型信息
                const modelInfo = getModelInfo(scene);
                const { position: cameraPos, target } = calculateCameraPosition(
                    modelInfo,
                    camera.value,
                    {
                        distanceFactor: 1.5,
                        heightFactor: 0.3,
                        angle: 0 // 正前方
                    }
                );
                // 设置相机位置
                camera.value.position.copy(cameraPos);
                // 设置控制器目标点
                controls.value.target.copy(target);
                // 计算并设置光源位置
                const lightPos = calculateLightPosition(modelInfo);
                pointLight.value.position.copy(lightPos);
                // 将模型添加到场景
                group.value.add(scene);
                // 可选：将模型信息存储在模型上，方便后续使用
                (scene as any).userData.modelInfo = modelInfo;
                
                resolve('')
            },
            (xhr: any) => { // 加载进度回调
                const percent = xhr.total == 0 ? 100 : (xhr.loaded / xhr.total * 100).toFixed(2);
                load.value.progress = percent
                console.log('模型加载进度:', percent);
            },
            (error: any) => { // 加载失败回调
                console.error('模型加载失败:', error);
                reject('')
            }
        )
    })
}