<template>
	<view v-if="visible" :class="['el-popup-wrapper',`${direction}`,`is-${status ? 'open' : 'close'}`]" :style="{ zIndex }" @touchmove.stop.prevent>
		<view class="modal" :style="{ background: modalBackground }" @click="modalClose" v-if="modal"></view>
		<view class="el-popup" :style="{ height, width, backgroundColor, borderRadius: parseRpx(borderRadius) }">
			<view class="container" :style="{ padding: parseRpx(padding), paddingTop }">
				<slot></slot>
			</view>
		
			<view class="close" v-if="status && showCloseBtn" @click="close">
				<uni-icons type="closeempty" size="20" color="#888"></uni-icons>
			</view>
		</view>
	</view>
</template>

<script setup>
	import { onUnload } from "@dcloudio/uni-app"
	import { ref,watch,computed } from "vue";
	import { isArray,isNumber } from "@/el-ui/libs/check.js"
	
	const props = defineProps({
		direction: {
			type: String, // "top" | "right" | "bottom" | "center" | "left"
			default: "center",
		},
		size: {
			type: [String, Number],
			default: "auto",
		},
		borderRadius: [String, Number],
		padding: {
			type: [String, Number],
			default: 32,
		},
		showCloseBtn: {
			type: Boolean,
			default: true
		},
		backgroundColor: {
			type: String,
			default: "#fff",
		},
		modal: {
			type: Boolean,
			default: true,
		},
		modalBackground: {
			type: String,
			default: "rgba(0, 0, 0, 0.4)",
		},
		closeOnClickModal: {
			type: Boolean,
			default: true,
		},
		zIndex: {
			type: Number,
			default: 1000000,
		}
	});
	
	// #ifdef H5
	onUnload(()=>{
		document.getElementsByTagName('body')[0].style.overflow = 'visible';
	});
	// #endif
	
	let id = 1;
	const emits = defineEmits(["open", "opened","opened", "close", "closed"]);
	
	// 是否可见
	const visible = ref(false);
	
	// 动画状态
	const status = ref(false);
	
	// 层级
	const zIndex = ref(0);
	
	// 计时器
	let timer = null;
	
	const { statusBarHeight } = uni.getSystemInfoSync();

	const parseRpx = (val)=>{
		return isArray(val) ? val.map(parseRpx).join(" ") : isNumber(val) ? `${val}rpx` : val;
	}
	
	const height = computed(() => {
		switch (props.direction) {
			case "top":
			case "bottom":
				return parseRpx(props.size);
			case "left":
			case "right":
				return "100%";
		}
	});
	
	const width = computed(() => {
		switch (props.direction) {
			case "top":
			case "bottom":
				return "100%";
			case "left":
			case "right":
			case "center":
				return parseRpx(props.size);
		}
	});
	
	// 顶部距离
	const paddingTop = computed(() => {
		if (["left", "right", "top"].includes(props.direction)) {
			let h = 0;
	
			// #ifdef H5 || APP || MP-WEIXIN
			h += statusBarHeight || 0;
			// #endif
	
			// #ifdef H5
			h += 44;
			// #endif
	
			let [t] = parseRpx(props.padding).split(" ");
	
			if (t == "0rpx") {
				t = "0px";
			}
	
			return `calc(${h}px + ${t})`;
		} else {
			return 1;
		}
	});
	
	// 打开
	const open = ()=>{
		zIndex.value = props.zIndex + id++;
		if(!visible.value) {
			visible.value = true;
			emits("open");
			
			// #ifdef H5
			document.getElementsByTagName('body')[0].style.overflow = 'hidden';
			// #endif
			
			clearTimeout(timer);
			timer = setTimeout(() => {
				status.value = true;
				timer = setTimeout(() => {
					emits("opened");
				}, 350);
			}, 50);
		}
	}
	
	// 关闭
	const close = ()=>{
		if (status.value) {
			const done = () => {
				status.value = false;
				emits("close");
				
				// #ifdef H5
				document.getElementsByTagName('body')[0].style.overflow = 'visible';
				// #endif
				
				clearTimeout(timer);
				timer = setTimeout(() => {
					visible.value = false;
					emits("closed");
				}, 300);
			};
	
			done();
		}
	}
	
	// 遮罩层关闭
	const modalClose = ()=>{
		if (!props.closeOnClickModal) {
			return false;
		}
	
		close();
	}
	
	defineExpose({
		open: open,
		close: close
	});
	
</script>

<style lang="scss" scoped>
	.el-popup-wrapper {
		position: fixed;
		top: 0;
		bottom: 0;
		left: 0;
		right: 0;
		opacity: 0;
		transition: all 0.3s;
		pointer-events: none;
		
		&::after {
			content: "";
			display: inline-block;
			height: 100%;
			width: 0;
			vertical-align: middle;
		}
		
		.modal {
			height: 100%;
			width: 100%;
			position: absolute;
			top: 0;
			bottom: 0;
			left: 0;
			right: 0;
		}
		
		.el-popup {
			background-color: #fff;
			position: absolute;
			transition: all 0.3s;
			box-sizing: border-box;
			.container {
				height: 100%;
				box-sizing: border-box;
			}
			
			.close {
				position: absolute;
				top: 10rpx;
				right: 20rpx;
			}
		}
		
		&.left {
			.el-popup {
				transform: translateX(-100%);
				top: 0;
				left: 0;
			}
		}
		
		&.right {
			.el-popup {
				transform: translateX(100%);
				right: 0;
				top: 0;
			}
		}
		
		&.top {
			.el-popup {
				transform: translateY(-100%);
				left: 0;
				top: 0;
			}
		}
		
		&.bottom {
			.el-popup {
				transform: translateY(100%);
				left: 0;
				bottom: 0;
				border-top-left-radius: 20rpx;
				border-top-right-radius: 20rpx;
			}
		}
		
		&.center {
			display: flex;
			flex-direction: column;
			justify-content: center;
			align-items: center;
		
			.el-popup {
				transform: scale(1.3);
			}
		}
		
		&.left,
		&.right,
		&.bottom {
			.el-popup {
				padding-bottom: env(safe-area-inset-bottom);
			}
		}
		
		&.is-open {
			pointer-events: auto;
			opacity: 1;
		
			.el-popup {
				transition: all 0.4s;
				transform: translate(0, 0);
			}
		}
	}
</style>