<template>
	<view class="Popover" :style="{'--theme-bg-color':bgStyleColor}">
		<view class="mark" @click="close()" v-show="inited"></view>
		<view @click.stop="handleClick" class="zb-button-popover">
			<slot></slot>
		</view>
		<view class="zb-popover" v-show="inited" ref="zb-transition" :class="[classes,`zb-popover-${placement}`]"
			:style="[mergeStyle]" @touchmove="noop">
			<view class="zb-popover-arrow" :style="[arrowStyle]" :class="[{
							'zb_popper__up':placement.indexOf('bottom')===0,
							'zb_popper__arrow':placement.indexOf('top')===0,
							'zb_popper__right':placement.indexOf('right')===0,
							'zb_popper__left':placement.indexOf('left')===0,
						}]">
			</view>
			<slot name="content">
				<view :class="[{'horizontal__action':actionsDirection==='horizontal'}]">
					<view @click.stop="actionAction(item)" v-for="item,index in options" class="zb-popover__action"
						:class="[{'dark__action':theme==='dark'}]" :key="index">
						<up-icon :name="item.icon" size="18" color="#333" />
						<view class="zb-popover__action-text">{{item.text}}</view>
					</view>
				</view>
			</slot>
		</view>
		
	</view>
</template>

<script>
	const tranClass = {
		enter: "zb-fade-zoom-enter zb-fade-zoom-enter-active",
		'enter-to': "zb-fade-zoom-enter-to zb-fade-zoom-enter-active",
		leave: "zb-fade-zoom-leave zb-fade-zoom-leave-active",
		'leave-to': "zb-fade-zoom-leave-to zb-fade-zoom-leave-active",
	}
	export default {
		props: {
			options: {
				type: Array,
				default: () => []
			},
			placement: {
				type: String,
				default: 'bottom-start'
			},
			bgColor: {
				type: String,

			},
			// light dark
			theme: {
				type: String,
				default: 'light'
			},
			// horizontal vertical
			actionsDirection: {
				type: String,
				default: 'vertical'
			}
		},
		name: "Popover",
		watch: {
			show: {
				handler(newVal) {
					newVal ? this.vueEnter() : this.vueLeave()
				},
				// 表示同时监听初始化时的props的show的意思
				immediate: true
			}
		},
		data() {
			return {
				show: false,
				inited: false, // 是否显示/隐藏组件
				classes: '', // 应用的类名
				display: false, // 组件是否展示
				duration: 100,
				popoverStyle: {

				},
				arrowOldStyle: {}
			};
		},
		computed: {

			bgStyleColor() {
				if (this.bgColor) {
					return this.bgColor
				}
				if (this.theme === 'light') {
					return 'white'
				}
				if (this.theme === 'dark') {
					return '#4a4a4a'
				}
			},

			mergeStyle() {
				return {
					transitionDuration: `${this.duration}ms`,
					transitionTimingFunction: `ease-out`,
					...this.popoverStyle
				}
			},
			arrowStyle() {
				return {
					...this.arrowOldStyle
				}
			}
		},
		mounted() {
			// window.addEventListener('click', () => {
			// 	this.show = false
			// })
		},
		methods: {
			handleClick() {
				if (this.show) {
					this.show = false
				} else {
					this.show = true
				}
				this.$emit('handleClick', this.show)
			},
			close() {
				this.show = false
			},
			actionAction(item) {
				this.$emit('select', item)
				this.show = false
			},
			sleep(value) {
				return new Promise((resolve) => {
					setTimeout(() => {
						resolve()
					}, value)
				})
			},
			vueEnter() {
				this.inited = true
				this.getPosition()
				this.classes = tranClass.enter
				this.$nextTick(async () => {
					await this.sleep(30)
					this.classes = tranClass['enter-to']

				})
			},
			vueLeave() {
				this.classes = tranClass.leave

				this.$nextTick(async () => {
					this.classes = tranClass['leave-to']
					await this.sleep(120)
					this.inited = false
				})
			},
			// 阻止事件冒泡
			preventEvent(e) {
				e && typeof(e.stopPropagation) === 'function' && e.stopPropagation()
			},

			getPosition() {
				return new Promise((resolve) => {
					this.$nextTick(() => {
						let selectorQuery = uni.createSelectorQuery().in(this).selectAll(
							'.zb-button-popover,.zb-popover')
						selectorQuery.boundingClientRect(async (data) => {
							let {
								left,
								bottom,
								right,
								top,
								width,
								height
							} = data[0]
							let popoverClientRect = data[1]
							let popoverStyle = {}
							let arrowOldStyle = {}

							switch (this.placement) {
								case 'top':
									if (popoverClientRect.width > width) {
										popoverStyle.left =
											`-${(popoverClientRect.width - width)/2}px`
									} else {
										popoverStyle.left =
											`${Math.abs(popoverClientRect.width - width)/2}px`
									}
									popoverStyle.bottom = `${height+8}px`
									arrowOldStyle.left = (popoverClientRect.width / 2 - 6) +
										'px'
									break;
								case 'top-start':
									popoverStyle.left = `0px`
									popoverStyle.bottom = `${height+8}px`
									arrowOldStyle.left = '16px'
									break;
								case 'top-end':
									popoverStyle.right = `0px`
									popoverStyle.bottom = `${height+8}px`
									arrowOldStyle.right = '16px'
									break;
								case 'bottom':
									if (popoverClientRect.width > width) {
										popoverStyle.left =
											`-${(popoverClientRect.width - width)/2}px`
									} else {
										popoverStyle.left =
											`${Math.abs(popoverClientRect.width - width)/2}px`
									}
									popoverStyle.top = `${height+8}px`
									arrowOldStyle.left = (popoverClientRect.width / 2 - 6) +
										'px'
									break;
								case 'bottom-start':
									popoverStyle.top = `${height+8}px`
									popoverStyle.left = `0px`
									arrowOldStyle.left = '16px'
									break;
								case 'bottom-end':
									popoverStyle.top = `${height+8}px`
									popoverStyle.right = `0px`
									arrowOldStyle.right = '16px'
									break;
								case 'right':
									popoverStyle.left = `${width+8}px`
									if (popoverClientRect.height > height) {
										popoverStyle.top =
											`-${(popoverClientRect.height - height)/2}px`
									} else {
										popoverStyle.top =
											`${Math.abs((popoverClientRect.height - height)/2)}px`
									}
									arrowOldStyle.top = `${popoverClientRect.height/2-6}px`
									break;
								case 'right-start':
									popoverStyle.left = `${width+8}px`
									popoverStyle.top = `0px`
									arrowOldStyle.top = `8px`
									break;
								case 'right-end':
									popoverStyle.left = `${width+8}px`
									popoverStyle.bottom = `0px`
									arrowOldStyle.bottom = `8px`
									break;
								case 'left':
									popoverStyle.right = `${width+8}px`
									if (popoverClientRect.height > height) {
										popoverStyle.top =
											`-${(popoverClientRect.height - height)/2}px`
									} else {
										popoverStyle.top =
											`${Math.abs((popoverClientRect.height - height)/2)}px`
									}
									arrowOldStyle.top = `${popoverClientRect.height/2-6}px`
									break;
								case 'left-start':
									popoverStyle.right = `${width+8}px`
									popoverStyle.top = `0px`
									arrowOldStyle.top = `8px`
									break;

								case 'left-end':
									popoverStyle.right = `${width+8}px`
									popoverStyle.bottom = `0px`
									arrowOldStyle.bottom = `8px`
									break;
							}

							this.popoverStyle = popoverStyle
							this.arrowOldStyle = arrowOldStyle
							resolve()
						}).exec()
					})
				})
			},
			// 空操作
			noop(e) {
				this.preventEvent(e)
			}
		}
	}
