<template>
	<div>
		<div class="carousel-holder" :class="classes" v-show="cards.length > 1">
			<div class="slide-container" ref="container" @mousedown="handleStart" @touchstart="handleStart" @mousemove="handleSlide" @touchmove="handleSlide" @mouseup="handleEnd" @touchend="handleEnd">
				<div class="slide_container_aspect_ratio" :style="`padding-top: calc(100% / ${aspectStyle});`"></div>
				<div v-for="(card, index) in cards" :key="card.id" :style="setSlidePos(index)" class="slide-wrapper">
					<slot :card="card" />
				</div>
			</div>
			<button @click="prevSlide" type="button" class="slide_left">
				<svg class="arrow_icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
					<path fill-rule="evenodd" d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/>
				</svg>
			</button>
			<button @click="nextSlide" type="button" class="slide_right">
				<svg class="arrow_icon" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 16 16">
					<path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/>
				</svg>
			</button>
			<div class="slide_dot_box">
				<button @click="currentSlide = index" type="button" v-for="(c, index) in cards" :key="c.id" class="slide_dot" :class="index == currentSlide ? 'active' : ''"></button>
			</div>
		</div>
		<div v-show="cards.length == 1">
			<div ref="singleCardContainer">
				<slot :card="cards[0]" />
			</div>
		</div>
	</div>
</template>

<script>
export default {
	props: {
		cards: {
			type: Array,
			required: true,
		},
		config: {
			type: Object,
		},
		modelValue: {
			type: Number,
		},
		classes: {
			type: String,
		},
		aspectStyle: {
			type: Number
		}
	},
	data() {
		return {
			settings: {
				maxDegree: 15,
				cardDistance: 25,
				maxScale: 1,
			},
			currentSlide: 0,
			sliding: false,
			startX: null,
			oriSlide: 0,
			slideDistance: 100,
			timer: null
		};
	},
	computed: {
		cardLength() {
			return this.cards.length
		}
	},
	methods: {
		setSlidePos(i) {
			const diff = i - this.currentSlide;
			// skewY
			let skew = Math.abs(diff) * this.settings.maxDegree;
			if (skew > this.settings.maxDegree) skew = this.settings.maxDegree;
			// else if (skew < -this.settings.maxDegree) skew = -this.settings.maxDegree
			// translateX
			let tX = -50 + diff * (100 + this.settings.cardDistance);
			// scale
			let scale = (1 - Math.abs(diff)) * this.settings.maxScale;
			if (scale > this.settings.maxScale) scale = this.settings.maxScale;
			else if (scale < 1) scale = 1;
			let nextI = Math.round(this.currentSlide);
			return {
				left: `50%`,
				top: "50%",
				transform: `translate(${tX}%, -50%) skewY(${skew}deg) scale(${scale})`,
				transition: this.sliding ? "none" : "all 0.3s",
				zIndex: nextI >= i ? 2 : 1,
				opacity: nextI == i ? 1 : 0.7,
			};
		},
		handleStart(e) {
			if (this.sliding) return;
			this.sliding = true;
			this.startX =
				e.type == "mousedown" ? e.clientX : e.touches[0].clientX;
			this.oriSlide = this.currentSlide;
		},
		handleSlide(e) {
			if (!this.sliding) return;
			// #ifdef H5
			window.getSelection().removeAllRanges();
			// #endif
			let xPos = e.type == "mousemove" ? e.clientX : e.touches[0].clientX;

			let dist = this.startX - xPos;
			if (dist > this.slideDistance) dist = this.slideDistance;
			else if (dist < -this.slideDistance) dist = -this.slideDistance;
			let newSlide = this.oriSlide + dist / this.slideDistance;
			if (newSlide < 0) newSlide = 0;
			else if (newSlide > this.cards.length - 1)
				newSlide = this.cards.length - 1;
			this.currentSlide = newSlide;
		},
		handleEnd(e) {
			this.sliding = false;
			this.currentSlide = Math.round(this.currentSlide);
			this.$emit("input", this.currentSlide);
		},
		resizeHandler() {
			const container = this.$refs.container
			const singleContainer = this.$refs.singleCardContainer
			const wrapper = container ? container.querySelector(".slide-wrapper") : singleContainer
			this.$refs.container.style.height = `${
				wrapper.offsetHeight +
				Math.tan((this.settings.maxDegree / 180) * Math.PI) *
					wrapper.offsetHeight
			}px`;
			this.slideDistance = wrapper.offsetWidth / 3;
		},
		prevSlide() {
			if (this.currentSlide == 0) {
				this.currentSlide = (this.cards.length - 1);
			} else {
				this.currentSlide--
			}
		},
		nextSlide() {
			if (this.currentSlide >= (this.cards.length - 1)) {
				this.currentSlide = 0;
			} else {
				this.currentSlide++
			}
		}
	},
	mounted() {
		// #ifdef H5
		window.addEventListener("resize", this.resizeHandler);
		
		this.timer = setInterval(() => {
			if (this.currentSlide >= (this.cards.length - 1)) {
				this.currentSlide = 0;
			} else {
				this.currentSlide++
			}
		}, 5000);
		// #endif
		// #ifdef APP-PLUS
		uni.onResize(() => {
			this.resizeHandler()
		})
		// #endif
	},
	beforeMount() {
		if (this.config) {
			for (let c in this.config) {
				if (this.settings[c]) this.settings[c] = this.config[c];
			}
		}
		if (this.modelValue) {
			this.currentSlide = this.modelValue;
		}
	},
	beforeUnmount() {
		// #ifdef H5
		window.removeEventListener("resize", this.resizeHandler);
		// #endif
		// #ifndef H5
		uni.offResize(() => {
			this.resizeHandler()
		})
		// #endif
		clearInterval(this.timer)
	},
	watch: {
		modelValue() {
			this.currentSlide = this.modelValue;
		},
		cardLength(n, o) {
			this.$nextTick(() => {
				this.resizeHandler()
			})
		}
	},
};
</script>

