<template>
	<view class="QS-tabs" :style="{
		'z-index': zIndex,
		'font-size': getFontSize + 'rpx',
		'background-color': getBgColor,
		'transition-duration': getDuration + 's'
		}">
		<scroll-view show-scrollbar="false" scroll-x class="QS-tabs-scroll" :scroll-left="left" scroll-with-animation :style="{ 
			'z-index': (Number(zIndex) + 1)
		}">
			<view class="QS-tabs-scroll-item " :style="{
				'height': getHeight + 'rpx', 
				'line-height': getHeight + 'rpx',
				'width': getWidth + 'rpx',
				'color': index===getCurrent?getActiveColor:getDefaultColor,
				'transition-duration': getDuration + 's',
				'z-index': (Number(zIndex) + 2)
			}"
			 v-for="(item, index) in getTabs" :key="index" @tap="emit(index)">
				<!-- line1 -->
				<view v-if="animationMode==='line1'" class="boxStyle" :style="getDurationStyle +( index===getCurrent?getActiveStyle:getDefaultStyle)"></view>
				{{item.name || item}}
			</view>
			<!-- itemBackground -->
			<view v-if="hasItemBackground" class="itemBackgroundBox" :style="getItemBackgroundBoxStyle">
				<view class="itemBackground" :style="getItemBackgroundStyle" />
			</view>
			<!-- line2 -->
			<view v-if="animationMode==='line2'" class="boxStyle2" :style="getLinezIndex + getDurationStyle + getBoxStyle2" />
			<view v-if="animationMode==='line3'" class="boxStyle2" :style="getLinezIndex + getBoxStyle3" />
		</scroll-view>
	</view>
</template>

