<template>
	<view class="vr-page">
		<!-- 返回按钮 -->
		<view class="back-btn" @click="back">‹ 返回</view>

		<!-- 主 Canvas -->
		<canvas canvas-id="vrCanvas" class="vr-canvas" @touchstart="onTouchStart" @touchmove="onTouchMove"
			@touchend="onTouchEnd"></canvas>

		<!-- 左上角 3D mini preview -->
		<canvas v-if="currentSpace.type==='model'" canvas-id="miniCanvas" class="mini-canvas"></canvas>

		<!-- Hotspot 点击由 Three.js raycaster 处理 -->

		<!-- 底栏 -->
		<view class="bottom-bar">
			<!-- 左侧空间切换 -->
			<view class="left">
				<button @click="showSpaceList = !showSpaceList">
					<image src="/static/icons/space.png" />
				</button>
			</view>
			<!-- 右侧工具 -->
			<view class="right">
				<button @click="showTools = !showTools">
					<image src="/static/icons/tools.png" />
				</button>
			</view>
		</view>

		<!-- 空间缩略图弹窗 -->
		<view v-if="showSpaceList" class="space-list">
			<view v-for="space in spaces" :key="space.id" class="space-item" @click="switchSpace(space.id)">
				<image :src="space.thumbnail" />
				<text>{{ space.name }}</text>
			</view>
		</view>

		<!-- 工具栏弹窗 -->
		<view v-if="showTools" class="tools-panel">
			<button @click="resetView">重置视角</button>
			<button @click="toggleFullScreen">全屏</button>
			<button @click="takePhoto">拍照</button>
		</view>

		<!-- 上一/下一空间按钮 -->
		<view class="switch-btn left" @click="prevSpace">‹</view>
		<view class="switch-btn right" @click="nextSpace">›</view>
	</view>
</template>

