<template>
	<view class="tui-cascade-selection">
		<scroll-view :scroll-x="true" scroll-with-animation :scroll-into-view="scrollViewId"
			:style="{ backgroundColor: headerBgColor }" class="tui-bottom-line"
			:class="{ 'tui-btm-none': !headerLine }">
			<view class="tui-selection-header" :style="{ height: tabsHeight, backgroundColor: backgroundColor }">
				<view class="tui-header-item" :class="{ 'tui-font-bold': idx === currentTab && bold }"
					:style="{ color: idx === currentTab ? getActiveColor : color, fontSize: size + 'rpx' }"
					:id="`id_${idx}`" @tap.stop="swichNav" :data-current="idx" v-for="(item, idx) in selectedArr"
					:key="idx">
					{{ item[textField] }}
					<view class="tui-active-line" :style="{ backgroundColor: getLineColor }"
						v-if="idx === currentTab && showLine"></view>
				</view>
			</view>
		</scroll-view>
		<swiper class="tui-selection-list" :current="defTab" duration="300" @change="switchTab"
			:style="{ height: height, backgroundColor: backgroundColor }">
			<swiper-item v-for="(item, index) in selectedArr" :key="index">
				<scroll-view scroll-y :scroll-into-view="item.scrollViewId" class="tui-selection-item"
					:style="{ height: height }">
					<view class="tui-first-item" :style="{ height: firstItemTop }"></view>
					<view class="tui-selection-cell" :style="{ padding: padding, backgroundColor: backgroundColor }"
						:id="`id_${subIndex}`" v-for="(subItem, subIndex) in item.list" :key="subIndex"
						@tap.stop="change(index, subIndex, subItem)">
						<icon type="success_no_circle" v-if="item.index === subIndex" :color="getCkMarkColor"
							:size="checkMarkSize" class="tui-icon-success"></icon>
						<image :src="subItem[srcField]" v-if="subItem[srcField]" class="tui-cell-img"
							:style="{ width: imgWidth, height: imgHeight, borderRadius: radius }"></image>
						<view class="tui-cell-title"
							:class="{ 'tui-font-bold': item.index === subIndex && textBold, 'tui-flex-shrink': nowrap }"
							:style="{ color: item.index === subIndex ? textActiveColor : textColor, fontSize: textSize + 'rpx' }">
							{{ subItem[textField] }}
						</view>
						<view class="tui-cell-sub_title" :style="{ color: subTextColor, fontSize: subTextSize + 'rpx' }"
							v-if="subItem[subTextField]">{{ subItem[subTextField] }}</view>
					</view>
				</scroll-view>
			</swiper-item>
		</swiper>
	</view>
</template>

