<template>
	<!-- 滑动解锁插件 http://www.jq22.com/jquery-info22779 -->
	<div
		ref="dragVerify"
		class="drag_verify"
		:style="dragVerifyStyle"
		@mousemove="dragMoving"
		@mouseup="dragFinish"
		@mouseleave="dragFinish"
		@touchmove="dragMoving"
		@touchend="dragFinish"
	>
		<div class="dv_progress_bar" ref="progressBar" :class="{ goFirst2: isOk }" :style="progressBarStyle"></div>
		<div class="dv_text" :style="textStyle" ref="message">
			<slot name="textBefore" v-if="$slots.textBefore"></slot>
			{{ message }}
			<slot name="textAfter" v-if="$slots.textAfter"></slot>
		</div>

		<div
			class="dv_handler dv_handler_bg"
			:class="{ goFirst: isOk }"
			@mousedown="dragStart"
			@touchstart="dragStart"
			ref="handler"
			:style="handlerStyle"
		>
			<component :is="handlerIcon"></component>
		</div>
	</div>
</template>
<script setup>
	import { ref, computed, onMounted } from 'vue'
	import { CheckCircleOutlined } from '@ant-design/icons-vue'

	const props = defineProps({
		// 是否通过
		isPassing: {
			type: Boolean,
			default: false
		},
		// 宽度
		width: {
			type: Number,
			default: 250
		},
		// 高度
		height: {
			type: Number,
			default: 40
		},
		// 组件文案
		text: {
			type: String,
			default: 'swiping to the right side'
		},
		// 成功文案
		successText: {
			type: String,
			default: 'success'
		},
		// 背景色
		background: {
			type: String,
			default: '#eee'
		},
		// 解锁中背景色
		progressBarBg: {
			type: String,
			default: '#76c61d'
		},
		// 解锁成功背景色
		completedBg: {
			type: String,
			default: '#76c61d'
		},
		circle: {
			type: Boolean,
			default: false
		},
		radius: {
			type: String,
			default: '4px'
		},
		handlerIcon: {
			type: String
		},
		successIcon: {
			type: String
		},
		handlerBg: {
			type: String,
			default: '#fff'
		},
		textSize: {
			type: String,
			default: '14px'
		},
		textColor: {
			type: String,
			default: '#333'
		}
	})

	const emit = defineEmits(['update:isPassing', 'handlerMove', 'passcallback'])

	const dragVerify = ref(null)
	const progressBar = ref(null)
	const messageRef = ref(null)
	const handler = ref(null)

	const isMoving = ref(false)
	const x = ref(0)
	const isOk = ref(false)

	onMounted(() => {
		if (dragVerify.value) {
			dragVerify.value.style.setProperty('--textColor', props.textColor)
			dragVerify.value.style.setProperty('--width', Math.floor(props.width / 2) + 'px')
			dragVerify.value.style.setProperty('--pwidth', -Math.floor(props.width / 2) + 'px')
		}
	})

	const handlerStyle = computed(() => {
		return {
			left: '0px',
			width: props.height + 'px',
			height: props.height + 'px',
			background: props.handlerBg
		}
	})

	const message = computed(() => {
		return props.isPassing ? props.successText : props.text
	})

	const dragVerifyStyle = computed(() => {
		return {
			width: props.width + 'px',
			height: props.height + 'px',
			lineHeight: props.height + 'px',
			background: props.background,
			borderRadius: props.circle ? props.height / 2 + 'px' : props.radius
		}
	})

	const progressBarStyle = computed(() => {
		return {
			background: props.progressBarBg,
			height: props.height + 'px',
			borderRadius: props.circle ? props.height / 2 + 'px 0 0 ' + props.height / 2 + 'px' : props.radius
		}
	})

	const textStyle = computed(() => {
		return {
			height: props.height + 'px',
			width: props.width + 'px',
			fontSize: props.textSize
		}
	})

	const dragStart = (e) => {
		if (!props.isPassing) {
			isMoving.value = true
			const handlerEl = handler.value
			x.value = (e.pageX || e.touches[0].pageX) - parseInt(handlerEl.style.left.replace('px', ''), 10)
		}
		emit('handlerMove')
	}

	const dragMoving = (e) => {
		if (isMoving.value && !props.isPassing) {
			let _x = (e.pageX || e.touches[0].pageX) - x.value
			const handlerEl = handler.value
			const progressBarEl = progressBar.value
			if (_x > 0 && _x <= props.width - props.height) {
				handlerEl.style.left = _x + 'px'
				progressBarEl.style.width = _x + props.height / 2 + 'px'
			} else if (_x > props.width - props.height) {
				handlerEl.style.left = props.width - props.height + 'px'
				progressBarEl.style.width = props.width - props.height / 2 + 'px'
				passVerify()
			}
		}
	}

	const dragFinish = (e) => {
		if (isMoving.value && !props.isPassing) {
			let _x = (e.pageX || e.changedTouches[0].pageX) - x.value
			if (_x < props.width - props.height) {
				isOk.value = true
				setTimeout(() => {
					handler.value.style.left = '0'
					progressBar.value.style.width = '0'
					isOk.value = false
				}, 500)
			} else {
				const handlerEl = handler.value
				handlerEl.style.left = props.width - props.height + 'px'
				progressBar.value.style.width = props.width - props.height / 2 + 'px'
				passVerify()
			}
			isMoving.value = false
		}
	}

	const passVerify = () => {
		emit('update:isPassing', true)
		isMoving.value = false
		const handlerEl = handler.value
		const messageEl = messageRef.value

		if (handlerEl && handlerEl.children[0]) {
			handlerEl.children[0].className = props.successIcon
		}
		if (progressBar.value) {
			progressBar.value.style.background = props.completedBg
		}
		if (messageEl) {
			messageEl.style['-webkit-text-fill-color'] = 'unset'
			messageEl.style.animation = 'slidetounlock2 3s infinite'
			messageEl.style.color = '#fff'
		}
		emit('passcallback')
	}

	const reset = () => {
		isMoving.value = false
		x.value = 0
		isOk.value = false

		const handlerEl = handler.value
		const messageEl = messageRef.value

		if (handlerEl) {
			handlerEl.style.left = '0'
			if (handlerEl.children[0]) {
				handlerEl.children[0].className = props.handlerIcon
			}
		}
		if (progressBar.value) {
			progressBar.value.style.width = '0'
		}
		if (messageEl) {
			messageEl.style['-webkit-text-fill-color'] = 'transparent'
			messageEl.style.animation = 'slidetounlock 3s infinite'
			messageEl.style.color = props.background
		}
	}
