<template>
	<div class="assembly-hot-image">
		<div class="upload">
			<div class="box">
				<cl-upload
					@success="onChange"
					text="上传图片"
					v-model="value.pic"
					:size="[80, 80]"
				></cl-upload>
				<div class="link">
					<assembly-link v-model="value.link" :prepend="false" @change="onChange" />
					<div class="tips">建议图片宽度750px</div>
				</div>
			</div>
		</div>
		<div class="hot" v-if="value.pic">
			<div ref="imageRect" class="attr-box">
				<img :src="value.pic" class="icon" />
				<div
					v-for="(item, index) in value.attr"
					:key="index"
					class="hot-spot"
					:style="{
						width: `${item.relativeW}px`,
						height: `${item.relativeH}px`,
						top: `${item.relativeY}px`,
						left: `${item.relativeX}px`,
						zIndex: item.index
					}"
				>
					<div class="link-name">{{ item.link.name }}</div>
				</div>
			</div>
		</div>
		<div class="add" @click="open" v-if="value.pic">
			<el-button link type="primary">打开热区设置</el-button>
		</div>
		<cl-dialog title="图片热区设置" width="500px" v-model="showHotMap">
			<el-scrollbar height="500px" @scroll="handleScroll">
				<div class="container" ref="container">
					<img ref="imageRef" :src="value.pic" draggable="false" class="icon" />
					<div
						v-for="(item, index) in attr"
						:key="index"
						class="draggable-resizable"
						:style="{
							width: `${item.w}px`,
							height: `${item.h}px`,
							zIndex: item.index,
							left: `${item.x}px`,
							top: `${item.y}px`
						}"
					>
						<el-icon class="close" @click.stop="remove(index)">
							<close-bold />
						</el-icon>
						<assembly-link
							:ref="(el: any) => (linkRefs[index] = el)"
							v-model="attr[index].link"
						>
							<div class="link-name" @click="addLink(index)">
								{{ item.link.name }}
							</div>
						</assembly-link>
						<div class="resize-handle top-left"></div>
						<div class="resize-handle top-right"></div>
						<div class="resize-handle bottom-left"></div>
						<div class="resize-handle bottom-right"></div>
						<div class="resize-handle top"></div>
						<div class="resize-handle right"></div>
						<div class="resize-handle bottom"></div>
						<div class="resize-handle left"></div>
					</div>
				</div>
			</el-scrollbar>
			<template #footer>
				<div>
					<el-button type="primary" @click="add">添加热区</el-button>
					<el-button type="success" @click="saveHotMap">保存热区</el-button>
				</div>
			</template>
		</cl-dialog>
	</div>
</template>

<script lang="ts" name="assembly-hot-image" setup>
import { ref, nextTick, type PropType } from "vue";
import { cloneDeep } from "lodash-es";
import { CloseBold } from "@element-plus/icons-vue";
import { Form } from "../../types/form";
import { DraggableResizableClass } from "../../static/js/DraggableResizableClass";

const props = defineProps({
	modelValue: {
		type: Object as PropType<Form.HotImage>,
		default: () => {
			return {
				pic: "",
				width: 0,
				height: 0,
				link: {},
				attr: []
			};
		}
	}
});

const emit = defineEmits(["update:modelValue"]);

const imageRef = ref<HTMLImageElement | null>(null);
const imageRect = ref<HTMLImageElement | null>(null);

const linkRefs = ref<any[]>([]);
const value = ref(props.modelValue);
const showHotMap = ref(false);
const attr = ref<Form.Hot[]>([]);

const container = ref<HTMLElement | null>(null);
let draggableResizableInstance: DraggableResizableClass | null = null;

function open() {
	attr.value = cloneDeep(value.value.attr);
	if (!attr.value.length) {
		add();
	}
	showHotMap.value = true;
	nextTick().then(() => {
		if (container.value) {
			draggableResizableInstance = new DraggableResizableClass(container.value, attr.value);
		}
		if (imageRef.value) {
			const canvas = imageRef.value.getBoundingClientRect();
			value.value.width = canvas.width;
			value.value.height = canvas.height;
		}
	});
}
const scrollTop = ref(0);
const handleScroll = (event) => {
	scrollTop.value = event.scrollTop;
};
function add() {
	const len = attr.value.length;
	let index = 1;
	if (len) {
		index = attr.value[len - 1].index + 1;
	}
	attr.value.push({
		x: 20,
		y: scrollTop.value + 20,
		w: 100,
		h: 60,
		relativeX: 0,
		relativeY: 0,
		relativeW: 0,
		relativeH: 0,
		index: index,
		link: {
			page: "",
			appid: "",
			type: "",
			name: "添加链接"
		}
	});
	nextTick(() => {
		if (draggableResizableInstance) {
			draggableResizableInstance.updateListeners();
		}
	});
}

function addLink(index: number) {
	linkRefs.value[index]?.open();
}

function remove(index: number) {
	attr.value.splice(index, 1);
	linkRefs.value.splice(index, 1);
	if (draggableResizableInstance) {
		draggableResizableInstance.updateListeners();
	}
}

