<template>
	<view class="popover-container" ref="popoverChild" @click.stop.prevent="change" :prop="visible" :change:prop="onShow">
		<slot></slot>
		<view :style="'visibility:' + (popoverShow ? 'visible' : 'hidden')">
			<view  class="popover-mask" @click.stop.prevent="prevent"  @touchstart.stop.prevent="hide" ></view>
			<view :class="'popover-content popover-content-' + calcPlacement" @click.stop.prevent="hide" ref="popoverContent" :style="(popoverShow ? 'opacity: 1;transform:unset;' : '') + popoverStyle">
				<view :class="'popover-arrow popover-arrow-' + calcPlacement" :style="arrowStyle">
					<view :class="'popover-arrow-icon popover-arrow-icon-' + calcPlacement"/>
				</view>
				<view class="popover-content-block">
					<slot name="popoverContent"></slot>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				popoverShow: false,
				popoverStyle: '',
				arrowStyle: '',
				visible: false,
				calcPlacement: 'topCenter'
			}
		},
		props: {
			placement: {
				type: String,
				default: 'top'
			}
		},
		
		methods: {
			prevent() {},
			change() {
				this.popoverStyle = ""
				this.visible = this.placement;
			},
			show({ popoverStyle, arrowStyle, calcPlacement }) {
				this.popoverShow = true;
				this.popoverStyle = `${popoverStyle}`;
				this.arrowStyle = arrowStyle;
				this.calcPlacement = calcPlacement;
			},
			hide() {
				this.popoverShow = false;
				this.visible = false;
			},
		}
	}
</script>
<script module="popover" lang="renderjs">
	const { screenWidth, screenHeight, windowHeight, windowWidth, windowBottom, windowTop } = uni.getSystemInfoSync();
	let instance;
	export default {
		methods: {
			onShow(nVal,oVal,ownerInstance,instance) {
				if(!nVal) return;
				const child = this.$refs.popoverChild;
				const content = this.$refs.popoverContent;
				const placement = this.visible || 'bottom';
				let popoverOptions = {};
				switch(placement) {
					case 'top':
						popoverOptions = this.calcVertical(child.$el, content.$el, 'top');
						break;
					case 'bottom':
						popoverOptions = this.calcVertical(child.$el, content.$el, 'bottom');
						break;
					case 'left':
						popoverOptions = this.calcHorizontal(child.$el, content.$el, 'left');
						break;
					case 'right':
						popoverOptions = this.calcHorizontal(child.$el, content.$el, 'right');
						break;
				}
				ownerInstance.callMethod('show', popoverOptions)
			},
			calcVertical(child, content, type) {
				const { offsetHeight: cOffsetHeight , offsetWidth: cOffsetWidth } = content;
				
				const { top: offsetTop, left: offsetLeft } = child.getBoundingClientRect();
				const { offsetHeight, offsetWidth } = child;
				let calcPlacement;
				let arrowStyle;
				let popoverStyle;
				let popoverHorizontal;
				let popoverVertical;
				// console.log(`windowTop:${windowTop}, windowBottom:${windowBottom}, windowHeight:${windowHeight}`,`cOffsetHeight: ${cOffsetHeight}`,`cOffsetWidth: ${cOffsetWidth}`,`offsetTop: ${offsetTop}`,`offsetLeft: ${offsetLeft}`, `offsetHeight: ${offsetHeight}`, `offsetWidth: ${offsetWidth}`)
				if(type == 'top') {
					if(cOffsetHeight > offsetTop) {
						popoverVertical = 'top: ' + (offsetTop + offsetHeight) + 'px;'
						calcPlacement = 'bottom';
					}else {
						popoverVertical = 'bottom: ' + (windowHeight - offsetTop) + 'px;'
						calcPlacement = 'top';
					}
				}
				if(type == 'bottom') {
					if(cOffsetHeight > (windowHeight - offsetHeight - offsetTop)) {
						popoverVertical = 'bottom: ' + (windowHeight - offsetTop) + 'px;'
						calcPlacement = 'top';
					}else {
						popoverVertical = 'top: ' + (offsetTop + offsetHeight) + 'px;'
						calcPlacement = 'bottom';
					}
				}
				
				const overWidth = (cOffsetWidth - offsetWidth)/2;
				const a = windowWidth - offsetLeft - offsetWidth;
				if( overWidth > (windowWidth - offsetLeft - offsetWidth)) {
					popoverHorizontal = 'right: ' + (windowWidth - offsetLeft - offsetWidth) + 'px;';
					arrowStyle = 'right: 12px';
					calcPlacement += 'Right';
				}
				else if(overWidth > offsetLeft) {
					popoverHorizontal = 'left: ' + offsetLeft + 'px;';
					arrowStyle = 'left: 12px';
					calcPlacement += 'Left';
				}
				else {
					popoverHorizontal = 'left: ' + (offsetLeft - overWidth) + 'px;';
					arrowStyle = 'left: 50%; transform: translateX(-50%)';
					calcPlacement += 'Center';
				}
				
				popoverStyle = popoverVertical + popoverHorizontal;
			
				return { popoverStyle, arrowStyle, calcPlacement };
			},
			calcHorizontal(child, content, type) {
				const { offsetHeight: cOffsetHeight , offsetWidth: cOffsetWidth } = content;
				const { top: offsetTop, left: offsetLeft } = child.getBoundingClientRect();
				const { offsetHeight, offsetWidth } = child;
				let calcPlacement;
				let arrowStyle;
				let popoverStyle;
				let popoverHorizontal;
				let popoverVertical;
				console.log(`offsetTop: ${offsetTop}`,`offsetLeft: ${offsetLeft}`, `offsetHeight: ${offsetHeight}`, `offsetWidth: ${offsetWidth}`)
				if(type == 'right') {
					if(cOffsetWidth > (windowWidth - offsetLeft - offsetWidth)) {
						popoverHorizontal = 'right: ' + (windowWidth - offsetLeft) + 'px;';
						calcPlacement = 'left';
					} else {
						popoverHorizontal = 'left: ' + (offsetLeft + offsetWidth) + 'px;';
						calcPlacement = 'right';
					}
					
				}
				
				if(type == 'left') {
					if(cOffsetWidth > offsetLeft) {
						popoverHorizontal = 'left: ' + (offsetLeft + offsetWidth) + 'px;';
						calcPlacement = 'right';
					} else {
						popoverHorizontal = 'right: ' + (windowWidth - offsetLeft) + 'px;';
						calcPlacement = 'left';
					}
				}
				
				const overHeight = (cOffsetHeight - offsetHeight)/2;
				if( overHeight > (windowHeight - offsetTop - offsetHeight)) {
					popoverVertical = 'bottom: ' + (windowHeight - offsetTop - offsetHeight) + 'px;';
					arrowStyle = 'bottom: 12px';
					calcPlacement += 'Bottom';
				}
				else if(overHeight > offsetTop) {
					popoverVertical = 'top: ' + offsetTop + 'px;';
					arrowStyle = 'top: 12px';
					calcPlacement += 'Top';
				}
				else {
					popoverVertical = 'top: ' + (offsetTop - overHeight) + 'px;';
					arrowStyle = 'top: 50%;transform: translateY(-50%)';
					calcPlacement += 'Center';
				}
				
				popoverStyle = popoverVertical + popoverHorizontal;
				
				return { popoverStyle, arrowStyle, calcPlacement };
			}
		}
	}
