<template>
	<view class="fs-popover" :style="{ 'z-index': zIndex }">
		<view class="fs-popover-refer" @click="handleClickRefer"><slot name="refer"></slot></view>
		<view
			class="fs-popover-action"
			v-if="actionVisible"
			:class="['fs-popover-' + placement]"
			:style="{ 'z-index': zIndex }"
			@click="handleClose"
		>
			<view class="fs-popover-arrow"></view>
			<slot>
				<view
					class="fs-popover-action-item line1"
					:class="{ 'fs-popover-active': item[valueKey] && item[valueKey] === modelValue[valueKey] }"
					v-for="(item, index) in actions"
					:key="index"
					@click="handleClickAction(item)"
				>
					{{ item.text }}
				</view>
			</slot>
		</view>

		<fs-mask v-model="actionVisible" :z-index="1" bgColor="rgba(0,0,0,0)"></fs-mask>
	</view>
</template>

<script>
export default {
	name: 'fs-popover'
}
</script>

<script setup>
import { ref, onMounted, watch } from 'vue'
import utils from '@/utils/utils'

const props = defineProps({
	modelValue: [Object],
	valueKey: {
		type: String,
		default: 'id'
	},
	placement: {
		type: String,
		default: 'bottom',
		validator(value) {
			return [
				'top',
				'top-start',
				'top-end',
				'bottom',
				'bottom-start',
				'bottom-end',
				'left',
				'left-start',
				'left-end',
				'right',
				'right-start',
				'right-end'
			].includes(value)
		}
	},
	actions: Array,
	bgColor: {
		type: String,
		default: '#fff'
	},
	textColor: {
		type: String,
		default: '#666'
	},
	activeColor: {
		type: String,
		default: '#165DFF'
	},
	borderColor: {
		type: String,
		default: '#E8EAF2'
	},
	width: {
		type: String,
		default: 'auto'
	},
	actionWidth: {
		type: String,
		default: 'auto'
	}
})
const emits = defineEmits(['clickAction', 'visibleChange', 'update:modelValue'])
const uuid = utils.uuid()

const actionVisible = ref(false)
const handleClickRefer = () => {
	uni.$emit('popoverClose', { uuid: uuid })
	actionVisible.value = !actionVisible.value
}
watch(actionVisible, () => {
	emits('visibleChange')
})

const handleClickAction = item => {
	emits('update:modelValue', item)
	emits('clickAction', item)
}
const handleClose = () => {
	actionVisible.value = false
}

const zIndex = ref(10)
uni.$on('popoverClose', res => {
	if (uuid !== res.uuid) {
		zIndex.value = 10
		handleClose()
	} else {
		zIndex.value = 20
	}
})

defineExpose({
	handleClose
})
</script>

<style lang="scss" scoped>
$margin: 20rpx;
$arrowOffset: 30rpx;
$arrowSize: 24rpx;

