<template>
	<el-dialog
		class="clipDialog"
		v-model="showPanel"
		align-center
		:show-close="false"
		width="75rem"
		height="69rem"
		style="border-radius: 2rem; padding: 4rem; --el-dialog-padding-primary: 1rem"
	>
		<template #header="{ close }">
			<div class="clip-header">
				<div class="title">{{ $t("clipDialog.title") }}</div>
				<span class="close" @click="close">
					<svg-icon name="close" size="12" color="#000" />
				</span>
			</div>
		</template>
		<div class="crop-image-modal">
			<div class="modal-content">
				<div class="clip">
					<!-- 图片剪切 -->
					<div class="image-clip" ref="el" v-if="data.url">
						<div
							class="box"
							ref="box"
							:style="{
								width: clipData.img_width + 'px',
								height: clipData.img_height + 'px',
							}"
						>
							<img :src="data.url" />
							<div class="shade"></div>
							<div
								ref="clipRef"
								class="clip"
								:style="{
									top: clipData.top + 'px',
									left: clipData.left + 'px',
									width: clipData.width + 'px',
									height: clipData.height + 'px',
								}"
								@mousedown.stop="clipMousedown"
								@touchstart.stop="clipMousedown"
							>
								<div class="img">
									<img
										:src="data.url"
										:style="{
											width: clipData.img_width + 'px',
											height: clipData.img_height + 'px',
											top: -clipData.top + 'px',
											left: -clipData.left + 'px',
										}"
									/>
								</div>
								<div
									class="top"
									@mousedown.stop="topMousedown"
									@touchstart.stop="topMousedown"
								></div>
								<div
									class="right"
									@mousedown.stop="rightMousedown"
									@touchstart.stop="rightMousedown"
								></div>
								<div
									class="bottom"
									@mousedown.stop="bottomMousedown"
									@touchstart.stop="bottomMousedown"
								></div>
								<div
									class="left"
									@mousedown.stop="leftMousedown"
									@touchstart.stop="leftMousedown"
								></div>
								<span
									class="top"
									@mousedown.stop="topMousedown"
									@touchstart.stop="topMousedown"
								></span>
								<span
									class="right"
									@mousedown.stop="rightMousedown"
									@touchstart.stop="rightMousedown"
								></span>
								<span
									class="bottom"
									@mousedown.stop="bottomMousedown"
									@touchstart.stop="bottomMousedown"
								></span>
								<span
									class="left"
									@mousedown.stop="leftMousedown"
									@touchstart.stop="leftMousedown"
								></span>
							</div>
						</div>
					</div>
					<!-- 空状态 -->
					<!-- <div class="empty-state" v-else>
						<div class="empty-icon">📷</div>
						<p>空</p>
					</div> -->
				</div>
			</div>
			<!-- <div class="operation">
				<div class="operation-btn">
					<svg-icon name="clipMinus" size="22" color="#000" />
				</div>
				<div class="slider">
					<el-slider v-model="clipSize" />
				</div>
				<div class="operation-btn">
					<svg-icon name="clipAdd" size="22" color="#000" />
				</div>
			</div> -->
			<div class="modal-footer">
				<div class="image-count" @click="close">	
					{{ $t("clipDialog.cancel") }}
				</div>
				<div class="image-submit" @click="confirm">
					{{ $t("clipDialog.confirm") }}
				</div>
			</div>
		</div>
	</el-dialog>
</template>

