<template>
	<section
		class="carousel-container"
		:class="{ 'show-pagination': showPagination }"
		aria-label="Featured content"
		@mouseenter="pauseAutoplay"
		@mouseleave="resumeAutoplay"
		@click="handleCarouselClick"
		@touchstart="handleCarouselTouch"
		@touchmove="handleCarouselTouch"
	>
		<KagolCarousel
			v-model="activePage"
			class="home-carousel"
			:autoplay="isAutoplayEnabled"
			:interval="10000"
		>
			<article v-for="slide in slides" :key="slide.id" ref="slideEls" class="carousel-slide">
				<div class="mask"></div>
				<div class="banner-title" v-if="slide.title">{{ slide.title }}</div>
				<img
					v-if="!slide.video"
					class="carousel-banner image"
					:src="slide.image"
					:alt="slide.alt"
				/>
				<video
					v-else
					class="carousel-banner video"
					:alt="slide.alt"
					:controls="false"
					autoplay
					muted
					loop
				>
					<source :src="slide.video" type="video/mp4" />
				</video>

				<div class="desc flex flex-center" v-if="slide.description">
					<span class="desc-fill" aria-hidden="true"></span>
					<span class="desc-index-group">
						<span class="desc-line" aria-hidden="true"></span>
						<span class="desc-index-frame">
							<span class="desc-index">{{ slide.number }}</span>
							<span class="desc-index-cover" aria-hidden="true"></span>
						</span>
					</span>
					<p class="desc-copy">{{ slide.description }}</p>
				</div>
			</article>

			<template #pagination="{ prevPage, nextPage }">
				<nav class="carousel-pagination" aria-label="Carousel pagination">
					<button
						class="carousel-pagination-button carousel-pagination-button-prev"
						type="button"
						aria-label="Previous slide"
						@click="prevPage"
					>
						<span
							class="carousel-pagination-arrow carousel-pagination-arrow-prev"
						></span>
					</button>
					<button
						class="carousel-pagination-button carousel-pagination-button-next"
						type="button"
						aria-label="Next slide"
						@click="nextPage"
					>
						<span
							class="carousel-pagination-arrow carousel-pagination-arrow-next"
						></span>
					</button>
				</nav>
			</template>

			<template #indicator></template>
		</KagolCarousel>
	</section>
</template>