<script>
	import * as THREE from 'three'
	import {
		GLTFLoader
	} from 'three/examples/jsm/loaders/GLTFLoader.js'

	export default {
		name: 'VRView',
		data() {
			return {
				spaces: [], // VR 空间数组
				currentIndex: 0,
				currentSpace: null,

				// Three.js 主场景
				renderer: null,
				scene: null,
				camera: null,
				sphere: null,
				videoTexture: null,

				// Mini 3D模型
				miniRenderer: null,
				miniScene: null,
				miniCamera: null,
				miniModel: null,

				// Hotspot
				raycaster: null,
				mouse: new THREE.Vector2(),

				// 触控
				isDragging: false,
				lastX: 0,
				lastY: 0,
				lon: 0,
				lat: 0,

				// UI
				showSpaceList: false,
				showTools: false
			}
		},
		onLoad(options) {
			if (options.vrList) {
				try {
					// JSON.parse(decodeURIComponent(options.spaces))
					this.spaces = options.vrList
				} catch (e) {
					console.error('解析 VR 空间失败', e)
				}
			}
			this.currentSpace = this.spaces[this.currentIndex]
			this.initThree()
		},
		methods: {
			back() {
				const pages = getCurrentPages();
				if (pages.length > 1) {
				  uni.navigateBack();
				} else {
				  uni.switchTab({
				  		url:'/pages/index/index'
				  	})
				}
			},

			// ==================== Three.js 主场景 ====================
			initThree() {
				const canvasQuery = uni.createSelectorQuery()
				canvasQuery.select('#vrCanvas').node().exec(res => {
					const canvasNode = res[0].node
					const {
						windowWidth: width,
						windowHeight: height
					} = uni.getSystemInfoSync()

					// 主 renderer
					this.renderer = new THREE.WebGLRenderer({
						canvas: canvasNode,
						antialias: true
					})
					this.renderer.setSize(width, height)

					// scene & camera
					this.scene = new THREE.Scene()
					this.camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 2000)
					this.camera.position.set(0, 0, 0.01)

					// raycaster
					this.raycaster = new THREE.Raycaster()

					this.loadSpace(this.currentSpace)
					this.animate()
				})
			},

			// 加载空间
			loadSpace(space) {
				// 清空场景
				while (this.scene.children.length) this.scene.remove(this.scene.children[0])
				if (this.videoTexture) {
					this.videoTexture = null
				}

				// 图片
				if (space.type === 'image') {
					const geometry = new THREE.SphereGeometry(500, 60, 40)
					geometry.scale(-1, 1, 1)
					const texture = new THREE.TextureLoader().load(space.src)
					const material = new THREE.MeshBasicMaterial({
						map: texture
					})
					this.sphere = new THREE.Mesh(geometry, material)
					this.scene.add(this.sphere)
				}
				// CubeMap
				else if (space.type === 'cubemap') {
					const urls = [space.cubemap.px, space.cubemap.nx, space.cubemap.py, space.cubemap.ny, space.cubemap.pz,
						space.cubemap.nz
					]
					const cubeTexture = new THREE.CubeTextureLoader().load(urls)
					this.scene.background = cubeTexture
				}
				// 视频
				else if (space.type === 'video') {
					const video = document.createElement('video')
					video.src = space.src
					video.crossOrigin = 'anonymous'
					video.loop = true
					video.muted = false
					video.autoplay = true
					video.play()
					this.videoTexture = new THREE.VideoTexture(video)
					const geometry = new THREE.SphereGeometry(500, 60, 40)
					geometry.scale(-1, 1, 1)
					const material = new THREE.MeshBasicMaterial({
						map: this.videoTexture
					})
					this.sphere = new THREE.Mesh(geometry, material)
					this.scene.add(this.sphere)
				}
				// 模型
				else if (space.type === 'model') {
					const loader = new GLTFLoader()
					loader.load(space.src, gltf => {
						this.sphere = gltf.scene
						this.sphere.scale.set(space.modelScale, space.modelScale, space.modelScale)
						this.scene.add(this.sphere)
						this.initMiniModel(gltf.scene.clone(), space.modelScale)
					})
				}

				// Hotspots
				if (space.hotspots && space.hotspots.length) {
					space.hotspots.forEach(h => {
						const spriteMap = new THREE.TextureLoader().load('/static/icons/hotspot.png')
						const spriteMaterial = new THREE.SpriteMaterial({
							map: spriteMap
						})
						const sprite = new THREE.Sprite(spriteMaterial)
						const phi = THREE.MathUtils.degToRad(90 - h.position.lat)
						const theta = THREE.MathUtils.degToRad(h.position.lon)
						const radius = 500
						sprite.position.set(
							radius * Math.sin(phi) * Math.cos(theta),
							radius * Math.cos(phi),
							radius * Math.sin(phi) * Math.sin(theta)
						)
						sprite.userData.targetId = h.targetId
						this.scene.add(sprite)
					})
				}
			},

			animate() {
				requestAnimationFrame(this.animate)
				// 相机旋转
				const phi = THREE.MathUtils.degToRad(90 - this.lat)
				const theta = THREE.MathUtils.degToRad(this.lon)
				this.camera.target = new THREE.Vector3(
					500 * Math.sin(phi) * Math.cos(theta),
					500 * Math.cos(phi),
					500 * Math.sin(phi) * Math.sin(theta)
				)
				this.camera.lookAt(this.camera.target)
				this.renderer.render(this.scene, this.camera)

				// mini 模型同步旋转
				if (this.currentSpace.type === 'model' && this.miniModel) {
					this.miniModel.rotation.y = this.camera.rotation.y
					this.miniRenderer.render(this.miniScene, this.miniCamera)
				}
			},

			// ==================== Mini 3D 模型 ====================
			initMiniModel(model, scale) {
				const canvasQuery = uni.createSelectorQuery()
				canvasQuery.select('#miniCanvas').node().exec(res => {
					const canvasNode = res[0].node
					this.miniRenderer = new THREE.WebGLRenderer({
						canvas: canvasNode,
						antialias: true,
						alpha: true
					})
					this.miniRenderer.setSize(150, 150)
					this.miniScene = new THREE.Scene()
					this.miniCamera = new THREE.PerspectiveCamera(75, 1, 0.1, 2000)
					this.miniCamera.position.set(0, 50, 100)
					this.miniModel = model
					this.miniScene.add(this.miniModel)
				})
			},

			// ==================== 空间切换 ====================
			switchSpace(id) {
				const index = this.spaces.findIndex(s => s.id === id)
				if (index >= 0) {
					this.currentIndex = index
					this.currentSpace = this.spaces[index]
					this.loadSpace(this.currentSpace)
					this.showSpaceList = false
				}
			},
			prevSpace() {
				this.currentIndex = (this.currentIndex - 1 + this.spaces.length) % this.spaces.length;
				this.switchSpace(this.spaces[this.currentIndex].id)
			},
			nextSpace() {
				this.currentIndex = (this.currentIndex + 1) % this.spaces.length;
				this.switchSpace(this.spaces[this.currentIndex].id)
			},

			// ==================== 手势 ====================
			onTouchStart(e) {
				this.isDragging = true;
				const t = e.touches[0];
				this.lastX = t.clientX;
				this.lastY = t.clientY
			},
			onTouchMove(e) {
				if (!this.isDragging) return;
				const t = e.touches[0];
				const dx = t.clientX - this.lastX;
				const dy = t.clientY - this.lastY;
				this.lastX = t.clientX;
				this.lastY = t.clientY;
				this.lon -= dx * 0.1;
				this.lat += dy * 0.1;
				this.lat = Math.max(-85, Math.min(85, this.lat))
			},
			onTouchEnd() {
				this.isDragging = false
			},

			// ==================== 工具栏功能示例 ====================
			resetView() {
				this.lon = 0;
				this.lat = 0
			},
			toggleFullScreen() {
				uni.setScreenBrightness({
					value: 1
				})
			}, // 示例
			takePhoto() {
				console.log('拍照功能可扩展')
			}
		}
	}