<script setup lang="ts">
	import {
		ref,
		computed,
		onDeactivated,
		reactive,
		nextTick,
	} from "vue";
	import { useI18n } from "vue-i18n";

	// Props
	const props = defineProps(
		{
			isRatio: {
				type: Boolean,
				default: true,
			}
		}
	);
	const { t } = useI18n();
	const clipSize = ref(0);
	var resolveFn: (value: string | PromiseLike<string>) => void;
	const showPanel = ref(false);
	const open = (url: string) => {
		showPanel.value = true;
		setImgage(url);
		return new Promise((resolve) => (resolveFn = resolve));
	};
	const close = () => {
		showPanel.value = false;
	};
	//提交选中的T图片
	const confirm = () => {
		const base64 = getImageBase64();
		resolveFn && resolveFn(base64);
		close();
	};

	const data = reactive({
		url: "",
	});
	const el = ref();
	const box = ref();
	const clipRef = ref();
	const clipData = reactive({
		top: 0,
		left: 0,
		width: 0,
		height: 0,
		img_width: 0,
		img_height: 0,
	});
	const canvas = document.createElement("canvas");
	const ctx = canvas.getContext("2d");
	const reload = () => {
		if (!el.value) return;
		const size = Math.min(
			1,
			el.value.offsetWidth / canvas.width,
			el.value.offsetHeight / canvas.height
		);
		const width = size * canvas.width;
		const height = size * canvas.height;
		clipSize.value = Math.min(width, height);
		clipData.left = 0;
		clipData.top = 0;
		clipData.width = props.isRatio ? clipSize.value : width;
		clipData.height = props.isRatio ? clipSize.value : height;
		clipData.img_width = width;
		clipData.img_height = height;
	};
	window.addEventListener("resize", reload);
	onDeactivated(() => {
		window.removeEventListener("resize", reload);
	});

	const setImgage = (url: string) => {
		if (!url) return;
		const img = new Image();
		img.onload = () => {
			const width = img.width;
			const height = img.height;
			canvas.width = width;
			canvas.height = height;
			ctx?.clearRect(0, 0, width, height);
			ctx?.drawImage(img, 0, 0, width, height);
			nextTick(() => reload());
		};
		img.src = url;
		data.url = url;
	};
	const canvasImageDataToBase64 = (imageData: any) => {
		// 创建一个临时的canvas元素
		const canvas = document.createElement("canvas");
		canvas.width = imageData.width;
		canvas.height = imageData.height;
		const ctx = canvas.getContext("2d");
		ctx?.putImageData(imageData, 0, 0);
		const dataURL = canvas.toDataURL("image/png");
		return dataURL;
	};
	const getImageBase64 = () => {
		const scale = canvas.width / clipData.img_width;
		const imageData = ctx?.getImageData(
			clipData.left * scale,
			clipData.top * scale,
			clipData.width * scale,
			clipData.height * scale
		);
		const base64 = canvasImageDataToBase64(imageData);
		return base64;
	};

	// 移动裁剪框
	const clipMousedown = (e: MouseEvent | TouchEvent) => {
		e.preventDefault();
		var pageX = 0;
		var pageY = 0;
		if (e.type == "touchstart") {
			const touch = e["touches"][0];
			pageX = touch.pageX;
			pageY = touch.pageY;
		} else {
			pageX = e["pageX"];
			pageY = e["pageY"];
		}
		const elInfo = box.value.getBoundingClientRect();
		const clipInfo = clipRef.value.getBoundingClientRect();
		// 鼠标相对元素的位置
		const CX = pageX - clipInfo.x;
		const CY = pageY - clipInfo.y;

		const mousemove = (e: MouseEvent | TouchEvent) => {
			e.preventDefault();
			var pageX = 0;
			var pageY = 0;
			if (e.type == "touchmove") {
				const touch = e["touches"][0];
				pageX = touch.pageX;
				pageY = touch.pageY;
			} else {
				pageX = e["pageX"];
				pageY = e["pageY"];
			}
			let x = pageX - elInfo.x - CX;
			let y = pageY - elInfo.y - CY;
			if (x < 0) {
				x = 0;
			} else if (x > elInfo.width - clipInfo.width) {
				x = elInfo.width - clipInfo.width;
			}
			if (y < 0) {
				y = 0;
			} else if (y > elInfo.height - clipInfo.height) {
				y = elInfo.height - clipInfo.height;
			}

			clipData.top = y;
			clipData.left = x;
			clipData.img_width = elInfo.width;
			clipData.img_height = elInfo.height;
		};
		const mouseup = () => {
			window.removeEventListener("mousemove", mousemove);
			window.removeEventListener("mouseup", mouseup);
			window.removeEventListener("touchmove", mousemove);
			window.removeEventListener("touchend", mouseup);
		};
		if (e.type == "touchstart") {
			window.addEventListener("touchmove", mousemove);
			window.addEventListener("touchend", mouseup);
		} else {
			window.addEventListener("mousemove", mousemove);
			window.addEventListener("mouseup", mouseup);
		}
	};

	// 移动裁剪框的四个边框
	const mousedown = (
		e: MouseEvent | TouchEvent,
		type: "top" | "bottom" | "right" | "left"
	) => {
		const minWidth = 20;
		const minHeight = 20;
		const elInfo = box.value.getBoundingClientRect();
		const R = elInfo.width - clipData.left - clipData.width;
		const B = elInfo.height - clipData.top - clipData.height;
		const noRatioMousemove = (e: MouseEvent | TouchEven)=>{
			var x = 0;
			var y = 0;
			if (e.type == "touchmove") {
				const touch = e["touches"][0];
				x = touch.pageX - elInfo.x;
				y = touch.pageY - elInfo.y;
			} else {
				x = e["pageX"] - elInfo.x;
				y = e["pageY"] - elInfo.y;
			}

			if (type == "right") {
				let width = x - clipData.left;
				if (width + clipData.left > elInfo.width) {
					width = elInfo.width - clipData.left;
				}
				if (width < minWidth) width = minWidth;
				clipData.width = width;
			} else if (type == "bottom") {
				let height = y - clipData.top;
				if (height + clipData.top > elInfo.height) {
					height = elInfo.height - clipData.top;
				}
				if (height < minHeight) height = minHeight;
				clipData.height = height;
			} else if (type == "left") {
				let left = x;
				let width = clipData.width;
				if (left < 0) {
					left = 0;
				} else if (left > elInfo.width - R - minWidth) {
					left = elInfo.width - R - minWidth;
				}
				width = elInfo.width - R - left;
				clipData.left = left;
				clipData.width = width;
				clipData.img_width = elInfo.width;
				clipData.img_height = elInfo.height;
			} else if (type == "top") {
				let top = y;
				let height = clipData.height;
				if (top < 0) {
					top = 0;
				} else if (top > elInfo.height - B - minHeight) {
					top = elInfo.height - B - minHeight;
				}
				height = elInfo.height - B - top;
				clipData.top = top;
				clipData.height = height;
				clipData.img_width = elInfo.width;
			}
		}
		const ratioMousemove = (e: MouseEvent | TouchEvent) => {
			var x = 0;
			var y = 0;
			if (e.type == "touchmove") {
				const touch = e["touches"][0];
				x = touch.pageX - elInfo.x;
				y = touch.pageY - elInfo.y;
			} else {
				x = e["pageX"] - elInfo.x;
				y = e["pageY"] - elInfo.y;
			}
			if (type == "right" || type == "bottom") {
				let width = x - clipData.left;
				let height = y - clipData.top;
				if (width + clipData.left > elInfo.width) {
					width = elInfo.width - clipData.left;
				}
				if (height + clipData.top > elInfo.height) {
					height = elInfo.height - clipData.top;
				}

				if (type == "right") {
					if (width < minWidth) {
						width = minWidth;
					}
					height = width;
					if (height + clipData.top > elInfo.height) {
						height = elInfo.height - clipData.top;
						width = height;
					}
				} else if (type == "bottom") {
					if (height < minHeight) {
						height = minHeight;
					}
					width = height;
					if (width + clipData.left > elInfo.width) {
						width = elInfo.width - clipData.left;
						height = width;
					}
				}
				clipData.width = width;
				clipData.height = height;
			} else if (type == "left" || type == "top") {
				let left = x;
				let top = y;
				let width = clipData.width;
				let height = clipData.height;
				if (type == "left") {
					if (left < 0) {
						left = 0;
					} else if (left > elInfo.width - R - minWidth) {
						left = elInfo.width - R - minWidth;
					}
					width = elInfo.width - R - left;
					top = elInfo.height - B - width;
					if (top < 0) {
						top = 0;
						width = height;
						left = elInfo.width - R - width;
					}
					height = elInfo.height - B - top;
				} else if (type == "top") {
					if (top < 0) {
						top = 0;
					} else if (top > elInfo.height - B - minHeight) {
						top = elInfo.height - B - minHeight;
					}
					height = elInfo.height - B - top;
					left = elInfo.width - R - height;
					if (left < 0) {
						left = 0;
						height = width;
						top = elInfo.height - B - height;
					}
					width = elInfo.width - R - left;
				}
				clipData.top = top;
				clipData.left = left;
				clipData.width = width;
				clipData.height = height;
				clipData.img_width = elInfo.width;
				clipData.img_height = elInfo.height;
			}
		}
		const mousemove = (e: MouseEvent | TouchEvent) => {
			if(props.isRatio){
				ratioMousemove(e)
			}else{
				noRatioMousemove(e)
			}
		};
		const mouseup = () => {
			window.removeEventListener("mousemove", mousemove);
			window.removeEventListener("mouseup", mouseup);
			window.removeEventListener("touchmove", mousemove);
			window.removeEventListener("touchend", mouseup);
		};
		if (e.type == "touchstart") {
			window.addEventListener("touchmove", mousemove);
			window.addEventListener("touchend", mouseup);
		} else {
			window.addEventListener("mousemove", mousemove);
			window.addEventListener("mouseup", mouseup);
		}
	};
	const topMousedown = (e: MouseEvent | TouchEvent) => {
		mousedown(e, "top");
	};
	const rightMousedown = (e: MouseEvent | TouchEvent) => {
		mousedown(e, "right");
	};
	const bottomMousedown = (e: MouseEvent | TouchEvent) => {
		mousedown(e, "bottom");
	};
	const leftMousedown = (e: MouseEvent | TouchEvent) => {
		mousedown(e, "left");
	};
	defineExpose({
		open,
		close,
	});
