<template>
	<div class="input-code">
		<input
			ref="inputRef"
			type="tel"
			maxlength="1"
			v-for="(v, i) in props.length"
			:key="i"
			v-model="code[i]"
			@input="handleInput(i)"
			@keydown.delete="handleDelete(i)"
			@paste="handlePaste"
		/>
	</div>
</template>

<script setup lang="ts">
	import { onMounted, ref, computed, watch, nextTick } from 'vue'
	const emit = defineEmits(['submit', 'update:modelValue'])
	const props = defineProps({
		length: {
			type: Number,
			default: 6
		}
	})
	const inputRef = ref('')
	const code = ref([])
	const codeStr = computed(() => code.value.join(''))
	watch(codeStr, (newVal) => {
		emit('update:modelValue', newVal)
	})
	const resetCode = (size = props.length) => {
		code.value = []
		for (let i = 0; i < size; i++) {
			code.value.push('')
		}
	}
	resetCode(props.length)
	const handleInput = (index: number) => {
		const value = code.value[index]
		if (value) {
			if (/[0-9]/.test(value)) {
				code.value[index] = value
				focusLast()
			} else {
				code.value[index] = ''
			}
		}
		submit()
	}
	const handleDelete = (index: number) => {
		if (code.value[index].length == 0) {
			focusLast(-1)
		}
	}
	const handlePaste = (e: ClipboardEvent) => {
		const text = e.clipboardData?.getData('text')
		if (text) {
			const nums = text.match(/[0-9]/g) || []
			if (nums.length === code.value.length) {
				code.value = [...nums]
				focusLast()
				nextTick(submit)
			}
		}
	}
	// 聚焦最后一个没有输入的
	const focusLast = (step = 0) => {
		let index = code.value.findIndex((item) => !item) + step
		index < 0 && (index = 0)
		if (index >= 0 && index < props.length) {
			inputRef.value[index]?.focus?.()
		}
		if (code.value.every((item) => item.length)) {
			inputRef.value?.forEach((item) => item.blur?.())
		}
	}
	const submit = () => {
		if (codeStr.value.length === props.length) {
			emit('submit', codeStr.value)
		}
	}
	onMounted(() => {
		focusLast()
	})
	defineExpose({
		resetCode
	})
</script>

<style lang="less" scoped>
	.input-code {
		width: 100%;
		display: flex;
		align-items: center;
		justify-content: var(--input-code-justify-content, space-between);
		gap: var(--input-code-input-gap, 0);
		> input {
			width: var(--input-code-input-width, 4.8rem);
			height: var(--input-code-input-height, 4.8rem);
			border-radius: var(--input-code-input-radius, 0);
			border-width: var(--input-code-input-border-width, 0.15rem);
			border-color: var(--input-code-input-border-color, #c4c4c4);
			border-style: var(--input-code-input-border-style, solid);
			background-color: var(--input-code-input-bg-color, #fff);
			text-align: center;
		}
	}
</style>