</script>

<style scoped>
	.vr-page {
		width: 100%;
		height: 100%;
		background: #000;
		position: relative
	}

	.vr-canvas {
		width: 100%;
		height: 100%;
		display: block
	}

	.mini-canvas {
		position: absolute;
		top: 20rpx;
		left: 20rpx;
		width: 150rpx;
		height: 150rpx;
		z-index: 10;
		border: 1px solid #ccc;
		border-radius: 6rpx
	}

	.back-btn {
		position: absolute;
		top: 40rpx;
		left: 20rpx;
		color: #fff;
		font-size: 28rpx;
		z-index: 10
	}

	.bottom-bar {
		position: absolute;
		bottom: 0;
		width: 100%;
		height: 80rpx;
		display: flex;
		justify-content: space-between;
		padding: 0 20rpx;
		z-index: 10
	}

	.bottom-bar .left,
	.bottom-bar .right {
		display: flex;
		align-items: center
	}

	.space-list {
		position: absolute;
		bottom: 80rpx;
		left: 0;
		width: 100%;
		height: 150rpx;
		background: rgba(0, 0, 0, 0.7);
		display: flex;
		overflow-x: scroll;
		padding: 10rpx
	}

	.space-list .space-item {
		margin-right: 10rpx;
		display: flex;
		flex-direction: column;
		align-items: center
	}

	.space-list image {
		width: 120rpx;
		height: 80rpx;
		border-radius: 6rpx
	}

	.tools-panel {
		position: absolute;
		bottom: 80rpx;
		right: 0;
		width: 200rpx;
		background: rgba(0, 0, 0, 0.7);
		display: flex;
		flex-direction: column;
		padding: 10rpx
	}

	.tools-panel button {
		margin-bottom: 10rpx;
		color: #fff
	}

	.switch-btn {
		position: absolute;
		top: 50%;
		transform: translateY(-50%);
		z-index: 10;
		color: #fff;
		font-size: 60rpx;
		background: rgba(0, 0, 0, 0.3);
		width: 80rpx;
		height: 80rpx;
		line-height: 80rpx;
		text-align: center;
		border-radius: 50%
	}

	.switch-btn.left {
		left: 20rpx
	}

	.switch-btn.right {
		right: 20rpx
	}
</style>