.fs-popover {
	position: relative;
	display: inline-block;
	width: v-bind(width);

	&-action {
		position: absolute;
		min-width: 260rpx;
		max-width: 100%;
		width: v-bind(actionWidth);
		background-color: v-bind(bgColor);
		transition: opacity 0.15s, transform 0.15s;
		border-radius: 12rpx;
		padding: 0 30rpx;
		color: v-bind(textColor);
		border: 2rpx solid v-bind(borderColor);

		&-item {
			padding: 20rpx;
			& + & {
				border-top: 2rpx solid v-bind(borderColor);
			}
		}
	}

	&-active {
		color: v-bind(activeColor);
	}

	&-arrow {
		position: absolute;
		width: $arrowSize;
		height: $arrowSize;
		transform: rotate(45deg);
		z-index: 1000;
		background-color: v-bind(bgColor);
		border: 2rpx solid transparent;
		margin-top: -$arrowSize / 2;
		margin-left: -$arrowSize / 2;
	}

	&-top {
		left: 50%;
		bottom: 100%;
		transform: translateX(-50%);
		margin-bottom: $margin;
		.fs-popover-arrow {
			border-bottom-color: v-bind(borderColor);
			border-right-color: v-bind(borderColor);
			bottom: -$arrowSize / 2;
			left: 50%;
		}
	}
	&-top-start {
		left: 0;
		bottom: 100%;
		margin-bottom: $margin;
		.fs-popover-arrow {
			border-bottom-color: v-bind(borderColor);
			border-right-color: v-bind(borderColor);
			bottom: -$arrowSize / 2;
			left: $arrowOffset;
			margin-left: 0;
		}
	}
	&-top-end {
		right: 0;
		bottom: 100%;
		margin-bottom: $margin;
		.fs-popover-arrow {
			border-bottom-color: v-bind(borderColor);
			border-right-color: v-bind(borderColor);
			bottom: -$arrowSize / 2;
			right: $arrowOffset;
			margin-left: 0;
		}
	}

	&-bottom {
		left: 50%;
		top: 100%;
		transform: translateX(-50%);
		margin-top: $margin;

		.fs-popover-arrow {
			border-top-color: v-bind(borderColor);
			border-left-color: v-bind(borderColor);
			top: 0;
			left: 50%;
		}
	}
	&-bottom-start {
		left: 0;
		top: 100%;
		margin-top: $margin;

		.fs-popover-arrow {
			border-top-color: v-bind(borderColor);
			border-left-color: v-bind(borderColor);
			top: 0;
			left: $arrowOffset;
			margin-left: 0;
		}
	}
	&-bottom-end {
		right: 0;
		top: 100%;
		margin-top: $margin;

		.fs-popover-arrow {
			border-top-color: v-bind(borderColor);
			border-left-color: v-bind(borderColor);
			top: 0;
			right: $arrowOffset;
			margin-left: 0;
		}
	}

	&-left {
		left: -$margin;
		top: 50%;
		transform: translate(-100%, -50%);
		.fs-popover-arrow {
			border-bottom-color: v-bind(borderColor);
			border-right-color: v-bind(borderColor);
			top: 50%;
			right: -$arrowSize / 2;
			transform: rotate(-45deg);
		}
	}
	&-left-start {
		left: -$margin;
		top: 0;
		transform: translateX(-100%);

		.fs-popover-arrow {
			border-bottom-color: v-bind(borderColor);
			border-right-color: v-bind(borderColor);
			top: $arrowOffset;
			right: -$arrowSize / 2;
			transform: rotate(-45deg);
			margin-top: 0;
		}
	}
	&-left-end {
		left: -$margin;
		bottom: 0;
		transform: translateX(-100%);

		.fs-popover-arrow {
			border-bottom-color: v-bind(borderColor);
			border-right-color: v-bind(borderColor);
			bottom: $arrowOffset;
			right: -$arrowSize / 2;
			transform: rotate(-45deg);
			margin-top: 0;
		}
	}

	&-right {
		left: 100%;
		top: 50%;
		transform: translateY(-50%);
		margin-left: $margin;

		.fs-popover-arrow {
			border-bottom-color: v-bind(borderColor);
			border-left-color: v-bind(borderColor);
			top: 50%;
			left: 0;
		}
	}
	&-right-start {
		left: 100%;
		top: 0;
		margin-left: $margin;
		.fs-popover-arrow {
			border-bottom-color: v-bind(borderColor);
			border-left-color: v-bind(borderColor);
			top: $arrowOffset;
			left: 0;
			margin-top: 0;
		}
	}
	&-right-end {
		left: 100%;
		bottom: 0;
		margin-left: $margin;
		.fs-popover-arrow {
			border-bottom-color: v-bind(borderColor);
			border-left-color: v-bind(borderColor);
			left: 0;
			bottom: $arrowOffset;
			margin-top: 0;
		}
	}
}
</style>