<style scoped>
.carousel-holder{
	position:relative;
}

.slide-container {
	width: 100%;
	overflow: hidden;
	display: flex;
	position: relative;
}

.slide-container .slide_container_aspect_ratio {
	width: 100%;
	padding-top: calc(100% / 3.2);
}

.slide-wrapper {
	width: 100%;
	position: absolute;
}


.slide_left {
    width: 50px;
    height: 50px;
    left: 20px;
    top: 50%;
    transform: translateY(-50%);
    background-color: rgba(0, 0, 0, 0.5);
    border-radius: 100%;
    position: absolute;
    z-index: 2;
}

.lucky_spin .slide_left {
	width: 20px;
	height: 20px;
	left: 5px;
	background-color: #000;
}

.slide_right {
    width: 50px;
    height: 50px;
    right: 20px;
    top: 50%;
    transform: translateY(-50%);
    background-color: rgba(0, 0, 0, 0.5);
    border-radius: 100%;
    position: absolute;
    z-index: 2;
}

.lucky_spin .slide_right {
	width: 20px;
	height: 20px;
	right: 5px;
	background-color: #000;
}

.arrow_icon {
    width: 20px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

.lucky_spin .arrow_icon {
	width: 10px;
}

.arrow_icon path {
    fill: #fff;
}

.slide_dot {
	width: 10px;
	height: 10px;
	background-color: rgba(255, 255, 255, 0.5);
	border-radius: 100%;
	margin: 5px;
	transition: all 0.3s;
}

.lucky_spin .slide_dot {
	display: none;
}

.slide_dot.active {
	background-color: #fff;
}

.slide_dot_box {
	display: inline-flex;
	align-items: center;
	margin: 0 auto;
	position: absolute;
	bottom: 20px;
	left: 50%;
	transform: translateX(-50%);
	z-index: 2;
}

/* Responsive */
@media (max-width: 767px) {
	.slide_left {
		width: 30px;
		height: 30px;
		left: 5px;
	}
	.arrow_icon {
		width: 15px;
	}
	.slide_right {
		width: 30px;
		height: 30px;
		right: 5px;
	}
	.slide_dot_box {
		bottom: 5px;
	}
	.slide_dot {
		width: 5px;
		height: 5px;
		margin: 3px;
	}
}
</style>