<script>
	export default {
		name: 'tuiCascadeSelection',
		emits: ['change', 'complete'],
		props: {
			/**
			 * 如果下一级是请求返回，则为第一级数据，否则所有数据
			 * 数据格式
			 * */
			itemList: {
				type: Array,
				default: () => {
					return [];
				}
			},
			srcField: {
				type: String,
				default: 'src'
			},
			textField: {
				type: String,
				default: 'text'
			},
			subTextField: {
				type: String,
				default: 'subText'
			},
			valueField: {
				type: String,
				default: 'value'
			},
			childrenField: {
				type: String,
				default: 'children'
			},
			/*
			   初始化默认选中数据
			   [{
				text: "",//选中text
				subText: '',//选中subText
				value: '',//选中value
				src: '', //选中src，没有则传空或不传
				index: 0, //选中数据在当前layer索引
				list: [{src: "", text: "", subText: "", value: 101}] //当前layer下所有数据集合
			  }];
			    
			   */
			defaultItemList: {
				type: Array,
				default () {
					return []
				}
			},
			defaultKey: {
				type: String,
				default: 'text'
			},
			//是否显示header底部细线
			headerLine: {
				type: Boolean,
				default: true
			},
			//header背景颜色
			headerBgColor: {
				type: String,
				default: '#FFFFFF'
			},
			//顶部标签栏高度
			tabsHeight: {
				type: String,
				default: '88rpx'
			},
			//默认显示文字
			text: {
				type: String,
				default: '请选择'
			},
			//tabs 文字大小
			size: {
				type: Number,
				default: 28
			},
			//tabs 文字颜色
			color: {
				type: String,
				default: '#555'
			},
			//选中颜色
			activeColor: {
				type: String,
				default: ''
			},
			//选中后文字加粗
			bold: {
				type: Boolean,
				default: true
			},
			//选中后是否显示底部线条
			showLine: {
				type: Boolean,
				default: true
			},
			//线条颜色
			lineColor: {
				type: String,
				default: ''
			},
			//icon 大小
			checkMarkSize: {
				type: Number,
				default: 15
			},
			//icon 颜色
			checkMarkColor: {
				type: String,
				default: ''
			},
			//item 图片宽度
			imgWidth: {
				type: String,
				default: '40rpx'
			},
			//item 图片高度
			imgHeight: {
				type: String,
				default: '40rpx'
			},
			//图片圆角
			radius: {
				type: String,
				default: '50%'
			},
			//item text颜色
			textColor: {
				type: String,
				default: '#333'
			},
			textActiveColor: {
				type: String,
				default: '#333'
			},
			//选中后字体是否加粗
			textBold: {
				type: Boolean,
				default: true
			},
			//item text字体大小
			textSize: {
				type: Number,
				default: 28
			},
			//text 是否不换行
			nowrap: {
				type: Boolean,
				default: false
			},
			//item subText颜色
			subTextColor: {
				type: String,
				default: '#999'
			},
			//item subText字体大小
			subTextSize: {
				type: Number,
				default: 24
			},
			// item padding
			padding: {
				type: String,
				default: '20rpx 30rpx'
			},
			//占位高度，第一条数据距离顶部距离
			firstItemTop: {
				type: String,
				default: '20rpx'
			},
			//swiper 高度
			height: {
				type: String,
				default: '300px'
			},
			//item  swiper 内容部分背景颜色
			backgroundColor: {
				type: String,
				default: '#FFFFFF'
			},
			//子集数据是否请求返回（默认false，一次性返回所有数据）
			request: {
				type: Boolean,
				default: false
			},
			//子级数据（当有改变时，默认当前选中项新增子级数据，request=true时生效）
			receiveData: {
				type: Array,
				default: () => {
					return [];
				}
			},
			//改变值则重置数据
			reset: {
				type: [Number, String],
				default: 0
			}
		},
		computed: {
			getActiveColor() {
				return this.activeColor || (uni && uni.$tui && uni.$tui.color.primary) || '#5677fc';
			},
			getLineColor() {
				return this.lineColor || (uni && uni.$tui && uni.$tui.color.primary) || '#5677fc';
			},
			getCkMarkColor() {
				return this.checkMarkColor || (uni && uni.$tui && uni.$tui.color.primary) || '#5677fc';
			}
		},
		watch: {
			itemList(val) {
				this.initData(val, -1);
			},
			receiveData(val) {
				this.subLevelData(val, this.currentTab);
			},
			reset() {
				this.initData(this.itemList, -1);
			},
			defaultItemList(val) {
				this.setDefaultData(val)
			}
		},
		created() {
			this.setDefaultData(this.defaultItemList)
		},
		data() {
			return {
				currentTab: 0,
				defTab: 0,
				//tab栏scrollview滚动的位置
				scrollViewId: 'id__1',
				selectedArr: []
			};
		},
		methods: {
			setDefaultData(val) {
				let defaultItemList = JSON.parse(JSON.stringify(val || []));
				if (defaultItemList.length > 0) {
					if ((typeof defaultItemList[0] === 'string' || typeof defaultItemList[0] === 'number') && !this
						.request) {
						let subi = -1
						let selectedArr = []
						for (let j = 0, len = defaultItemList.length; j < len; j++) {
							let item = defaultItemList[j]
							let list = []
							let obj = {}
							if (j === 0) {
								list = this.getItemList(-1)
							} else {
								list = this.getItemList(j - 1, subi, selectedArr)
							}
							subi = this.getDefaultIndex(list, item)
							if (subi !== -1) {
								obj = list[subi]
								selectedArr.push({
									[this.textField]: obj[this.textField] || this.text,
									[this.valueField]: obj[this.valueField] || '',
									[this.srcField]: obj[this.srcField] || '',
									[this.subTextField]: obj[this.subTextField] || '',
									index: subi,
									scrollViewId: `id_${subi}`,
									list: list
								})
							}

							if (subi === -1) break;
						}
						this.selectedArr = selectedArr;
						this.defTab = this.currentTab;
						this.$nextTick(() => {
							setTimeout(() => {
								this.currentTab = selectedArr.length - 1;
								this.defTab = this.currentTab;
								this.checkCor();
							}, 20)
						});
					} else {
						defaultItemList.map(item => {
							item.scrollViewId = `id_${item.index}`;
						});
						this.selectedArr = defaultItemList;
						this.defTab = this.currentTab;
						this.$nextTick(() => {
							setTimeout(() => {
								this.currentTab = defaultItemList.length - 1;
								this.defTab = this.currentTab;
								this.checkCor();
							}, 20)
						});
					}

				} else {
					this.initData(this.itemList, -1);
				}
			},
			getDefaultIndex(arr, val) {
				if (!arr || arr.length === 0 || val === undefined) return -1;
				let index = -1;
				let key = this.defaultKey || 'text'
				for (let i = 0, len = arr.length; i < len; i++) {
					if (arr[i][key] == val) {
						index = i;
						break;
					}
				}
				return index;
			},
			initData(data, layer) {
				if (!data || data.length === 0) return;
				if (this.request) {
					//第一级数据
					this.subLevelData(data, layer);
				} else {
					let selectedValue = this.selectedValue || {};
					if (selectedValue.type) {
						this.setDefaultData(selectedValue);
					} else {
						this.subLevelData(this.getItemList(layer, -1), layer);
					}
				}
			},
			removeChildren(data) {
				let list = data.map(item => {
					delete item[this.childrenField];
					return item;
				});
				return list;
			},
			getItemList(layer, index, selectedArr) {
				let list = [];
				let arr = JSON.parse(JSON.stringify(this.itemList));
				selectedArr = selectedArr || this.selectedArr
				if (layer == -1) {
					list = this.removeChildren(arr);
				} else {
					let value = selectedArr[0].index;
					value = value === undefined || value == -1 ? index : value;
					if (arr[value] && arr[value][this.childrenField]) {
						list = arr[value][this.childrenField];
					}
					if (layer > 0) {
						for (let i = 1; i < layer + 1; i++) {
							let val = layer === i ? index : selectedArr[i].index;
							list = val === -1 ? [] : (list[val][this.childrenField] || []);
							if (list.length === 0) break;
						}
					}
					list = this.removeChildren(list);
				}
				return list;
			},
			//滚动切换
			switchTab: function(e) {
				this.currentTab = e.detail.current;
				this.checkCor();
			},
			//点击标题切换当
			swichNav: function(e) {
				let cur = e.currentTarget.dataset.current;
				if (this.currentTab != cur) {
					this.defTab = this.currentTab;
					setTimeout(() => {
						this.currentTab = cur;
						this.defTab = this.currentTab;
					}, 20)
				}
			},
			checkCor: function() {
				let item = this.selectedArr[this.currentTab];
				item.scrollViewId = 'id__1';
				this.$nextTick(() => {
					setTimeout(() => {
						let val = item.index < 2 ? 0 : Number(item.index - 2);
						item.scrollViewId = `id_${val}`;
					}, 20);
				});

				if (this.currentTab > 1) {
					this.scrollViewId = `id_${this.currentTab - 1}`;
				} else {
					this.scrollViewId = `id_0`;
				}
			},
			change(index, subIndex, subItem) {
				let item = this.selectedArr[index];
				if (item.index == subIndex) return;
				item.index = subIndex;
				item[this.textField] = subItem[this.textField]
				item[this.valueField] = subItem[this.valueField];
				item[this.subTextField] = subItem[this.subTextField] || '';
				item[this.srcField] = subItem[this.srcField] || '';
				this.$emit('change', {
					layer: index,
					subIndex: subIndex, //layer=> Array index
					...subItem
				});

				if (!this.request) {
					let data = this.getItemList(index, subIndex);
					this.subLevelData(data, index);
				}
			},
			//新增子级数据时处理
			subLevelData(data, layer) {
				if (!data || data.length === 0) {
					if (layer == -1) return;
					//完成选择
					let arr = this.selectedArr;
					if (layer < arr.length - 1) {
						let newArr = arr.slice(0, layer + 1);
						this.selectedArr = newArr;
					}
					let result = JSON.parse(JSON.stringify(this.selectedArr));
					let lastItem = result[result.length - 1] || {};
					let text = '';
					result.map(item => {
						text += item[this.textField];
						delete item['list'];
						//delete item['index'];
						delete item['scrollViewId'];
						return item;
					});
					this.$emit('complete', {
						result: result,
						[this.valueField]: lastItem[this.valueField],
						[this.textField]: text,
						[this.subTextField]: lastItem[this.subTextField],
						[this.srcField]: lastItem[this.srcField]
					});
				} else {
					//重置数据（ >layer层级）
					let item = [{
						[this.textField]: this.text,
						[this.subTextField]: '',
						[this.valueField]: '',
						[this.srcField]: '',
						index: -1,
						scrollViewId: 'id__1',
						list: data
					}];
					if (layer == -1) {
						this.selectedArr = item;
					} else {
						let retainArr = this.selectedArr.slice(0, layer + 1) || [];
						this.selectedArr = retainArr.concat(item);
					}

					let current = this.selectedArr.length - 1;
					if (current >= this.currentTab) {
						this.defTab = this.currentTab
					}
					this.$nextTick(() => {
						setTimeout(() => {
							this.defTab = current;
							this.currentTab = current;
							this.scrollViewId = `id_${this.currentTab > 1?this.currentTab - 1:0}`;
						}, 50)

					});
				}
			}
		}
	};
