<template>
	<div class="w100p bd rds4 hidden">
		<div class="plr10 grayBg bb bT4 flex">
			<div class="flex lt">
				<el-checkbox @change="onCheckAll" v-model="checkAll" label="全选" size="large"></el-checkbox>
				<div class="ml5 gray">（已选{{modelValue.length}}项）</div>
			</div>

			<div class="flex rt">
				<el-checkbox v-model="expandAll" label="全部展开" size="large" @change="_onExpandAll"></el-checkbox>
				<el-checkbox v-if="isShowLinkAll" v-model="linkAll" label="联动选择" size="large"></el-checkbox>
			</div>
		</div>
		<el-tree-v2 v-show="!expandAll" ref="tree" :data="data" :props="propsSync" show-checkbox :height="300" :check-strictly="true" :default-expanded-keys="expandedKeys" @check="_onCheck"></el-tree-v2>
		<el-tree-v2 v-if="renderAllExpanded" v-show="expandAll" ref="expandedTree" :data="data" :props="propsSync" show-checkbox :height="300" :check-strictly="true" :default-expanded-keys="expandedKeys" @check="_onCheck"></el-tree-v2>
	</div>
</template>

<script>

	import {findParents} from "@/js_sdk/lib/findParents";

	export default {
		name: "st-tree-checkbox",
		emits:["update:modelValue"],
		props:{
			modelValue: {
				type: Array,
				default() {
					return [];
				}
			} ,
			data: {
				type: Array,
				default() {
					return [];
				}
			},
			props: {
				type: Object,
				default() {
					return {}
				}
			},
			checkStrictly : Boolean ,
			isShowLinkAll : {
				type : Boolean ,
				default : true
			},
			linkAllDefaultVal: {
				type: Boolean,
				default: false
			},
			expandAllDefaultVal: {
				type: Boolean,
				default: false
			}
		},
		watch:{
			modelValue:{
				handler() {
					!!this.$refs.tree && this.$refs.tree.setCheckedKeys(this.modelValue);
					// 全选反选功能
					this.checkAll = this.allKeys.length === this.modelValue.length;
				},
				immediate: true
			}
		},
		computed:{
			propsSync(){
				return Object.assign({
					value: "id",
					label: "label",
					children: "children",
					disabled: "disabled"
				} , this.props);
			},
			allKeys() {
				return this.getChildrenValue(this.data);
			}
		},
		data() {
			return {
				renderAllExpanded : false ,
				linkAll : this.linkAllDefaultVal ,
				expandAll : false ,
				checkAll : false ,
				expandedKeys : []
			}
		},
		async mounted() {
			await this.$nextTick();
			if(this.expandAllDefaultVal) {
				this.expandAll = true ;
				await this._onExpandAll(true);
			}
			this._setCheckedKeys(this.modelValue);
		},
		methods: {

			onCheckAll(value){
				let allCheckedKeys = value ? this.getChildrenValue(this.data) : [] ;
				this.setCheckedKeys(allCheckedKeys);
			},

			setCheckedKeys(allCheckedKeys){
				allCheckedKeys = Array.from(new Set(allCheckedKeys));
				this._setCheckedKeys(allCheckedKeys);
				this.$emit("update:modelValue" , [...allCheckedKeys]);
			},

			getChildrenValue(list){
				if(!list) return [] ;
				return list.reduce((ids,item)=>{
					ids.push(item[this.propsSync.value]);
					let childIds = this.getChildrenValue(item[this.propsSync.children]);
					ids.push(...childIds);
					return ids ;
				},[]);
			},

			_onCheck(data , info){
				let valueKey = this.propsSync.value ;
				let childrenKey = this.propsSync.children ;
				let value = data[valueKey] ;
				let {checkedKeys} = info ;
				let parentIds = findParents(this.data, value, valueKey , childrenKey).map(item => item.id);
				let childrenIds = this.getChildrenValue(data[childrenKey]);
				let allCheckedKeys = this._getAllCheckedKeys(checkedKeys,parentIds,childrenIds,value) ;
				// 父节点反选
				this.isRemoveParentNode(parentIds, allCheckedKeys);
				this.setCheckedKeys(allCheckedKeys);
			},

			_getAllCheckedKeys(checkedKeys,parentIds,childrenIds,value){
				if(this.checkStrictly) return checkedKeys ;
				let allCheckedKeys = [] ;
				if (checkedKeys.includes(value)){
					allCheckedKeys = this._getAllCheckedKeysOnChecked(parentIds,childrenIds,checkedKeys) ;
				} else {
					//取消选中当前元素时，下级所有子元素都取消勾选
					allCheckedKeys = checkedKeys.filter(key=>!childrenIds.includes(key));
				}
				return allCheckedKeys ;
			},

			_getAllCheckedKeysOnChecked(parentIds,childrenIds,checkedKeys){
				if(this.linkAll){
					return [...parentIds , ...childrenIds,...checkedKeys];
				}
				return [...parentIds ,...checkedKeys];
			},

			async _onExpandAll(expandAll) {
				this.expandedKeys = expandAll ? this.allKeys : [] ;
				this.renderAllExpanded = true ;
				await this.$nextTick();
				this._setCheckedKeys(this.modelValue);
			},

			_setCheckedKeys(checkedKeys){
				if(this.expandAll) {
					this.$refs.expandedTree.setCheckedKeys(checkedKeys);
				} else {
					this.$refs.tree.setCheckedKeys(checkedKeys);
				}
			},
			isRemoveParentNode(parentId, allCheckedKeys) {
				// 根节点或者多个父节点不处理
				if(parentId.length === 0 || parentId.length > 1) return false;

				const childIds = this.data.filter(item => (item.id == parentId[0])).map(item => {
					return this.getChildNodes(item[this.propsSync.children]);
				})
				// 选中节点是否有子节点
				let status = false;
				childIds[0].map(item => {
					if(allCheckedKeys.indexOf(item) > -1) {
						return status = true;
					};
				});
				// 删除父节点
				if(!status) {
					const index = allCheckedKeys.indexOf(parentId[0]);
					allCheckedKeys.splice(index, 1);
				}
			},
			getChildNodes(data) {
				if(!data) return [];
				return data.reduce((ids, cur) => {
					ids.push(cur.id);
					const childsIds = this.getChildNodes(cur[this.propsSync.children]);
					ids.push(...childsIds);
					return ids;
				}, [])
			}
		}
	}
</script>