</script>
<style lang="less" scoped>
	.drag_verify {
		position: relative;
		background-color: #e8e8e8;
		text-align: center;
		overflow: hidden;

		.dv_handler {
			position: absolute;
			top: 0px;
			left: 0px;
			cursor: move;

			i {
				color: #666;
				padding-left: 0;
				font-size: 16px;
			}

			.anticon-check-circle {
				color: #6c6;
				margin-top: 9px;
			}
		}

		.dv_progress_bar {
			position: absolute;
			height: 34px;
			width: 0px;
		}

		.dv_text {
			position: absolute;
			top: 0px;
			color: transparent;
			-moz-user-select: none;
			-webkit-user-select: none;
			user-select: none;
			-o-user-select: none;
			-ms-user-select: none;
			background: -webkit-gradient(
				linear,
				left top,
				right top,
				color-stop(0, var(--textColor)),
				color-stop(0.4, var(--textColor)),
				color-stop(0.5, #fff),
				color-stop(0.6, var(--textColor)),
				color-stop(1, var(--textColor))
			);
			-webkit-background-clip: text;
			-webkit-text-fill-color: transparent;
			-webkit-text-size-adjust: none;
			animation: slidetounlock 3s infinite;

			* {
				-webkit-text-fill-color: var(--textColor);
			}
		}

		.goFirst {
			left: 0px !important;
			transition: left 0.5s;
		}

		.goFirst2 {
			width: 0px !important;
			transition: width 0.5s;
		}
	}
</style>
<style>
	@keyframes slidetounlock {
		0% {
			background-position: var(--pwidth) 0;
		}
		100% {
			background-position: var(--width) 0;
		}
	}
	@keyframes slidetounlock2 {
		0% {
			background-position: var(--pwidth) 0;
		}
		100% {
			background-position: var(--pwidth) 0;
		}
	}
</style>