</script>

<style scoped lang="less">
	.clip-header {
		margin-top: 0.2rem;
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding-bottom: 3.3rem;
		border-bottom: 0.1rem solid rgba(0, 0, 0, 0.1);
		> .title {
			font-family: Semibold;
			font-size: 1.6rem;
			color: #000;
		}
		.close{
			cursor: pointer;
		}
	}
	/* 弹窗主体 */
	.crop-image-modal {
		background-color: #fff;
		display: flex;
		flex-direction: column;
	}
	.close-btn {
		background: none;
		border: none;
		font-size: 24px;
		cursor: pointer;
		color: #666;
		padding: 0;
		line-height: 1;
		opacity: 0.7;
		transition: all 0.2s;
		width: 24px;
		height: 24px;
		display: flex;
		align-items: center;
		justify-content: center;

		&:hover {
			opacity: 1;
			color: #333;
			transform: scale(1.1);
		}
	}

	/* 弹窗内容 */
	.modal-content {
		// padding: 20px;
		overflow: hidden;
		background-color: #fff;
		-webkit-overflow-scrolling: touch;
		display: flex;
		width: 47.2rem;
		height: 35.20rem;
		margin: 4rem auto;
		> .clip{
			background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKAQMAAAC3/F3+AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAGUExURf///9ra2sgNdccAAAARSURBVAjXY2A/wICMfjAgIwB8gwi84a8abQAAAABJRU5ErkJggg==);
			flex: 1;
			display: flex;
		}
		
	}
	.operation{
		display: flex;
		align-items: center;
		width: 52rem;
		margin: 0 auto;
		gap: 2rem;
		> .operation-btn{
			cursor: pointer;
		}
		> .slider{
			flex: 1;
			:deep(.el-slider){
				--el-slider-main-bg-color: #000;
			}
		}
	}
	.image-clip {
		user-select: none;
		flex: 1;
		display: flex;
		align-items: center;
		justify-content: center;
		> .box {
			position: relative;
			> img {
				display: block;
				width: 100%;
				height: 100%;
			}
			> .shade {
				position: absolute;
				top: 0;
				left: 0;
				right: 0;
				bottom: 0;
				background-color: rgba(0, 0, 0, 0.5);
			}
			> .clip {
				position: absolute;
				cursor: move;
				outline: 1px solid #39f;

				> * {
					position: absolute;
				}
				> .img {
					pointer-events: none;
					width: 100%;
					height: 100%;
					overflow: hidden;
					> img {
						position: absolute;
						background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKAQMAAAC3/F3+AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAGUExURf///9ra2sgNdccAAAARSURBVAjXY2A/wICMfjAgIwB8gwi84a8abQAAAABJRU5ErkJggg==);
					}
				}

				> .top {
					cursor: n-resize;
				}
				> .bottom {
					cursor: s-resize;
				}
				> .right {
					cursor: e-resize;
				}
				> .left {
					cursor: w-resize;
				}

				--border: 4px;
				--trbl: calc(0px - var(--border) / 2);
				--ball-size: 8px;
				--ball-trbl: calc(0px - var(--ball-size) / 2);
				> div.top {
					top: var(--trbl);
					left: 0;
					right: 0;
					height: var(--border);
				}

				> div.bottom {
					bottom: var(--trbl);
					left: 0;
					right: 0;
					height: var(--border);
				}
				> div.left {
					top: 0;
					left: var(--trbl);
					bottom: 0;
					width: var(--border);
				}
				> div.right {
					top: 0;
					right: var(--trbl);
					bottom: 0;
					width: var(--border);
				}
				> span {
					position: absolute;
					width: var(--ball-size);
					height: var(--ball-size);
					border-radius: 50%;
					background-color: #39f;
				}
				> span.top {
					top: var(--ball-trbl);
					left: 50%;
					transform: translateX(-50%);
				}
				> span.right {
					right: var(--ball-trbl);
					top: 50%;
					transform: translateY(-50%);
				}
				> span.bottom {
					bottom: var(--ball-trbl);
					left: 50%;
					transform: translateX(-50%);
				}
				> span.left {
					left: var(--ball-trbl);
					top: 50%;
					transform: translateY(-50%);
				}
			}
		}
	}

	/* 空状态 */
	.empty-state {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		color: #666;
		min-height: 300px;
		flex: 1;
		.empty-icon {
			font-size: 48px;
			margin-bottom: 16px;
			opacity: 0.5;
		}

		p {
			font-size: 16px;
			margin: 0;
		}
	}

	/* 弹窗底部 */
	.modal-footer {
		display: flex;
		justify-content: flex-end;
		align-items: center;
		flex-shrink: 0;
		gap: 1.6rem;
		// margin-top: 6.6rem;
		> div {
			cursor: pointer;
			width: 7.7rem;
			text-align: center;
			font-size: 1.2rem;
			line-height: 2.8rem;
			font-weight: 500;
			border-radius: 2rem;
			border: 1px solid #000;
		}
		.image-count{
			background-color: #fff;
			color: #000;
		}
		.image-submit{
			background-color: #000;
			color: #fff;
		}
	}
	.image-count {
		font-size: 14px;
		color: #666;
		font-weight: 500;
	}
</style>
