<template>
	<view class="carousel" :style="{width:boxWidth,height:boxHeight}" @touchstart="touchStart" @touchmove="touchMove"
		@touchend="touchEnd">
		<!-- 轮播轨道 -->
		<view class="track" :style="trackStyle">
			<view class="slide" v-for="(item, index) in normalizedList" :key="index">
				<!-- 图片 -->
				<image v-if="item.mediaType === 'image'" :src="item.src" mode="aspectFill" />

				<!-- 视频 -->
				<view v-else-if="item.mediaType === 'video'" class="video-wrapper" @click.stop="playVideo(index)">
					<video :id="'video-' + index" :src="item.src" :poster="item.poster"
						:controls="playingIndex === index" :show-center-play-btn="false" object-fit="cover"
						@play="onVideoPlay" @pause="onVideoPause" />
					<view v-if="playingIndex !== index" class="play-btn">▶</view>
				</view>

				<!-- VR -->
				<view v-else-if="item.mediaType === 'vr'" class="vr-wrapper">
					<image class="vr-cover" :src="item.src" mode="aspectFill" />
					<image class="vr-icon" mode="aspectFit" :src="vrIcon" @tap.stop="enterVR()" />
				</view>
			</view>
		</view>

		<!-- 点指示器 -->
		<view v-if="indicator === 'dot'" class="dots">
			<view v-for="(item, index) in normalizedList" :key="index" class="dot"
				:class="{ active: index === current }" />
		</view>

		<!-- 箭头指示器 -->
		<view v-if="indicator === 'arrow'" class="arrow left" @click.stop="prev">‹</view>
		<view v-if="indicator === 'arrow'" class="arrow right" @click.stop="next">›</view>

		<!-- 底部分区长条指示器（固定分区长度，跳动游标） -->
		<view v-if="autoTypeIndicateList.length" class="type-bar">
			<view v-for="(item, index) in autoTypeIndicateList" :key="index" class="type-segment"
				:class="{ active: current >= item.startIndex && current <= item.endIndex }"
				:style="{ width: getSegmentWidth + '%' }" @click.stop="jumpToType(item)">
				{{ item.name }}
			</view>
		</view>
		<!-- 右下角索引 -->
		<view class="index-display">
			{{ current + 1 }} / {{ normalizedList.length }}
		</view>

	</view>
</template>

<script>
	export default {
		name: 'Carousel',
		props: {
			list: {
				type: Array,
				required: true
			}, // [{src:'',type:''}]
			indicator: {
				type: String,
				default: 'dot'
			}, // dot | arrow | none
			autoplay: {
				type: Boolean,
				default: false
			},
			interval: {
				type: Number,
				default: 3000
			},
			vrIcon: {
				type: String,
				default: ''
			},
			boxWidth: {
				type: String,
				default: '100%'
			},
			boxHeight: {
				type: String,
				default: '500rpx'
			},
			vrViewPage: {
				type: String,
				default: ''
			},
			assetsId: {
				type: String,
				default: ''
			}
		},
		data() {
			return {
				current: 0,
				containerWidth: 0,
				startX: 0,
				offsetX: 0,
				timer: null,
				playingIndex: null
			}
		},
		computed: {
			/* VR 永远在最前 */
			normalizedList() {
				const vr = []
				const other = []
				this.list.forEach(item => {
					item.mediaType === 'vr' ? vr.push(item) : other.push(item)
				})
				return [...vr, ...other]
			},

			trackStyle() {
				return `width:${this.normalizedList.length * this.containerWidth}px;
		transform: translate3d(${-this.current * this.containerWidth + this.offsetX}px,0,0);
        transition:${this.offsetX === 0 ? 'transform .3s' : 'none'};`
			},

			/* 自动生成分区指示 */
			autoTypeIndicateList() {
				const list = this.normalizedList
				if (!list.length) return []

				const result = []
				let startIndex = 0
				let bizType = list[0].bizType
				for (let i = 1; i <= list.length; i++) {
					if (i === list.length || list[i].bizType !== bizType) {
						result.push({
							type: bizType,
							name: bizType,
							startIndex,
							endIndex: i - 1
						})
						startIndex = i
						bizType = list[i] && list[i].bizType
					}
				}
				return result
			},
			getSegmentWidth() {
				if (!this.autoTypeIndicateList.length) return 100
				return 100 / this.autoTypeIndicateList.length
			}
		},
		mounted() {
			this.$nextTick(this.calcWidth)
			this.start()
		},
		beforeUnmount() {
			this.stop()
		},
		onLoad() {},
		watch: {
			normalizedList(list) {
				if (this.current >= list.length) this.current = 0
			},
			current() {
				this.stopVideo()
			}
		},
		methods: {
			calcWidth() {
				uni.createSelectorQuery()
					.in(this)
					.select('.carousel')
					.boundingClientRect(rect => {
						if (rect) this.containerWidth = rect.width
					})
					.exec()
			},

			start() {
				if (!this.autoplay) return
				this.stop()
				this.timer = setInterval(this.next, this.interval)
			},
			stop() {
				this.timer && clearInterval(this.timer)
				this.timer = null
			},
			next() {
				this.current = (this.current + 1) % this.normalizedList.length
			},
			prev() {
				this.current = (this.current - 1 + this.normalizedList.length) % this.normalizedList.length
			},

			touchStart(e) {
				this.stop()
				this.startX = e.touches[0].clientX
			},
			touchMove(e) {
				this.offsetX = e.touches[0].clientX - this.startX
			},
			touchEnd() {
				if (Math.abs(this.offsetX) > this.containerWidth / 4) {
					this.offsetX > 0 ? this.prev() : this.next()
				}
				this.offsetX = 0
				this.start()
			},

			/* 视频 */
			playVideo(index) {
				if (this.playingIndex === index) return
				this.stopVideo()
				this.playingIndex = index
				this.stop()
				this.$nextTick(() => {
					uni.createVideoContext('video-' + index, this).play()
				})
			},
			stopVideo() {
				if (this.playingIndex !== null) {
					uni.createVideoContext('video-' + this.playingIndex, this).pause()
					this.playingIndex = null
				}
			},
			onVideoPlay() {
				this.stop()
			},
			onVideoPause() {
				this.start()
			},

			/* VR */
			enterVR() {
				this.stop()
				this.stopVideo()
				this.$u.route({
					url: this.vrViewPage,
					params: {
						title: "vr看资产",
						id: this.assetsId
					}
				})
			},
			/* 分区跳转 */
			jumpToType(item) {
				this.stop()
				this.stopVideo()
				this.current = item.startIndex
				this.$nextTick(this.start)
			}
		}
	}
