<template>
	<!-- #ifndef APP-NVUE -->
	<view
	    class="uv-grid-item"
	    hover-class="uv-grid-item--hover-class"
	    :hover-stay-time="200"
	    @tap="clickHandler"
	    :class="classes"
	    :style="[itemStyle]"
	>
		<slot />
	</view>
	<!-- #endif -->
	<!-- #ifdef APP-NVUE -->
	<view
	    class="uv-grid-item"
	    :hover-stay-time="200"
	    @tap="clickHandler"
	    :class="classes"
	    :style="[itemStyle]"
	>
		<slot />
	</view>
	<!-- #endif -->
</template>

<script>
	import mpMixin from '../../libs/mixin/mpMixin.js'
	import mixin from '../../libs/mixin/mixin.js'
	import props from './props.js';
	/**
	 * gridItem 提示
	 * @description 宫格组件一般用于同时展示多个同类项目的场景，可以给宫格的项目设置徽标组件(badge)，或者图标等，也可以扩展为左右滑动的轮播形式。搭配uv-grid使用
	 * @tutorial https://www.uvui.cn/components/grid.html
	 * @property {String | Number}	name		宫格的name ( 默认 null )
	 * @property {String}			bgColor		宫格的背景颜色 （默认 'transparent' ）
	 * @property {Object}			customStyle	自定义样式，对象形式
	 * @event {Function} click 点击宫格触发
	 * @example <uv-grid-item></uv-grid-item>
	 */
	export default {
		name: "uv-grid-item",
		mixins: [mpMixin, mixin, props],
		emits: ['$uvGridItem','click'],
		data() {
			return {
				parentData: {
					col: 3, // 父组件划分的宫格数
					border: true, // 是否显示边框，根据父组件决定
				},
				// #ifdef APP-NVUE
				width: 0, // nvue下才这么计算，vue下放到computed中，否则会因为延时造成闪烁
				// #endif
				classes: [], // 类名集合，用于判断是否显示右边和下边框
			};
		},
		created() {
			// 父组件的实例
			this.updateParentData()
		},
		mounted() {
			this.init()
		},
		computed: {
			// #ifndef APP-NVUE
			// vue下放到computed中，否则会因为延时造成闪烁
			width() {
				return 100 / Number(this.parentData.col) + '%'
			},
			// #endif
			itemStyle() {
				const style = {
					background: this.bgColor,
					width: this.width
				}
				return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle))
			}
		},
		methods: {
			init() {
				// 用于在父组件uv-grid的children中被添加入子组件时，
				// 重新计算item的边框
				uni.$on('$uvGridItem', () => {
					this.gridItemClasses()
				})
				// #ifdef APP-NVUE
				// 获取元素该有的长度，nvue下要延时才准确
				this.$nextTick(function(){
					this.getItemWidth()
				})
				// #endif
				// 发出事件，通知所有的grid-item都重新计算自己的边框
				uni.$emit('$uvGridItem')
				this.gridItemClasses()
			},
			// 获取父组件的参数
			updateParentData() {
				// 此方法写在mixin中
				this.getParentData('uv-grid');
			},
			clickHandler() {
				let name = this.name
				// 如果没有设置name属性，历遍父组件的children数组，判断当前的元素是否和本实例this相等，找出当前组件的索引
				const children = this.parent?.children
				if(children && this.name === null) {
					name = children.findIndex(child => child === this)
				}
				// 调用父组件方法，发出事件
				this.parent && this.parent.childClick(name)
				this.$emit('click', name)
			},
			async getItemWidth() {
				// 如果是nvue，不能使用百分比，只能使用固定宽度
				let width = 0
				if(this.parent) {
					// 获取父组件宽度后，除以栅格数，得出每个item的宽度
					const parentWidth = await this.getParentWidth()
					width = parentWidth / Number(this.parentData.col) + 'px'
				}
				this.width = width
			},
			// 获取父元素的尺寸
			getParentWidth() {
				// #ifdef APP-NVUE
				// 返回一个promise，让调用者可以用await同步获取
				const dom = uni.requireNativePlugin('dom')
				return new Promise(resolve => {
					// 调用父组件的ref
					dom.getComponentRect(this.parent.$refs['uv-grid'], res => {
						resolve(res.size.width)
					})
				})
				// #endif
			},
			gridItemClasses() {
				if(this.parentData.border) {
					let classes = []
					this.parent.children.map((child, index) =>{
						if(this === child) {
							const len = this.parent.children.length
							// 贴近右边屏幕边沿的child，并且最后一个（比如只有横向2个的时候），无需右边框
							if((index + 1) % this.parentData.col !== 0 && index + 1 !== len) {
								classes.push('uv-border-right')
							}
							// 总的宫格数量对列数取余的值
							// 如果取余后，值为0，则意味着要将最后一排的宫格，都不需要下边框
							const lessNum = len % this.parentData.col === 0 ? this.parentData.col : len % this.parentData.col
							// 最下面的一排child，无需下边框
							if(index < len - lessNum) {
								classes.push('uv-border-bottom')
							}
						}
					})
					// 支付宝，头条小程序无法动态绑定一个数组类名，否则解析出来的结果会带有","，而导致失效
					// #ifdef MP-ALIPAY || MP-TOUTIAO
					classes = classes.join(' ')
					// #endif
					this.classes = classes
				}
			}
		},
		// #ifdef VUE2
		beforeDestroy() {
			// 移除事件监听，释放性能
			uni.$off('$uvGridItem')
		},
		// #endif
		// #ifdef VUE3
		unmounted() {
			// 移除事件监听，释放性能
			uni.$off('$uvGridItem')
		}
		// #endif
	};
</script>

<style lang="scss" scoped>
	$show-border: 1;
	$show-border-right: 1;
	$show-border-bottom: 1;
	@import '../../libs/css/variable.scss';
	@import '../../libs/css/components.scss';
	@import '../../libs/css/color.scss';
	$uv-grid-item-hover-class-opcatiy:.5 !default;
	$uv-grid-item-margin-top:1rpx !default;
	$uv-grid-item-border-right-width:0.5px !default;
	$uv-grid-item-border-bottom-width:0.5px !default;
	$uv-grid-item-border-right-color:$uv-border-color !default;
	$uv-grid-item-border-bottom-color:$uv-border-color !default;
	.uv-grid-item {
		align-items: center;
		justify-content: center;
		position: relative;
		flex-direction: column;
		/* #ifndef APP-NVUE */
		box-sizing: border-box;
		display: flex;
		/* #endif */

		/* #ifdef MP */
		position: relative;
		float: left;
		/* #endif */

		/* #ifdef MP-WEIXIN */
		margin-top:$uv-grid-item-margin-top;
		/* #endif */

		&--hover-class {
			opacity:$uv-grid-item-hover-class-opcatiy;
		}
	}

	/* #ifdef APP-NVUE */
	// 由于nvue不支持组件内引入app.vue中再引入的样式，所以需要写在这里
	.uv-border-right {
		border-right-width:$uv-grid-item-border-right-width;
		border-color: $uv-grid-item-border-right-color;
	}

	.uv-border-bottom {
		border-bottom-width:$uv-grid-item-border-bottom-width;
		border-color:$uv-grid-item-border-bottom-color;
	}
	/* #endif */
</style>