<script setup lang="ts">
	import {
		nextTick,
		onBeforeUnmount,
		onMounted,
		shallowRef,
		useTemplateRef,
		watch,
		computed,
		ref
	} from 'vue'
	import { gsap } from 'gsap'
	import { Carousel as KagolCarousel } from '@kagol/vue-carousel'
	import '@kagol/vue-carousel/dist/style.css'
	import { useI18n } from 'vue-i18n'
	import { IMAGE_BASE_URL } from '@/tools/config'

	const { t, locale } = useI18n()

	type HomeSlide = {
		id: string
		image: string
		video: string
		alt: string
		title?: string
		number?: string
		description?: string
	}

	const activePage = shallowRef(1)
	const isAutoplayEnabled = shallowRef(false)
	const slideEls = useTemplateRef<HTMLElement[]>('slideEls')
	const windowWidth = ref(typeof window !== 'undefined' ? window.innerWidth : 768)
	const showPagination = ref(false)
	let hideTimeout: number | null = null

	const getVideoUrl = () => {
		const isMobile = windowWidth.value < 768
		const isEnglish = locale.value === 'en'

		if (isEnglish) {
			return isMobile
				? 'https://s3.ap-east-1.amazonaws.com/code-create.com.hk/2023/06/codec_brand_vid_EN_1x1_SUB.mp4'
				: 'https://s3.ap-east-1.amazonaws.com/code-create.com.hk/2023/06/codec_brand_vid_16x9_ENG_SUB.mp4'
		} else {
			// 中文（简体和繁体都使用中文版本）
			return isMobile
				? 'https://s3.ap-east-1.amazonaws.com/code-create.com.hk/2023/05/codec_brand_video_SC_1x1_SUB.mp4'
				: 'https://s3.ap-east-1.amazonaws.com/code-create.com.hk/2023/05/codec_brand_video_SC_16x9_SUB.mp4'
		}
	}

	const slides = computed<HomeSlide[]>(() => [
		{
			id: 'aida',
			image: `${IMAGE_BASE_URL}/2022/11/mainbanner01-2.jpg`,
			video: '',
			alt: t('Home.banner1slogan'),
			title: t('Home.banner1slogan'),
			number: '01',
			description: t('Home.banner1desc')
		},
		{
			id: 'mixi',
			image: `${IMAGE_BASE_URL}/2022/11/mainbanner02-3.jpg`,
			video: '',
			alt: 'Code Create product banner',
			title: t('Home.banner2slogan'),
			number: '02',
			description: t('Home.banner2desc')
		},
		{
			id: 'video',
			image: '',
			video: getVideoUrl(),
			alt: 'Code Create product video banner'
		}
	])
	const descAnimationDelay = 1
	let activeSlideIndex: number | null = null
	let descAnimationFrame = 0
	let descTimeline: ReturnType<typeof gsap.timeline> | null = null
	let handleResize: (() => void) | null = null

	function getActiveSlideIndex() {
		const slideCount = slides.value.length

		return (((activePage.value - 1) % slideCount) + slideCount) % slideCount
	}

	function prefersReducedMotion() {
		return window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false
	}

	function playDescAnimation(slideIndex: number) {
		const activeSlide = slideEls.value?.[slideIndex]
		const desc = activeSlide?.querySelector<HTMLElement>('.desc')
		const fill = desc?.querySelector<HTMLElement>('.desc-fill')
		const line = desc?.querySelector<HTMLElement>('.desc-line')
		const index = desc?.querySelector<HTMLElement>('.desc-index')
		const cover = desc?.querySelector<HTMLElement>('.desc-index-cover')
		const copy = desc?.querySelector<HTMLElement>('.desc-copy')

		descTimeline?.kill()
		descTimeline = null

		if (!fill || !line || !index || !cover || !copy) {
			return
		}

		gsap.killTweensOf([fill, line, index, cover, copy])

		if (prefersReducedMotion()) {
			gsap.set(fill, { width: '100%' })
			gsap.set(line, { autoAlpha: 1, width: 1, x: 0 })
			gsap.set(index, { autoAlpha: 1, x: 0 })
			gsap.set(cover, { autoAlpha: 0, xPercent: 110 })
			gsap.set(copy, { autoAlpha: 1, x: 0 })
			return
		}

		gsap.set(fill, { width: 0 })
		gsap.set(line, { autoAlpha: 0, width: 5, x: 18 })
		gsap.set(index, { autoAlpha: 0, x: -34 })
		gsap.set(cover, { autoAlpha: 0, xPercent: 0 })
		gsap.set(copy, { autoAlpha: 0, x: 22 })

		descTimeline = gsap
			.timeline({
				delay: descAnimationDelay,
				defaults: {
					ease: 'power3.out'
				}
			})
			.addLabel('panel', 0)
			.to(fill, { duration: 1.05, ease: 'power2.out', width: '100%' }, 'panel')
			.to(line, { autoAlpha: 1, duration: 0.9, width: 1, x: 0 }, 'panel+=0.12')
			.addLabel('number', 1.18)
			.set(index, { autoAlpha: 1 }, 'number')
			.set(cover, { autoAlpha: 1 }, 'number')
			.to(index, { duration: 0.7, x: 0 }, 'number')
			.to(cover, { duration: 0.72, ease: 'power2.inOut', xPercent: 110 }, 'number+=0.08')
			.to(copy, { autoAlpha: 1, duration: 0.72, x: 0 }, '>')
	}

	function queueDescAnimation() {
		const slideIndex = getActiveSlideIndex()

		if (slideIndex === activeSlideIndex) {
			return
		}

		activeSlideIndex = slideIndex
		nextTick(() => {
			if (descAnimationFrame) {
				window.cancelAnimationFrame(descAnimationFrame)
			}

			descAnimationFrame = window.requestAnimationFrame(() => {
				descAnimationFrame = 0
				playDescAnimation(slideIndex)
			})
		})
	}

	function pauseAutoplay() {
		isAutoplayEnabled.value = false
	}

	function resumeAutoplay() {
		isAutoplayEnabled.value = true
	}

	function showPaginationControls() {
		showPagination.value = true
		
		if (hideTimeout) {
			window.clearTimeout(hideTimeout)
		}
		
		hideTimeout = window.setTimeout(() => {
			showPagination.value = false
			hideTimeout = null
		}, 3000)
	}

	function handleCarouselClick() {
		showPaginationControls()
	}

	function handleCarouselTouch() {
		showPaginationControls()
	}

	function handleOutsideClick(event: MouseEvent | TouchEvent) {
		const container = document.querySelector('.carousel-container')
		if (container && !container.contains(event.target as Node)) {
			showPagination.value = false
			if (hideTimeout) {
				window.clearTimeout(hideTimeout)
				hideTimeout = null
			}
		}
	}

	onMounted(() => {
		resumeAutoplay()
		queueDescAnimation()

		// 监听窗口resize事件以更新视频选择
		handleResize = () => {
			windowWidth.value = window.innerWidth
		}
		window.addEventListener('resize', handleResize)

		// 监听点击轮播图外部区域
		document.addEventListener('click', handleOutsideClick)
		document.addEventListener('touchstart', handleOutsideClick)
	})

	onBeforeUnmount(() => {
		if (descAnimationFrame) {
			window.cancelAnimationFrame(descAnimationFrame)
		}

		descTimeline?.kill()

		// 移除resize监听
		if (handleResize) {
			window.removeEventListener('resize', handleResize)
		}

		// 清理定时器和事件监听
		if (hideTimeout) {
			window.clearTimeout(hideTimeout)
		}
		document.removeEventListener('click', handleOutsideClick)
		document.removeEventListener('touchstart', handleOutsideClick)
	})

	watch(activePage, queueDescAnimation)
