// var app = getApp(); //获取应用实例
// const util = require('@/static/utils/util.js');
// const config = require('@/services/urlConfig.js');
// import requestConfig from '@/services/requestConfig.js';
import * as THREE from 'three';
import TWEEN from 'three/addons/libs/tween.module.js';
let glbWidth = 300;//空间地板模型的真实尺寸
let glbHeight = 300;
export default {
	data() {
		return {
			gltfSpaceUrl: "https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_WoodFloor1.glb", //模型地址
			// gltfSpaceUrl: "https://dm.static.elab-plus.com/3d/model/20230607/diban/diban.gltf", //模型地址
			// gltfSpaceUrl: "https://dm.static.elab-plus.com/miniProgram/model/BP_L_carpet01-1.gltf", //模型地址
			// gltfSpace1Url: "https://dm.static.elab-plus.com/miniProgram/model/BP_G_tiles01_1.gltf", //模型地址
			gltfSpace1Url: "https://dm.static.elab-plus.com/miniProgram/model/BP_G_tiles01.glb", //模型地址
			instancedSpaceMeshList:[],//地板实例对象 当地板复杂是就会存在多个
			spaceTypes : ["卧室","客厅","餐厅","厨房","玄关","卫生间","衣帽间","收纳","阳台","飘窗","链接空间","自定义","楼梯","花园"],
		}
	},
	watch: {},
	methods: {
		// 加载地板模型
		loaderSpaceArr(list){
			if(!list || list.length==0){
				return false;
			}
			this.instancedSpaceMeshList = [];
			this.gltfSpaces = [];
			let comlist = list.filter(it=>it.spaceType!=14);//过滤花园的空间
			this.loaderCommonSpace(this.gltfSpaceUrl,comlist,1);
			let arrlist = list.filter(it=>it.spaceType==14);//花园的空间
			// this.loaderCommonSpace(this.gltfSpace1Url,arrlist,2);
			if(arrlist && arrlist.length>0){
				this.loaderGraseSpace(list);//加载草地的模型-所有地块都添加，填补房间里面的
			}
		},
		loaderCommonSpace(gltfSpaceUrl,list,type=1){
			var that = this;
			this.loader.load(gltfSpaceUrl,  ( gltf ) => {
				console.log("地板模型加载成功",list)
				// gltf.scene.receiveShadow = true;//材质是否接收阴影
				gltf.scene.traverse((child)=> {
					if (child.isMesh && child.visible) {
						let instancedMesh = new THREE.InstancedMesh(child.geometry.clone(), child.material.clone(), list.length);
						this.instancedSpaceMeshList.push(instancedMesh);
						//设置每一块地板的实例值
						list.forEach((obj,i)=>{
							let positionX = obj.centerX / 100;
							let positionY = obj.centerY / 100;
							if(type==1){
								// glbWidth = glbHeight = 1500;
							}
							let scaleX = obj.spaceWidth / glbWidth;
							let scaleY = obj.spaceHeight / glbHeight;
							
							gltf.scene.position.set(positionX, 0, -positionY);
							gltf.scene.scale.set(scaleX, 1, scaleY); 
							gltf.scene.updateMatrixWorld();//更新世界坐标-这样，子模型也同步更新了
							
							instancedMesh.setMatrixAt(i, child.matrixWorld);
							instancedMesh.instanceMatrix.needsUpdate = true;
							instancedMesh.setColorAt(i, child.material.color);
							instancedMesh.instanceColor.needsUpdate = true;//打开颜色修改开关,不开，颜色是不能修改额
							let gltfSpace = that.gltfSpaces.find(gltfSpace=>gltfSpace.spaceId == obj.spaceId);//判断是否已经添加过
							if(!gltfSpace){
								let position = new THREE.Vector3();//当前几何体的位置参数
								let scale = new THREE.Vector3();//当前几何体的缩放参数
								position.set(positionX, 0, -positionY);
								scale.set(scaleX, 1, scaleY); 
								let md = {
									spaceId:obj.spaceId,//模型实例的唯一标识
									instancedMeshIndexList:[//标识网格实例数组的序号 以及 当前几何体 在网格实例的序号
										{instancedMeshIndex: this.instancedSpaceMeshList.length - 1, instancedAtIndex : i},
									],
									spaceName:obj.spaceName,//几何体的id
									spaceType:obj.spaceType,
									position:position,
									scale:scale,
									isSizeLock:obj.isSizeLock,
								};
								that.gltfSpaces.push(md);
							}else{//添加另外一组实例
								gltfSpace.instancedMeshIndexList.push({
									instancedMeshIndex:this.instancedSpaceMeshList.length - 1, instancedAtIndex:i
								})
							}
						})
						instancedMesh.userType = "mesh";
						if(type==2){//花园
							instancedMesh.name = "花园";
						}else{//室内
							instancedMesh.name = "地板";
						}
						instancedMesh.receiveShadow = true;//材质是否接收阴影
						that.scene.add(instancedMesh);
					}
				});
				// this.pvCurPageName=="room_show"
				if(true){
					//给地板模型添加天花板
					list && list.forEach(obj=>{
						if(obj.spaceType!=14){//花园不加上面的墙
							let positionX = obj.centerX / 100;
							let positionY = obj.centerY / 100;
							// 天花板
							const planeGeometry = new THREE.PlaneGeometry(obj.spaceWidth / 100,obj.spaceHeight / 100);
							const planeMaterial = new THREE.MeshStandardMaterial({
							    color:0xffffff,
								metalness: 0.4, // 设置金属度为1.0
								roughness: 1 // 设置粗糙度为0.5
							});
							const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial)
							planeMesh.rotation.x =  Math.PI / 2 ;  // 旋转 180 度
							planeMesh.position.set(positionX, 2.8, -positionY);
							planeMesh.userType = "mesh";
							that.scene.add(planeMesh);
						}
					})
				}
			});
		},
		//草地加载
		loaderGraseSpace(list){
			let glbWidth = 300;
			let glbHeight = 300;
			var that = this;
			console.log("草地模型加载成功",list)
			//将模型添加到场景中
			let texture = new THREE.TextureLoader().load( "https://dm.static.elab-plus.com/miniProgram/grass.jpg");
			// let texture = new THREE.TextureLoader().load( "https://dm.static.elab-plus.com/miniProgram/Avatar_male.png" );
			texture.wrapS = THREE.RepeatWrapping;
			texture.wrapT = THREE.RepeatWrapping;
			
			list && list.forEach(obj=>{
				let positionX = obj.centerX / 100;
				let positionY = obj.centerY / 100;
				let scaleX = obj.spaceWidth / 100;
				let scaleY = obj.spaceHeight / 100;
				
				texture = texture.clone();
				//使用纹理贴图材质
				texture.repeat.set(scaleX, scaleY);
				
				let geometry = new THREE.PlaneGeometry(obj.spaceWidth/100, obj.spaceHeight/100);
				let material = new THREE.MeshBasicMaterial({ map: texture });
				let cube = new THREE.Mesh(geometry, material);
				
				cube.name = "地板";
				cube.userType = "mesh";
				cube.userData = obj;//位置数据
				// 设置位置，旋转，缩放
				cube.position.set(positionX, -0.01, -positionY);
				cube.rotation.x = -Math.PI / 2 ;  // 旋转 180 度
				cube.receiveShadow = true;//材质是否接收阴影
				
				//注释掉，不让草地进入空间列表中，不触发空间变化的动画过程，规避掉动画过程中的问题
				// let md = {
				// 	spaceId:obj.spaceId,//模型实例的唯一标识
				// 	spaceName:obj.spaceName,//几何体的id
				// 	spaceType:obj.spaceType,
				// 	position:cube.position,
				// 	scale:cube.scale,
				// 	isSizeLock:obj.isSizeLock,
				// };
				// that.gltfSpaces.push(md);
				that.scene.add(cube);
			})
		},
		//修改当前空间的面积大小
		changeSpacesAnimOld(curSpace){
			// 寻找地板
			const cube = this.gltfSpaces.find((item)=>{
			    return item.spaceId == curSpace.spaceId;
			})
			console.log("空间移动目标",cube.spaceId, JSON.stringify(cube.position),JSON.stringify(cube.scale),curSpace.toScaleX, curSpace.toScaleZ, curSpace.toPx, curSpace.toPz);
			//获取地板模型的geometry实例
			cube.instancedMeshIndexList.forEach(instanced=>{
				let _index = instanced.instancedMeshIndex;//第一个geometry实例 在 全局InstancedMesh实例的位置
				let instancedMesh = this.instancedSpaceMeshList[_index];//获取具体的网格实例
				let stratMatrix = new THREE.Matrix4();//定义一个四维矩阵
				instancedMesh.getMatrixAt(instanced.instancedAtIndex,stratMatrix);//获取当前几何体的四维矩阵到stratMatrix里面
				
				let endMatrix = stratMatrix.clone();//复制一个四维矩阵 
				let scaleMatrix = new THREE.Matrix4();//定义一个缩放变化矩阵
				let panMatrix = new THREE.Matrix4();//定义一个平移变化矩阵
				
				scaleMatrix.makeScale(curSpace.toScaleX / cube.scale.x,1,curSpace.toScaleZ / cube.scale.z);		//获得缩放变化矩阵
				panMatrix.makeTranslation(curSpace.toPx - cube.position.x,0,curSpace.toPz - cube.position.z);	//获得平移变化矩阵
				endMatrix.multiply(scaleMatrix).premultiply(panMatrix);//通过矩阵计算获得最终的矩阵
				// console.warn("***drawModel-isAnimate-space***",JSON.stringify(endMatrix1),JSON.stringify(endMatrix),JSON.stringify(stratMatrix));
				var tween = new TWEEN.Tween(stratMatrix.elements)
				.to(endMatrix.elements, 2000)
				.easing(TWEEN.Easing.Quadratic.InOut)
				.onUpdate((matrixWorld)=> {
					let m4 = new THREE.Matrix4();//定义一个四维矩阵
					m4.set(...matrixWorld);//注意：四维矩阵的显示和实际计算的行列优先规则不同
					instancedMesh.instanceMatrix.needsUpdate = true;//更新之前，必须开启开关
					instancedMesh.setMatrixAt(instanced.instancedAtIndex,m4.transpose());//更新几何体的世界矩阵
				}).onComplete(()=>{
					instancedMesh.setMatrixAt(instanced.instancedAtIndex,endMatrix);//更新几何体的世界矩阵
					this.tweenCameraAnmaChange(false)
				});
				// 开始动画
				tween.start();
				this.tweenCameraAnmaChange(true)
				cube.position.x = curSpace.toPx;
				cube.position.z = curSpace.toPz;
				cube.scale.x = curSpace.toScaleX;
				cube.scale.z = curSpace.toScaleZ;
			});
		},
		//修改当前空间的面积大小-动画方案2
		changeSpacesAnim(curSpace){
			// 寻找地板
			const cube = this.gltfSpaces.find((item)=>{
			    return item.spaceId == curSpace.spaceId;
			})
			console.log("空间移动目标",cube.spaceId, JSON.stringify(cube.position),JSON.stringify(cube.scale),
			curSpace.toPx, curSpace.toPz,curSpace.toScaleX, curSpace.toScaleZ);
			//初始形变值
			let x = cube.position.x;
			let z = cube.position.z;
			let scaleX = cube.scale.x;
			let scaleZ = cube.scale.z;
			//最终形变值
			let toPx = curSpace.toPx;
			let toPz = curSpace.toPz;
			let toScaleX = curSpace.toScaleX;
			let toScaleZ = curSpace.toScaleZ;
			if(cube.instancedMeshIndexList){
				let spaceInitMatrix = [];//空间动画时的初始变换矩阵
				cube.instancedMeshIndexList.forEach(instanced=>{
					let _index = instanced.instancedMeshIndex;//geometry实例 在 全局InstancedMesh实例的位置
					let instancedMesh = this.instancedSpaceMeshList[_index];//获取具体的网格实例
					let startMatrix = new THREE.Matrix4();//定义一个四维矩阵
					instancedMesh.getMatrixAt(instanced.instancedAtIndex,startMatrix);//获取当前几何体的四维矩阵到stratMatrix里面
					spaceInitMatrix.push({
						index:_index,
						matrix:startMatrix.clone(),
						color:instancedMesh.material.color.clone(),
					})
				});
				// console.warn("***cube***",cube.spaceId,Date.now(),JSON.stringify(spaceInitMatrix[0].matrix))
				var tween = new TWEEN.Tween({
					x: cube.position.x,
					z: cube.position.z,
					sx:cube.scale.x,
					sz:cube.scale.z
				})
				.to({
					x: curSpace.toPx,
					z: curSpace.toPz,
					sx:curSpace.toScaleX,
					sz:curSpace.toScaleZ
				}, 2000)
				.easing(TWEEN.Easing.Quadratic.InOut)
				.onUpdate((object)=> {
					//获取地板模型的geometry实例
					cube.instancedMeshIndexList.forEach(instanced=>{
						let _index = instanced.instancedMeshIndex;//第一个geometry实例 在 全局InstancedMesh实例的位置
						let instancedMesh = this.instancedSpaceMeshList[_index];//获取具体的网格实例
						//获取对象实例的初始变换矩阵
						let tmp = spaceInitMatrix.find(it=>it.index==_index);
						let stratMatrix = tmp.matrix.clone();	//获取初始变换矩阵
						let scaleMatrix = new THREE.Matrix4();	//定义一个缩放变化矩阵
						let panMatrix = new THREE.Matrix4();	//定义一个平移变化矩阵
						
						scaleMatrix.makeScale(object.sx / scaleX,1,object.sz / scaleZ);	//获得缩放变化矩阵
						panMatrix.makeTranslation(object.x - x,0,object.z - z);	//获得平移变化矩阵
						stratMatrix.multiply(scaleMatrix).premultiply(panMatrix);//通过矩阵计算获得最终的形变矩阵
						instancedMesh.instanceMatrix.needsUpdate = true;//更新之前，必须开启开关
						instancedMesh.setMatrixAt(instanced.instancedAtIndex,stratMatrix);//更新几何体的世界矩阵
						if(this.curSpaceObj.spaceId==cube.spaceId){//当前选中的空间才变化颜色
							instancedMesh.instanceColor.needsUpdate = true;//打开颜色修改开关,不开，颜色是不能修改额
							let color = new THREE.Color(0xFF9F40); // 使用sRGB颜色值
							// color.convertSRGBToLinear(); // 将颜色值转换为线性颜色值
							instancedMesh.setColorAt(instanced.instancedAtIndex, color);//修改这个几何体的颜色
						}
					});
				}).onComplete(()=>{//这个回调很可能会很慢
					this.tweenCameraAnmaChange(false);
					console.warn("***changeSpacesAnim-over***")
					if(this.curSpaceObj.spaceId==cube.spaceId){//当前选中的空间才恢复颜色
						cube.instancedMeshIndexList.forEach(instanced=>{
							let _index = instanced.instancedMeshIndex;//第一个geometry实例 在 全局Instance
							let instancedMesh = this.instancedSpaceMeshList[_index];//获取具体的网格实例
							let tmp = spaceInitMatrix.find(it=>it.index==_index);
							instancedMesh.instanceColor.needsUpdate = true;//打开颜色修改开关,不开，颜色是不能修改额
							instancedMesh.setColorAt(instanced.instancedAtIndex, tmp.color);//修改这个几何体的颜色
						});
					}
				});
				// 开始动画
				tween.start();
				this.tweenCameraAnmaChange(true)
				cube.position.x = curSpace.toPx;
				cube.position.z = curSpace.toPz;
				cube.scale.x = curSpace.toScaleX;
				cube.scale.z = curSpace.toScaleZ;
			}else{//有点问题规避下
				// 空间动画
				var tween = new TWEEN.Tween({
					x: scaleX, 
					z: scaleZ, 
					px:x,
					pz:z,
				})
				.to({
					x: toScaleX,
					z: toScaleZ,
					px:toPx,
					pz:toPz,
				}, 2000)
				.easing(TWEEN.Easing.Quadratic.InOut)
				.onUpdate((object)=> {
					cube.scale.x = object.x;
					cube.scale.z = object.z;
					cube.position.x = object.px;
					cube.position.z = object.pz;
				});
				// 开始动画
				tween.start();
			}
		},
		//所有空间整体缩放-同时同步到数据里面
		allSpaceScale(){
			const centerOffset = new THREE.Vector3(0, 0, 0); // 假设中心点在几何体的正中心
			const scale = new THREE.Vector3(0.9, 1, 0.9); // 缩放尺度
			//实例化的默认中心是就原点也就是0 0 0 这个点，所以centerOffset也必须是原点
			// this.instancedMeshList.forEach((mesh)=>{
			// 	mesh.scale.copy(scale);
			// 	mesh.updateMatrix();
			// 	mesh.updateMatrixWorld();
			// 	mesh.updateMorphTargets();
			// 	mesh.geometry.computeVertexNormals();
			// })
			// this.instancedSpaceMeshList.forEach((mesh)=>{
			// 	mesh.scale.copy(scale);
			// 	mesh.updateMatrix();
			// 	mesh.updateMatrixWorld();
			// 	mesh.updateMorphTargets();
			// 	mesh.geometry.computeVertexNormals();
			// })
			// this.gltfLayouts.forEach((mesh)=>{
			// 	// mesh.scale.copy(scale);
			// })
			
			this.gltfSpaces.forEach(cube=>{
				let dis = centerOffset.clone().sub(cube.position);//获得差值向量
				// console.warn("***dis***",JSON.stringify(dis),JSON.stringify(cube.position),cube.spaceId);
				let x = dis.x * (1 - scale.x);//x轴需要移动的距离
				let y = dis.y * (1 - scale.y);//y轴需要移动的距离
				let z = dis.z * (1 - scale.z);//z轴需要移动的距离
				
				let pi = new THREE.Vector3();//新的中心点位置
				pi.x = cube.position.x + x;
				pi.y = cube.position.y + y;
				pi.z = cube.position.z + z;
				cube.scale.x = cube.scale.x * scale.x;//修改真实的比例
				cube.scale.z = cube.scale.z * scale.z;//
				cube.position.copy(pi);
				//同步信息到空间列表中
				let sapce = this.spaceList.find(it=>{ return it.spaceId==cube.spaceId});
				if(sapce){
					//更新空间中心点值
					sapce.centerX = pi.x * 100;
					sapce.centerY = -1* pi.z * 100;
					//更新空间宽度高度值
					sapce.spaceWidth = cube.scale.x * glbWidth;
					sapce.spaceHeight = cube.scale.z * glbHeight;
				}
				// let dir = new THREE.Vector3( 0, 10, 0 );;//当前几何体的位置参数
				// console.warn("***dis1***",JSON.stringify(pi),JSON.stringify(dir));
				// let length = 3;
				// let hex = 0xff0000;
				// let arrowHelper = new THREE.ArrowHelper( dir, pi, length, hex );
				// this.scene.add( arrowHelper );
				
				//这是矩阵运算处理缩放的方法-此为数学上的方案
				cube.instancedMeshIndexList.forEach(instanced=>{
					let _index = instanced.instancedMeshIndex;//第一个geometry实例 在 全局InstancedMesh实例的位置
					let instancedMesh = this.instancedSpaceMeshList[_index];//获取具体的网格实例
					let stratMatrix = new THREE.Matrix4();//定义一个四维矩阵
					instancedMesh.getMatrixAt(instanced.instancedAtIndex,stratMatrix);//获取当前几何体的四维矩阵到stratMatrix里面
					let scaleMatrix = new THREE.Matrix4().makeScale(scale.x, scale.y, scale.z);
					let inverseTranslationMatrix = new THREE.Matrix4().makeTranslation(x, y, z);
					stratMatrix.premultiply(inverseTranslationMatrix);
					stratMatrix.multiply(scaleMatrix);
					instancedMesh.instanceMatrix.needsUpdate = true;
					instancedMesh.setMatrixAt(instanced.instancedAtIndex,stratMatrix);//更新几何体的世界矩阵
				});
			})
			this.$nextTick(()=>{
				this.updateAllWallHandle();
			})
			setTimeout(() =>{
				this.updataPageData();//更新数据到各个对象里面
				this.calculateLayoutModelSize();//重新计算家具位置
				this.updateLables();//更新lable
				this.$nextTick(()=>{
					this.updateCareFul();//更新精细调整里面的空间
					this.updateSpanceData();//更新语音组件里面的空间
				})
			}, 100);
		}
	}
}