</script>

<style lang="scss" scoped>
	.popover-container {
		display: inline-block;
	}
	.popover-mask {
		position: fixed;
		top: 0;
		right: 0;
		bottom: 0;
		left: 0;
		z-index: 98;
	}
	
	.popover-arrow {
		position: absolute;
		width: 14rpx;
		height: 14rpx;
	}
	.popover-arrow-leftTop,
	.popover-arrow-leftBottom,
	.popover-arrow-leftCenter {
		right: -8rpx;
	}
	.popover-arrow-rightTop,
	.popover-arrow-rightBottom,
	.popover-arrow-rightCenter {
		left: -8rpx;
	}
	.popover-arrow-topLeft,
	.popover-arrow-topRight,
	.popover-arrow-topCenter {
		bottom: 10rpx;
	}
	.popover-arrow-bottomLeft,
	.popover-arrow-bottomRight,
	.popover-arrow-bottomCenter {
		top: 10rpx;
	}
	.popover-arrow-icon { 
		position: absolute;
		top: 0;
		right: 0;
		bottom: 0;
		left: 0;
		display: block;
		height: 14rpx;
		width: 14rpx;
		margin: auto;
		background: #3B3B3C;
		content: "";
		pointer-events: auto;
	}
	.popover-arrow-icon-leftTop,
	.popover-arrow-icon-leftBottom,
	.popover-arrow-icon-leftCenter {
		transform: translateX(-10rpx) rotate(45deg);
	}
	.popover-arrow-icon-rightTop,
	.popover-arrow-icon-rightBottom,
	.popover-arrow-icon-rightCenter {
		transform: translateX(10rpx) rotate(45deg);
	}
	.popover-arrow-icon-topLeft,
	.popover-arrow-icon-topRight,
	.popover-arrow-icon-topCenter {
		transform: translateY(10rpx) rotate(45deg);
	}
	.popover-arrow-icon-bottomLeft,
	.popover-arrow-icon-bottomRight,
	.popover-arrow-icon-bottomCenter {
		transform: translateY(-10rpx) rotate(45deg);
	}
	.popover-content {
		position: fixed;
		transition: ease 100ms;
		opacity: 0;
		transform: scale(0.6);
		box-sizing: border-box;
		z-index: 99;
		display: flex;
	}
	.popover-content-leftTop {
		padding-right: 8rpx;
		transform-origin: 100% 0;
	}
	.popover-content-leftBottom {
		padding-right: 8rpx;
		transform-origin: 100% 100%;
	}
	.popover-content-leftCenter {
		padding-right: 8rpx;
		transform-origin: 100% 50%;
	}
	.popover-content-rightTop {
		padding-left: 8rpx;
		transform-origin: 0 0;
	}
	.popover-content-rightBottom {
		padding-left: 8rpx;
		transform-origin: 0 100%;
	}
	.popover-content-rightCenter {
		padding-left: 8rpx;
		transform-origin: 0 50%;
	}
	.popover-content-topLeft {
		padding-bottom: 8rpx;
		transform-origin: 0 100% ;
	}
	.popover-content-topRight {
		padding-bottom: 8rpx;
		transform-origin: 100% 100%;
	}
	.popover-content-topCenter {
		padding-bottom: 8rpx;
		transform-origin: 50% 100%;
	}
	.popover-content-bottomLeft {
		padding-top: 8rpx;
		transform-origin: 0 0;
	}
	.popover-content-bottomRight {
		padding-top: 8rpx;
		transform-origin: 100% 0;
	}
	.popover-content-bottomCenter {
		padding-top: 8rpx;
		transform-origin: 50% 0;
	}
	.popover-content-block {
		background: #3B3B3C;
		border-radius: 10rpx;
		flex-shrink: 0;
		max-width: 500rpx;
		min-width: 100rpx;
		min-height: 50rpx;
	}
</style>
