<template>
	<view class="el-sticky" :id="elId" :style="[style]">
		<view :style="[stickyContent]">
			<slot />
		</view>
	</view>
</template>

<script setup>
	import { computed,watch,ref,onMounted,nextTick,getCurrentInstance } from "vue";
	import { browser } from "../../libs/check.js";
	import { getSystemInfo,guid,deepMerge,px2rpx,unit } from "../../libs/utils.js";
	import { getClientRect,addStyle } from "../../libs/style.js";
	
	const props = defineProps({
		// 吸顶容器到顶部某个距离的时候，进行吸顶，在H5平台，NavigationBar为44px
		offsetTop: {
		    type: [String, Number],
		    default: 0
		},
		// 自定义导航栏的高度
		customNavHeight: {
		    type: [String, Number],
		    // #ifdef H5
		    // H5端的导航栏属于“自定义”导航栏的范畴，因为它是非原生的，与普通元素一致
		    default: 44,
		    // #endif
		    // #ifndef H5
		    default: 0
		    // #endif
		},
		// 是否开启吸顶功能
		disabled: {
		    type: Boolean,
		    default: false
		},
		// 吸顶区域的背景颜色
		bgColor: {
		    type: String,
		    default: 'transparent'
		},
		// z-index值
		zIndex: {
		    type: [String, Number],
		    default: ''
		},
		// 列表中的索引值
		index: {
		    type: [String, Number],
		    default: ''
		},
		customStyle: {
			type: [String,Object],
			default: {}
		}
	});
	
	let contentObserver = ref(null);
	let cssSticky 		= ref(false); 		// 是否使用css的sticky实现
	let stickyTop 		= ref(0); 			// 吸顶的top值，因为可能受自定义导航栏影响，最终的吸顶值非offsetTop值
	let elId      		= ref(guid());
	let left      		= ref(0); 			// js模式时，吸顶的内容因为处于postition: fixed模式，为了和原来保持一致的样式，需要记录并重新设置它的left，height，width属性
	let width     		= ref('auto');
	let height    		= ref('auto');
	let fixed     		= ref(false); 		// js模式时，是否处于吸顶模式
	
	const style = computed(()=>{
		const style = {};
		if(!props.disabled) {
			if (cssSticky.value) {
				style.position  = 'sticky';
				style.zIndex 	= EZindex.value;
				style.top 		= unit(stickyTop.value,'px');
			} else {
				style.height = fixed.value ? unit(height.value,'px') : 'auto';
			}
		} else {
			style.position = 'static';
		}
		
		style.backgroundColor = props.bgColor;
		return deepMerge(addStyle(props.customStyle), style);
	});
	
	const stickyContent = computed(()=>{
		const style = {};
		if (!cssSticky.value) {
			style.position 	= fixed.value ? 'fixed' : 'static';
			style.top 		= unit(stickyTop.value,'px');
			style.left 		= unit(left.value,'px');
			style.width 	= unit(width.value,'px');
			style.zIndex 	= EZindex.value;
		}
		
		return style;
	});
	
	const EZindex = computed(()=>{
		return props.zIndex ? props.zIndex : 9999999;
	})
	
	const getStickyTop = ()=>{
		stickyTop.value = px2rpx(props.offsetTop) + px2rpx(props.customNavHeight);
	}
	
	const checkSupportCssSticky = async()=>{
		// #ifdef H5
		// H5，一般都是现代浏览器，是支持css sticky的，这里使用创建元素嗅探的形式判断
		if (checkCssStickyForH5()) {
			cssSticky.value = true;
		}
		// #endif
		
		// #ifdef APP-PLUS
		cssSticky.value = true;
		// #endif
		
		// #ifdef APP-VUE || MP-WEIXIN
		cssSticky.value = await checkComputedStyle();
		// #endif
	}
	
	let instance = getCurrentInstance();
	const checkComputedStyle = ()=>{
		return new Promise(resolve => {
			uni.createSelectorQuery().in(instance).select('.el-sticky').fields({
				computedStyle: ["position"]
			}).exec(e => {
				resolve('sticky' === e[0].position);
			});
		})
	}
	
	const checkCssStickyForH5 = ()=>{
		let vendorList 			= ['', '-webkit-', '-ms-', '-moz-', '-o-'];
		let vendorListLength  	= vendorList.length;
		let stickyElement 		= document.createElement('div');
		let flag 				= false;
		for(let i = 0; i < vendorListLength; i++){
			stickyElement.style.position = vendorList[i] + 'sticky'
			if(stickyElement.style.position != ''){
				flag = true;
				break;
			}
		}
		
		return flag;
	}
	
	const init = ()=>{
		getStickyTop();
		checkSupportCssSticky();
	}
	init();
	
</script>

<style lang="scss" scoped>
	.el-sticky {
		position: sticky;
	}
</style>