async function saveHotMap() {
	adjustElements();
	value.value.attr = attr.value;
	onChange();
	showHotMap.value = false;
}
// 调整等比例缩放位置 大小
function adjustElements() {
	// 计算缩放比例
	const { width, height } = imageRect.value!.getBoundingClientRect();
	const scaleX = width / value.value.width;
	const scaleY = height / value.value.height;
	// 调整子元素属性
	attr.value.forEach((element) => {
		element.relativeX = Math.floor(element.x * scaleX);
		element.relativeY = Math.floor(element.y * scaleY);
		element.relativeW = Math.floor(element.w * scaleX);
		element.relativeH = Math.floor(element.h * scaleY);
	});
}

function onChange() {
	emit("update:modelValue", value.value);
}
</script>

<style lang="scss" scoped>
.assembly-hot-image {
	.upload {
		box-sizing: border-box;
		background-color: #f6f7fa;
		border-radius: 10px;
		padding: 6px;
		margin-bottom: 10px;

		.box {
			box-sizing: border-box;
			display: flex;
			background-color: #ffffff;
			padding: 10px;
			border-radius: 6px;

			.link {
				box-sizing: border-box;
				margin-left: 10px;
			}
			.tips {
				font-size: 14px;
				margin-top: 10px;
				color: var(--el-color-warning);
			}
		}
	}

	.hot {
		margin-top: 20px;
		width: 100%;
		padding: 10px;
		box-sizing: border-box;
		background-color: #f6f7fa;
		border-radius: 10px;
		min-height: 100px;
		.attr-box {
			position: relative;
			display: inline-block;
			width: 100%;
			height: 100%;
			.icon {
				width: 100%;
				height: auto;
				max-width: 100%;
				vertical-align: middle;
			}
			.hot-spot {
				position: absolute;
				background-color: rgb(73 104 217 / 35%);
				border: 1px dashed white;
				display: flex;
				justify-content: center;
				align-items: center;
				overflow: hidden;
				user-select: auto;
				-webkit-user-select: auto;
				-moz-user-select: auto;
				user-select: none; /* 禁用选中 */
				outline: none; /* 移除焦点样式 */
				.link-name {
					font-size: 12px;
					color: #fff;
					line-height: 16px;
				}
			}
		}
	}
	.add {
		margin-top: 20px;
		display: flex;
		align-items: center;
		justify-content: center;
		height: 30px;
		border: 1px solid var(--el-border-color);
		border-radius: 6px;
		cursor: pointer;
	}
}

.container {
	position: relative;
	width: 460px;
	height: 100%;
	.icon {
		width: 100%;
		height: auto;
		max-width: 100%;
		vertical-align: middle;
		user-select: none; /* 禁用选中 */
	}

	.draggable-resizable {
		position: absolute;
		overflow: visible;
		background-color: rgb(73 104 217 / 35%);
		border: 1px dashed white;
		display: flex;
		justify-content: center;
		align-items: center;
		cursor: move;
		user-select: auto;
		-webkit-user-select: auto;
		-moz-user-select: auto;
		user-select: none; /* 禁用选中 */
		outline: none; /* 移除焦点样式 */
		.resize-handle {
			position: absolute;
			width: 10px;
			height: 10px;
			border-radius: 5px;
			background: #fff;
			bottom: 0;
			right: 0;
			z-index: 10;
			cursor: se-resize; /* 确保缩放时光标正确 */
			/* 添加特定位置的样式 */
			&.top-left {
				top: -5px;
				left: -5px;
				cursor: nw-resize;
			}
			&.top-right {
				top: 0;
				right: 0;
				cursor: ne-resize;
			}
			&.bottom-left {
				bottom: -5px;
				left: -5px;
				cursor: sw-resize;
			}
			&.bottom-right {
				bottom: -5px;
				right: -5px;
				cursor: se-resize;
			}
			&.top {
				top: -5px;
				left: 50%;
				transform: translateX(-50%);
				cursor: n-resize;
				width: 10px;
				height: 10px;
			}
			&.right {
				right: -5px;
				top: 50%;
				transform: translateY(-50%);
				cursor: e-resize;
			}
			&.bottom {
				bottom: -5px;
				left: 50%;
				transform: translateX(-50%);
				cursor: s-resize;
				width: 10px;
				height: 10px;
			}
			&.left {
				left: -5px;
				top: 50%;
				transform: translateY(-50%);
				cursor: w-resize;
			}
		}

		.link-name {
			font-size: 14px;
			color: #ffffff;
			cursor: pointer;
			max-width: 100px;
			overflow: hidden;
			user-select: none; /* 禁用选中 */
		}

		.link-name:hover {
			color: var(--el-color-danger);
			cursor: pointer;
		}

		.close {
			position: absolute;
			right: 0;
			top: 0;
			height: 14px;
			width: 14px;
			color: #fff;
			z-index: 11;
			background-color: var(--el-color-black);
			padding: 1px;
			cursor: pointer;
			user-select: none; /* 禁用选中 */

			&:hover {
				background-color: red;
			}
		}
	}
}
</style>
