<template>
	<view class="context-menu none-pointer-events">
		<view @longpress.prevent.stop="onLongPress($event)" @touchmove="onTouchMove" @touchend="onTouchEnd">
			<slot></slot>
		</view>
		<view v-if="isShowMenu" class="menu-mask" @touchstart="onClose()" @contextmenu.prevent=""></view>
		<view v-if="isShowMenu" class="menu" :style="menuStyle">
			<view class="menu-item" v-for="(item) in items" :key="item.key" @click.prevent="onSelectMenu(item)">
				<text :style="itemStyle(item)"> {{ item.name }}</text>
			</view>
		</view>
	</view>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { ContextMenuProps, ContextMenuEmits } from '../../types/components/context-menu'
import type { TouchPoint } from '../../types/common'

const props = defineProps<ContextMenuProps>();
const emit = defineEmits<ContextMenuEmits>();

const isShowMenu = ref(false);
const isTouchMove = ref(false);
const menuStyle = ref("");
const menuTouch = ref<TouchPoint>({ clientX: 0, clientY: 0 });

const onLongPress = (e: any) => {
	if (isTouchMove.value) {
		// 屏幕移动时不弹出
		return;
	}

	uni.getSystemInfo({
		success: (res) => {
			const touches = e.touches[0];
			let style = "";
			/* 因 非H5端不兼容 style 属性绑定 Object ，所以拼接字符 */
			if (touches.clientY > (res.windowHeight / 2)) {
				style = `bottom:${res.windowHeight - touches.clientY + 20}px;`;
			} else {
				style = `top:${touches.clientY + 20}px;`;
			}
			if (touches.clientX > (res.windowWidth / 2)) {
				style += `right:${res.windowWidth - touches.clientX}px;`;
			} else {
				style += `left:${touches.clientX}px;`;
			}
			menuStyle.value = style;

			menuTouch.value = touches;
			isShowMenu.value = true;
		}
	});
};

const onTouchMove = (e: any) => {
	isTouchMove.value = true;
	const touches = e.touches[0];
	// 屏幕拖动大于50px时，取消菜单
	if (Math.abs(touches.clientX - menuTouch.value.clientX) > 50 ||
		Math.abs(touches.clientY - menuTouch.value.clientY) > 50) {
		onClose();
	}
};

const onTouchEnd = () => {
	isTouchMove.value = false;
};

const onSelectMenu = (item: any) => {
	emit("select", item);
	isShowMenu.value = false;
};

const onClose = () => {
	isShowMenu.value = false;
};

const itemStyle = (item: any) => {
	if (item.color) {
		return `color:${item.color};`;
	}
	return `color:#000;`;
};
</script>

<style lang="scss" scoped>
.context-menu {
	.menu-mask {
		position: fixed;
		left: 0;
		top: 0;
		right: 0;
		bottom: 0;
		width: 100%;
		height: 100%;
		z-index: 999;
	}

	.menu {
		position: fixed;
		border-radius: 4px;
		overflow: hidden;
		background-color: #fff;
		z-index: 1000;
		box-shadow: $im-box-shadow-dark;

		.menu-item {
			height: 28px;
			min-width: 120rpx;
			line-height: 28px;
			font-size: $im-font-size-small;
			display: flex;
			padding: 6px 20px;
			justify-content: flex-start;

			&:hover {
				background: $im-bg-active;
			}

			.menu-icon {
				margin-right: 10rpx;
			}
		}
	}
}
</style>