</script>

<style lang="scss" scoped>
	.mark { position: fixed; left: 0; right: 0; top: 0; bottom: 0; z-index: 1; background-color: rgba(0, 0, 0, 0.4); }
	$theme-bg-color: var(--theme-bg-color);

	.Popover {
		position: relative;
	}

	.zb-button-popover {
		display: inline-block;
	}

	.zb-popover {
		border-radius: 8px;
		z-index: 2144;
		position: absolute;
		background-color: $theme-bg-color;
		box-shadow: 0 2px 12px #3232331f;

	}

	.zb-popover-top {
		transform-origin: 50% bottom;
	}

	.zb-popover-top-start {
		transform-origin: 50% bottom;
	}

	.zb-popover-top-end {
		transform-origin: 0 bottom;
	}

	.zb-popover-bottom {
		transform-origin: 50% 0;
	}

	.zb-popover-bottom-end {
		transform-origin: 100% 0;
	}

	.zb-popover-bottom-start {
		transform-origin: 0 0;
	}

	.zb-popover-right {
		transform-origin: left 50%;
	}

	.zb-popover-right-start {
		transform-origin: left 0;
	}

	.zb-popover-right-end {
		transform-origin: left 100%;
	}

	.zb-popover-left {
		transform-origin: right 50%;
	}

	.zb-popover-left-start {
		transform-origin: right 0;
	}

	.zb-popover-left-end {
		transform-origin: right 100%;
	}

	.zb-popover-arrow {
		position: absolute;
		width: 0;
		height: 0;
		border-color: transparent;
		border-style: solid;
		border-width: 6px;
		color: $theme-bg-color;
	}

	.zb_popper__up {
		border-top-width: 0;
		border-bottom-color: currentColor;
		top: -6px;
	}

	.zb_popper__right {
		border-left-width: 0;
		border-right-color: currentColor;
		left: -5px;
	}

	.zb_popper__left {
		border-right-width: 0;
		border-left-color: currentColor;
		right: -5px;
	}

	.zb_popper__arrow {
		border-bottom-width: 0;
		border-top-color: currentColor;
		bottom: -6px;
	}

	.zb-popover__action {
		position: relative;
		display: flex;
		box-sizing: border-box;
		height: 88rpx;
		padding: 0 30rpx;
		font-size: 30rpx;
		cursor: pointer;
	}

	.zb-popover__action-text {
		display: flex;
		flex: 1;
		align-items: center;
		height: 100%;
		padding: 0 24rpx;
		border-bottom: 1rpx solid #ebedf0;
		word-wrap: break-word;
		white-space: nowrap;
	}

	.zb-popover__action:last-child {
		.zb-popover__action-text {
			border-bottom: none;
		}
	}

	.dark__action {
		color: white;

		.zb-popover__action-text {
			border-bottom: 1rpx solid #ebedf033
		}
	}

	.horizontal__action {
		display: flex;

		.zb-popover__action {
			padding: 0 20rpx;
			border-right: 1rpx solid #ebedf0;
		}

		.zb-popover__action-text {
			padding: 0;
			//border-right:1rpx solid #ebedf0;
		}
	}


	$u-zoom-scale: scale(0.95);

	.zb-fade-enter-active,
	.zb-fade-leave-active {
		transition-property: opacity;
	}

	.zb-fade-enter,
	.zb-fade-leave-to {
		opacity: 0
	}

	.zb-fade-zoom-enter,
	.zb-fade-zoom-leave-to {
		transform: $u-zoom-scale;
		opacity: 0;
	}

	.zb-fade-zoom-enter-active,
	.zb-fade-zoom-leave-active {
		transition-property: transform, opacity;
	}

	.zb-fade-down-enter-active,
	.zb-fade-down-leave-active,
	.zb-fade-left-enter-active,
	.zb-fade-left-leave-active,
	.zb-fade-right-enter-active,
	.zb-fade-right-leave-active,
	.zb-fade-up-enter-active,
	.zb-fade-up-leave-active {
		transition-property: opacity, transform;
	}

	.zb-fade-up-enter,
	.zb-fade-up-leave-to {
		transform: translate3d(0, 100%, 0);
		opacity: 0
	}

	.zb-fade-down-enter,
	.zb-fade-down-leave-to {
		transform: translate3d(0, -100%, 0);
		opacity: 0
	}

	.zb-fade-left-enter,
	.zb-fade-left-leave-to {
		transform: translate3d(-100%, 0, 0);
		opacity: 0
	}

	.zb-fade-right-enter,
	.zb-fade-right-leave-to {
		transform: translate3d(100%, 0, 0);
		opacity: 0
	}


	.zb-popover__action {
		&:active {
			background-color: rgba(0, 0, 0, 0.2);
		}

		&--disabled {
			color: var(--van-popover-dark-action-disabled-text-color);

			&:active {
				background-color: transparent;
			}
		}
	}
</style>