</script>

<style scoped>
	.carousel {
		overflow: hidden;
		position: relative;
	}

	.track {
		display: flex;
		height: 100%;
	}

	.slide {
		width: 100%;
		flex-shrink: 0;
	}

	.slide image,
	.video-wrapper,
	.vr-wrapper,
	video {
		width: 100%;
		height: 100%;
	}

	/* dots */
	.dots {
		position: absolute;
		bottom: 20rpx;
		left: 50%;
		transform: translateX(-50%);
		display: flex;
	}

	.dot {
		width: 12rpx;
		height: 12rpx;
		border-radius: 50%;
		background: rgba(255, 255, 255, .5);
		margin: 0 6rpx;
	}

	.dot.active {
		background: #fff;
	}

	/* arrows */
	.arrow {
		position: absolute;
		top: 50%;
		transform: translateY(-50%);
		width: 60rpx;
		height: 60rpx;
		line-height: 60rpx;
		text-align: center;
		background: rgba(0, 0, 0, .4);
		color: #fff;
		font-size: 40rpx;
		border-radius: 50%;
	}

	.arrow.left {
		left: 20rpx;
	}

	.arrow.right {
		right: 20rpx;
	}

	/* video */
	.video-wrapper {
		position: relative;
	}

	.play-btn {
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		width: 80rpx;
		height: 80rpx;
		line-height: 80rpx;
		text-align: center;
		border-radius: 50%;
		background: rgba(0, 0, 0, .5);
		color: #fff;
		font-size: 40rpx;
	}

	/* vr */
	.vr-wrapper {
		position: relative;
	}

	.vr-icon {
		position: absolute;
		top: 50%;
		left: 12%;
		transform: translate(-50%, -50%);
		width: 100rpx !important;
		height: 100rpx !important;
		background: rgba(80, 80, 80, 0.45);
		border-radius: 50%;
		padding: 12rpx;
	}

	.type-bar {
		position: absolute;
		bottom: 80rpx;
		left: 50%;
		transform: translateX(-50%);
		height: 40rpx;
		display: flex;
		background: rgba(0, 0, 0, 0.4);
		overflow: hidden;
		min-width: 300rpx;
	}


	.type-segment {
		display: flex;
		justify-content: center;
		align-items: center;
		color: #fff;
		/* 保持文字白色 */
		font-size: 20rpx;
		cursor: pointer;
		padding: 0 10rpx;
		transition: background 0.3s;
	}

	.type-segment.active {
		background: rgba(255, 47, 49, 0.6);
		/* 仅背景高亮，不覆盖文字 */
	}

	.index-display {
		position: absolute;
		bottom: 80rpx;
		right: 20rpx;
		padding: 6rpx 12rpx;
		background: rgba(0, 0, 0, 0.5);
		color: #fff;
		font-size: 24rpx;
		border-radius: 12rpx;
	}
</style>