<template>
	<div class="offset-tool">
		<div class="input" v-show="showInput">
			<my-input v-model="left" type="number" before="X" after="%" :min="-100" :max="100" />
			<my-input v-model="top" type="number" before="Y" after="%" :min="-100" :max="100" />
		</div>
		<div
			class="dish"
			@mousedown="mousedown"
			@touchstart="mousedown"
			ref="dishRef"
			v-show="showDish"
		>
			<img src="/src/assets/images/icon/xyz.png" />
			<span class="ball" :style="ballStyle"></span>
			<span class="tip x">X: {{ left }}%</span>
			<span class="tip y">Y: {{ top }}%</span>
			<span class="line x"></span>
			<span class="line y"></span>
			<span class="line z" :style="lineZStyle"></span>
		</div>
	</div>
</template>

<script setup lang="ts">
	import { ref, watch, computed } from 'vue'
	import MyInput from './my-input.vue'
	const props = defineProps({
		modelValue: { type: Object as () => { x: number; y: number } },
		showInput: {
			type: Boolean,
			default: true
		},
		showDish: {
			type: Boolean,
			default: true
		}
	})
	const emit = defineEmits(['update:modelValue', 'change', 'input'])
	// 工具的实际坐标 -100 ~ 100
	const top = ref(Math.round(props.modelValue.y))
	const left = ref(Math.round(props.modelValue.x))

	// 原点的坐标 0 ~ 100
	const ballStyle = computed(() => ({
		top: 50 + top.value / 2 + '%',
		left: 50 + left.value / 2 + '%'
	}))
	watch(
		() => props.modelValue.x,
		(v) => (left.value = v)
	)
	watch(
		() => props.modelValue.y,
		(v) => (top.value = v)
	)
	const dishRef = ref<HTMLDivElement>()
	const mousedown = (e: MouseEvent | TouchEvent) => {
		if (!dishRef.value) return
		const mousemove = (e: MouseEvent | TouchEvent) => {
			if (!dishRef.value) return
			const rect = dishRef.value.getBoundingClientRect()
			const X = e.clientX || (e as TouchEvent).touches[0].clientX
			const Y = e.clientY || (e as TouchEvent).touches[0].clientY
			var x = ((X - rect.left) / rect.width) * 100
			var y = ((Y - rect.top) / rect.height) * 100
			if (x < 0) x = 0
			if (x > 100) x = 100
			if (y < 0) y = 0
			if (y > 100) y = 100
			left.value = Math.round((x - 50) * 2)
			top.value = Math.round((y - 50) * 2)
			onInput()
		}
		mousemove(e)
		const mouseup = () => {
			onChange()
			document.removeEventListener('mousemove', mousemove)
			document.removeEventListener('touchmove', mousemove)
			document.removeEventListener('mouseup', mouseup)
			document.removeEventListener('touchend', mouseup)
		}
		document.addEventListener('mousemove', mousemove)
		document.addEventListener('touchmove', mousemove)
		document.addEventListener('mouseup', mouseup)
		document.addEventListener('touchend', mouseup)
	}
	const onInput = () => {
		const value = {
			x: left.value,
			y: top.value
		}
		emit('update:modelValue', value)
		emit('input', value)
	}
	var changeTime: any = null
	const onChange = () => {
		clearTimeout(changeTime)
		changeTime = setTimeout(() => {
			const value = {
				x: left.value,
				y: top.value
			}
			emit('update:modelValue', value)
			emit('change', value)
		}, 500)
	}
	const lineZStyle = computed(() => ({
		'--rotateZ': calculateAngle(0, 0, left.value, top.value) + 'deg',
		width: calculateDistance(0, 0, left.value, top.value) / 2 + '%'
	}))
	// 计算角度
	function calculateAngle(x1: number, y1: number, x2: number, y2: number) {
		const deltaX = x2 - x1
		const deltaY = y1 - y2
		let angle = Math.atan2(deltaX, deltaY) * (180 / Math.PI) - 90
		return angle
	}
	// 计算距离
	function calculateDistance(x1: number, y1: number, x2: number, y2: number) {
		const deltaX = x2 - x1
		const deltaY = y2 - y1
		const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY)
		return distance
	}
</script>

<style scoped lang="less">
	.offset-tool {
		position: relative;
		> .input {
			display: flex;
			align-items: center;
			justify-content: center;
			> * {
				flex: 1;
				margin-right: 1rem;
				&:last-child {
					margin-right: 0;
				}
			}
		}
		> .dish {
			width: 11.5rem;
			height: 11.5rem;
			border: 0.1rem solid #eaeaea;
			border-radius: 0.34rem;
			cursor: pointer;
			position: relative;
			background-color: #f6f6f6;
			margin-top: 2rem;
			> * {
				position: absolute;
				pointer-events: none;
				user-select: none;
			}
			> img {
				width: 1.2rem;
				height: 1.2rem;
				bottom: 0.35rem;
				right: 0.35rem;
			}
			> .ball {
				top: 50%;
				left: 50%;
				transform: translate(-50%, -50%);
				width: 0.85rem;
				height: 0.85rem;
				border: 0.1rem solid #fff;
				background-color: #333;
				border-radius: 50%;
				box-shadow: 0px 0.068rem 0.17px 0px rgba(0, 0, 0, 0.26);
			}
			> .tip {
				font-size: 0.85rem;
				color: #000;
				line-height: 2.4rem;
				&.x {
					top: 50%;
					right: 0%;
					transform: translate(100%, -50%);
					padding-left: 6px;
				}
				&.y {
					top: 0%;
					left: 50%;
					transform: translate(-50%, -100%);
				}
			}
			> .line {
				border-color: #d9d9d9;
				border-style: dashed;
				border-width: 0;
				width: 0;
				height: 0;
				top: 50%;
				left: 50%;
				transform: translate(-50%, -50%);
				&.x {
					width: 100%;
					border-top-width: 0.1rem;
				}
				&.y {
					height: 100%;
					border-left-width: 0.1rem;
				}
				&.z {
					width: 50%;
					border-top-width: 0.1rem;
					border-color: #454754;
					transform: translate(0%, -50%) rotateZ(var(--rotateZ));
					transform-origin: left center;
				}
			}
		}
	}
</style>