</script>

<style scoped>
	.tui-cascade-selection {
		width: 100%;
		box-sizing: border-box;
	}

	.tui-selection-header {
		width: 100%;
		display: flex;
		align-items: center;
		position: relative;
		box-sizing: border-box;
	}

	.tui-bottom-line {
		position: relative;
	}

	.tui-bottom-line::after {
		width: 100%;
		content: '';
		position: absolute;
		border-bottom: 1rpx solid #eaeef1;
		-webkit-transform: scaleY(0.5) translateZ(0);
		transform: scaleY(0.5) translateZ(0);
		transform-origin: 0 100%;
		bottom: 0;
		right: 0;
		left: 0;
		z-index: 1;
		pointer-events: none;
	}

	.tui-btm-none::after {
		border-bottom: 0 !important;
	}

	.tui-header-item {
		max-width: 240rpx;
		padding: 15rpx 30rpx;
		box-sizing: border-box;
		flex-shrink: 0;
		overflow: hidden;
		white-space: nowrap;
		text-overflow: ellipsis;
		position: relative;
	}

	.tui-font-bold {
		font-weight: bold;
	}

	.tui-active-line {
		width: 60rpx;
		height: 6rpx;
		border-radius: 4rpx;
		position: absolute;
		bottom: 0;
		right: 0;
		left: 50%;
		transform: translateX(-50%);
	}

	.tui-selection-cell {
		width: 100%;
		box-sizing: border-box;
		display: flex;
		align-items: center;
	}

	.tui-icon-success {
		margin-right: 12rpx;
	}

	.tui-cell-img {
		margin-right: 12rpx;
		flex-shrink: 0;
	}

	.tui-cell-title {
		word-break: break-all;
	}

	.tui-flex-shrink {
		flex-shrink: 0;
	}

	.tui-font-bold {
		font-weight: bold;
	}

	.tui-cell-sub_title {
		margin-left: 20rpx;
		word-break: break-all;
	}

	.tui-first-item {
		width: 100%;
	}
</style>