<script>
	const {
		windowWidth
	} = uni.getSystemInfoSync();
	export default {
		props: {
			tabs: { //需循环的标签列表
				type: Array,
				default () {
					return [];
				}
			},
			current: { //当前所在滑块的 index
				type: Number,
				default: 0
			},
			height: { //QS-tabs的高度和行高
				type: [String, Number],
				default: 80
			},
			width: { //单个tab的宽度
				type: [String, Number],
				default: 250
			},
			fontSize: { //字体大小
				type: [String, Number],
				default: 30
			},
			duration: { //过渡动画时长, 单位 s
				type: [String, Number],
				default: .5
			},
			activeColor: { //选中项的主题颜色
				type: String,
				default: '#33cc33'
			},
			defaultColor: { //未选中项的主题颜色
				type: String,
				default: '#888'
			},
			animationLineWidth: { //动画线条的宽度
				type: [String, Number],
				default: 40
			},
			line2Style: { //line2线条的样式
				type: String,
				default: 'height: 3rpx;border-radius: 4rpx;'
			},
			animationMode: { //动画类型
				type: String,
				default: 'line1'
			},
			autoCenter: { //是否自动滚动至中心目标
				type: Boolean,
				default: true
			},
			autoCenterMode: { //滚动至中心目标类型
				type: String,
				default: 'component'
			},
			activeStyle: { //line1模式选中项的样式
				type: String,
				default: 'bottom:0;left:50%;margin-left: -20%;height: 5rpx;border-radius:4rpx;'
			},
			defaultStyle: { //line1模式未选中项的样式
				type: String,
				default: 'bottom:0;left:50%;margin-left: -20%;height: 4rpx;border-radius:4rpx;'
			},
			backgroundColor: { //统一背景颜色
				type: String,
				default: 'rgba(255,255,255,0)'
			},
			hasItemBackground: { //是否开启背景追光
				type: Boolean,
				default: false
			},
			itemBackgroundColor: { //统一追光背景颜色
				type: String,
				default: 'rgba(255,255,255,0)'
			},
			itemBackgroundStyle: { //追光样式
				type: String,
				default: ''
			},
			zIndex: { //css的z-index属性值
				type: [String, Number],
				default: 99
			},
			swiperWidth: {
				type: [String, Number],
				default: 750
			}
		},
		computed: {
			getCurrent() {
				if (this.current > (this.getTabs.length - 1)) {
					return (this.getTabs.length - 1)
				}
				return this.current;
			},
			getTabs() {
				return this.tabs;
			},
			getHeight() {
				return this.height;
			},
			getWidth() {
				return Number(this.width);
			},
			getFontSize() {
				return this.fontSize;
			},
			getDuration() {
				return this.duration;
			},
			getBgColor() {
				const defaultColor = this.backgroundColor || 'rgba(255,255,255,0)';
				if (this.getTabs[this.getCurrent] instanceof Object) {
					return this.getTabs[this.getCurrent].backgroundColor || defaultColor;
				} else {
					return defaultColor;
				}
			},
			getItemBackgroundColor() {
				const defaultColor = this.itemBackgroundColor || 'rgba(255,255,255,0)';
				if (this.getTabs[this.getCurrent] instanceof Object) {
					return this.getTabs[this.getCurrent].itemBackgroundColor || defaultColor;
				} else {
					return defaultColor;
				}
			},
			getDurationStyle() {
				return `transition-duration: ${this.getDuration}s;`
			},
			getActiveColor() {
				let activeColor;
				if (this.getTabs[this.getCurrent] instanceof Object) {
					if (this.getTabs[this.getCurrent].activeColor) {
						activeColor = this.getTabs[this.getCurrent].activeColor;
					} else {
						activeColor = this.activeColor;
					}
				} else {
					activeColor = this.activeColor;
				}
				return activeColor;
			},
			getDefaultColor() {
				let defaultColor;
				if (this.getTabs[this.getCurrent] instanceof Object) {
					if (this.getTabs[this.getCurrent].defaultColor) {
						defaultColor = this.getTabs[this.getCurrent].defaultColor;
					} else {
						defaultColor = this.defaultColor;
					}
				} else {
					defaultColor = this.defaultColor;
				}
				return defaultColor;
			},
			getActiveStyle() {
				return `width:${this.animationLineWidth}%;background-color:${this.getActiveColor};${this.activeStyle}`;
			},
			getDefaultStyle() {
				return `width:0;background-color:${this.getActiveColor};${this.defaultStyle}`;
			},
			getLinezIndexNum() {
				return Number(this.zIndex) + 2;
			},
			getLinezIndex() {
				return `z-index: ${this.getLinezIndexNum};`;
			},
			getLw() {
				const lineWidth = Number(this.line2Width);
				const lw = Number(this.width) * (lineWidth / 100);
				return lw;
			},
			getBoxStyle2() {
				const lw = this.getLw;
				const x = Number(this.width) * (this.getCurrent + 1) - Number(this.width) / 2 - lw / 2;
				return `transform:translate(${x}rpx, -100%);width:${this.getLw}rpx;background-color: ${this.getActiveColor};${this.line2Style}`;
			},
			getItemBackgroundBoxStyle() {
				return `height: ${this.getHeight}rpx;
						width: ${this.getWidth}rpx;
						z-index: ${(Number(this.zIndex) + 1)};
						transition-duration: ${this.getDuration}s;
						transform: translateX(${Number(this.width)*(this.getCurrent)}rpx);`
			},
			getItemBackgroundStyle() {
				return `transition-duration: ${this.getDuration}s;
						background-color: ${this.getItemBackgroundColor};
						box-shadow: 0 0 5rpx 5rpx ${this.getItemBackgroundColor};
						${this.itemBackgroundStyle};`
			},
			getFinishDx() {
				const lw = this.getLw;
				const d = Number(this.animationFinishCurrent);
				const animationFinishCurrent = d + 1;
				const a = Number(this.width) * animationFinishCurrent;
				const b = Number(this.width) / 2;
				const c = lw / 2;
				const x = a - b - c;
				return x;
			},
			getDxNum() {
				const sw = Number(this.swiperWidth) / 750 * windowWidth;
				const b = this.dx / sw;
				const c = Number(this.width);
				const a = b * c;
				return a;
			},
			getBoxStyle3() {
				const x = this.getFinishDx + this.getDxNum;
				return `transform:translate(${x}rpx, -100%);width:${this.getLw}rpx;background-color: ${this.getActiveColor};${this.line2Style}`;
			}
		},
		watch: {
			current(n, o) {
				this.change(n);
			}
		},
		data() {
			return {
				left: 0,
				line2Width: Number(this.animationLineWidth),
				setTimeoutFc: null,
				componentsWidth: 0,
				animationFinishCurrent: this.current,
				dx: 0
			}
		},
		// #ifndef H5
		onReady() {
			this.getQuery(() => {
				this.countScrollX();
			});
		},
		// #endif
		// #ifdef H5
		mounted() {
			this.getQuery(() => {
				this.countScrollX();
			});
		},
		// #endif
		methods: {
			emit(index) {
				this.$emit('change', index);
			},
			change() {
				this.countScrollX();
				if (this.animationMode === 'line2') {
					this.line2Width = 2;
					if (this.setTimeoutFc) clearTimeout(this.setTimeoutFc);
					this.setTimeoutFc = setTimeout(() => {
						this.line2Width = this.animationLineWidth;
					}, this.getDuration * 1000 * 3 / 5);
				}
			},
			getQuery(cb) {
				try {
					let view = uni.createSelectorQuery().in(this).select('.QS-tabs');
					view.fields({
						size: true
					}, data => {
						if (data) {
							this.componentsWidth = data.width;
							if (cb && typeof cb === 'function') cb(data);
						} else {
							this.retryGetQuery(cb);
						}
					}).exec();
				} catch (e) {
					//TODO handle the exception
					this.componentsWidth = windowWidth;
				}
			},
			retryGetQuery() {
				try {
					let view = uni.createSelectorQuery().select('.QS-tabs');
					view.fields({
						size: true
					}, data => {
						if (data) {
							this.componentsWidth = data.width;
						} else {
							this.componentsWidth = windowWidth;
						}
						if (cb && typeof cb === 'function') cb(data);
					}).exec();
				} catch (e) {
					//TODO handle the exception
					this.componentsWidth = windowWidth;
				}
			},
			countScrollX() {
				if (this.autoCenter) {
					const width = Number(this.width);
					const itemWidth = width / 750 * windowWidth;
					let left = itemWidth * (this.getCurrent + 1) - itemWidth / 2;
					let fatherWidth;
					if (this.autoCenterMode === 'window') {
						fatherWidth = windowWidth;
					} else {
						fatherWidth = this.componentsWidth;
					}
					this.left = left - fatherWidth / 2;
				}
			},
			setDx(dx) {
				this.dx = dx;
			},
			setFinishCurrent(current) {
				this.dx = 0;
				this.animationFinishCurrent = current;
			}
		}
	}
</script>

<style scoped>
	view,
	scroll-view {
		box-sizing: border-box;
	}

	.QS-tabs {
		width: 100%;
		transition-property: background-color, color;
	}

	.QS-tabs-scroll {
		width: 100%;
		white-space: nowrap;
		position: relative;
	}

	.QS-tabs-scroll-item {
		position: relative;
		display: inline-block;
		text-align: center;
		transition-property: background-color, color;
		padding: 0 20rpx;
	}

	.content {
		overflow: hidden;
		white-space: nowrap;
		text-overflow: ellipsis;
	}

	.boxStyle {
		pointer-events: none;
		position: absolute;
		transition-property: all;
	}

	.boxStyle2 {
		pointer-events: none;
		position: absolute;
		bottom: 0;
		left: 0;
		transition-property: all;
	}

	.itemBackgroundBox {
		pointer-events: none;
		position: absolute;
		top: 0;
		left: 0;
		transition-property: transform, background-color;
		display: flex;
		flex-direction: row;
		justify-content: center;
		align-items: center;
	}

	.itemBackground {
		height: 100%;
		width: 100%;
		transition-property: all;
	}
</style>