</script>

<style scoped lang="less">
	.carousel-container {
		width: 100%;
		overflow: hidden;
	}

	.home-carousel {
		.carousel-slide {
			position: relative;
			width: 100%;
			aspect-ratio: 16 / 9;
			height: 960px;
			overflow: hidden;
			.mask {
				position: absolute;
				top: 0;
				left: 0;
				right: 0;
				bottom: 0;
				background-color: rgba(0, 0, 0, 0.35);
				z-index: 2;
			}
			.carousel-banner {
				display: block;
				width: 100%;
				height: 100%;
				object-fit: cover;
				position: absolute;
			}
			.banner-title {
				position: absolute;
				right: 50%;
				top: 50%;
				white-space: pre-line;
				color: #fff;
				font-size: 64px;
				font-family: 'Poppins';
				transform: translateY(-70%);
				z-index: 3;
			}
			.desc {
				position: absolute;
				left: 0;
				bottom: 0;
				z-index: 3;
				display: flex;
				align-items: center;
				gap: 24px;
				height: 140px;
				width: 656px;
				color: #ffffff;
				background: transparent;
				isolation: isolate;
				pointer-events: none;
			}
			.desc-fill {
				position: absolute;
				inset: 0 auto 0 0;
				z-index: 0;
				display: block;
				width: 0;
				background: #a51f24;
				pointer-events: none;
			}
			.desc > * {
				pointer-events: auto;
			}

			.desc-index-group {
				position: relative;
				z-index: 1;
				flex: 0 0 auto;
			}
			.desc-line {
				position: absolute;
				top: -160%;
				left: 50%;
				display: block;
				width: 1px;
				height: 65px;
				background: rgba(255, 255, 255, 0.72);
				opacity: 0;
				transform: translateX(-50%);
				will-change: transform, width, opacity;
			}
			.desc-index-frame {
				position: relative;
				display: block;
				overflow: hidden;
			}
			.desc-index {
				flex: 0 0 auto;
				position: relative;
				z-index: 1;
				display: block;
				font-family: 'Poppins';
				font-size: 52px;
				font-weight: 700;
				line-height: 1;
				opacity: 0;
				will-change: transform, opacity;
			}
			.desc-index-cover {
				position: absolute;
				inset: 0;
				z-index: 2;
				display: block;
				background: #ffffff;
				opacity: 0;
				pointer-events: none;
				will-change: transform;
			}
			.desc-copy {
				position: relative;
				z-index: 1;
				max-width: 440px;
				margin: 0;
				font-family: 'Poppins';
				font-size: 14px;
				font-weight: 600;
				line-height: 1.45;
				opacity: 0;
				will-change: transform, opacity;
			}
		}
		.carousel-pagination {
			position: absolute;
			right: 0;
			bottom: 0;
			z-index: 2;
			display: flex;
			flex-direction: column;
			width: 70px;
			height: 140px;
			transform: translateX(100%);
			transition: transform 0.28s ease;
			will-change: transform;
			z-index: 9;
			opacity: 1;
		}
		.carousel-pagination-button {
			position: relative;
			display: flex;
			flex: 1 1 0;
			align-items: center;
			justify-content: center;
			width: 100%;
			padding: 0;
			border: 0;
			color: #ffffff;
			background: #65090c;
			cursor: pointer;
			appearance: none;
			transition: background-color 0.2s ease;
		}

		// .carousel-pagination-button:hover {
		// 	background: rgba(255, 255, 255, 0.75);
		// }

		// .carousel-pagination-button:focus-visible {
		// 	position: relative;
		// 	z-index: 1;
		// 	outline: 2px solid #ffffff;
		// 	outline-offset: -6px;
		// }

		.carousel-pagination-arrow {
			position: absolute;
			top: 50%;
			left: 50%;
			display: block;
			box-sizing: border-box;
			width: 20px;
			height: 20px;
			border-top: 2.5px solid currentColor;
			border-right: 2.5px solid currentColor;
		}

		.carousel-pagination-arrow-prev {
			transform: translate(-50%, -50%) rotate(225deg);
		}

		.carousel-pagination-arrow-next {
			transform: translate(-50%, -50%) rotate(45deg);
		}
	}

	.carousel-container:hover .carousel-pagination {
		transform: translateX(0);
	}

	:deep(.xui-carousel) {
		width: 100%;
	}

	:deep(.xui-carousel-item-container) {
		height: 100%;
	}

	@media (max-width: 768px) {
		.home-carousel {
			.carousel-slide {
				aspect-ratio: auto;
				height: 365px;
				min-height: 365px;

				.carousel-banner {
					height: 100%;
				}

				.banner-title {
					top: 86px;
					right: auto;
					left: 30px;
					width: min(220px, calc(100% - 60px));
					font-size: 28px;
					font-weight: 700;
					line-height: 1.35;
					letter-spacing: 2px;
					transform: none;
				}

				.desc {
					width: 100%;
					min-width: 0;
					height: 102px;
					min-height: 102px;
					padding: 16px 15px;
					gap: 18px;
					background: transparent;
				}
				.desc-line {
					top: -70px;
					height: 45px;
				}
				.desc-index {
					font-size: 32px;
				}
				.desc-copy {
					max-width: none;
					font-size: 11px;
					font-weight: 600;
					line-height: 1.45;
				}
			}

			.carousel-pagination {
				width: 50px;
				height: 102px;
				transform: translateX(0);
				opacity: 0;
				transition: opacity 0.3s ease;
			}

			.carousel-pagination-button {
				width: 50px;
				height: 51px;
			}
		}

		.carousel-container.show-pagination .carousel-pagination {
			opacity: 1;
		}

		.carousel-pagination-arrow {
			width: 18px;
			height: 18px;
		}

		.carousel-container:hover .carousel-pagination {
			transform: translateX(0);
		}
	}
</style>
