<template>
	<div class="layers-check">
		<el-checkbox
			class="check-page-all"
			v-model="checkPageAll"
			@change="checkPageAllEv($event)"
		></el-checkbox>
		<el-table
			v-model="value"
			:data="tableData"
			:default-expand-all="true"
			@change="onChange"
			border
			ref="Table"
			:tree-props="{ children: 'children' }"
			row-key="id"
			@cell-click="cellClick"
		>
			<el-table-column type="selection" width="55">
				<template #default="scope">
					<el-checkbox
						v-model="scope.row.pageCheck"
						@change="pageCheckEv(scope)"
					></el-checkbox>
				</template>
			</el-table-column>
			<!-- <el-table-column prop="parentId" label="parentId" v-if="false"></el-table-column> -->
			<el-table-column
				v-for="(item, index) in tableColumn"
				:key="index"
				:prop="item.prop"
				:label="item.label"
				:width="item.width"
			>
				<template #default="scope">
					<div v-if="item.prop == 'opacity'">
						<el-input
							v-if="item.edit"
							size="small"
							ref="tableInput"
							v-model="scope.row[item.prop]"
							@blur="removeClass"
							placeholder="输入0到1直接的数字"
						></el-input>
					</div>
					<div v-if="item.prop == 'isInit'">
						<el-switch
							v-if="item.edit"
							v-model="scope.row[item.prop]"
							inline-prompt
							active-value="1"
							inactive-value="0"
							@click="changeStatus"
						></el-switch>
					</div>
					<div v-if="item.prop == 'isHide'">
						<el-switch
							v-if="item.edit"
							v-model="scope.row[item.prop]"
							inline-prompt
							active-value="1"
							inactive-value="0"
							@click="changeStatus"
						></el-switch>
					</div>
					<div v-if="item.prop == 'isExpand'">
						<el-switch
							v-if="item.edit"
							v-model="scope.row[item.prop]"
							inline-prompt
							active-value="1"
							inactive-value="0"
							@click="changeStatus"
						></el-switch>
					</div>
					<div v-if="item.prop == 'isHideChild'">
						<div v-if="scope.row['children'] != null">
							<el-switch
								v-if="item.edit"
								v-model="scope.row[item.prop]"
								inline-prompt
								active-value="1"
								inactive-value="0"
								@click="changeStatusAndChild(scope.row)"
							></el-switch>
						</div>
					</div>
					<div v-if="item.prop == 'isCheck'">
						<!-- <el-switch
							v-if="item.edit"
							v-model="scope.row[item.prop]"
							inline-prompt
							active-value="1"
							inactive-value="0"
							@click="changeStatus"
						></el-switch> -->
						<el-radio-group
							v-if="item.edit"
							v-model="scope.row[item.prop]"
							@click="changeStatus"
						>
							<el-radio :label="3">无</el-radio>
							<el-radio :label="6">单选框</el-radio>
							<el-radio :label="9">复选框</el-radio>
						</el-radio-group>
					</div>
				</template>
			</el-table-column>
		</el-table>
	</div>
</template>

<script lang="ts" name="layers-select" setup>
import { useForm } from "@cool-vue/crud";
import { cloneDeep } from "lodash-es";
import { computed, onMounted, ref, watch } from "vue";
import { useCool } from "/@/cool";
import { deepTree } from "/@/cool/utils";
import { useUpsert } from "@cool-vue/crud";

const props = defineProps({
	modelValue: {
		type: Array,
		default: () => []
	}
});

const tableColumn = [
	{ label: "图层描述", prop: "layerName", width: 140 },
	{ label: "是否隐藏本节点", prop: "isHide", edit: true, width: 102 },
	{ label: "是否隐藏子节点", prop: "isHideChild", edit: true, width: 102 },
	{ label: "是否默认展开", prop: "isExpand", edit: true, width: 102 },
	{ label: "是否进行框选", prop: "isCheck", edit: true, width: 152 },
	{ label: "是否默认加载", prop: "isInit", edit: true, width: 102 },
	{ label: "透明度", prop: "opacity", edit: true, width: 148 }
];

const emit = defineEmits(["update:modelValue"]);

// 请求服务
const { service } = useCool();

const Form = useForm();

// 绑定值
const value = ref();

// 菜单列表
const list = ref<any[]>([]);

const Table = ref();

//全选状态
const checkPageAll = ref<boolean>(false);

const selectionAllData = ref<any[]>([]);

// 树形表格
const tableData = computed(() => {
	return deepTree(
		// cloneDeep(list.value).filter((e) => (props.type === 0 ? e.type == 0 : props.type > e.type))
		cloneDeep(list.value)
	);
	// return list.value;
});

// 数据初始化 绑定 pageCheck 属性
function initData() {
	let bindCheck = (data: any) => {
		data.forEach((item: any) => {
			item.pageCheck = false;
			item.isCheck = "3";
			if (item.children && item.children.length) {
				bindCheck(item.children);
			}
			return item;
		});
	};
	bindCheck(tableData.value);
	console.log(tableData.value);
}

// 点击全选
function checkPageAllEv(state: any) {
	let checkAll = (data: any, checked: any) => {
		for (let item of data) {
			item.pageCheck = checked;
			if (item.children && item.children.length) {
				checkAll(item.children, checked);
			}
		}
	};
	checkAll(tableData.value, state);
	selectionAllData.value = [];
	mapChecked(tableData.value);
}
// 行点击
function pageCheckEv(scope: any) {
	// 如果是勾选  则 自身 以及 所有子集都需要选中  所有父集也都需要选中
	// 如果是勾销  则 自身 以及 所有子集都需要取消  所有父级则需要逐级判断其子集是否有勾选的子集
	// 此外 无论是勾选还是勾销  都需要判断对全选状态的影响

	// 处理自身以及子集选中状态
	handleCheckAll(scope.row, scope.row.pageCheck);
	// 处理父级
	if (scope.row.parentId) {
		let parents = getParent(tableData.value, scope.row.parentId);
		if (scope.row.pageCheck) {
			// 如果是勾选 所有父集都需要选中
			parents.forEach((item) => {
				item.pageCheck = true;
			});
		} else {
			// 如果是勾销 所有父级则需要逐级判断其子集是否有勾选的子集
			// 因为 parents 是逐级递归获取的  所以循环父集合也是逐级处理
			// 只有当上级父元素处理完成 才能处理上上一级元素
			// 因为上上一级元素的处理是根据其子集情况 即包含了上级父元素的处理状态
			// 万幸的是 object 是复杂数据类型  当你改变了上级父元素的处理状态 那么上上一级元素中的其处理状态也会变化
			parents.forEach((item) => {
				let isCheck = item.children.some((child: any) => child.pageCheck);
				item.pageCheck = isCheck;
			});
		}
	}
	// 处理对全选状态的影响
	checkPageAll.value = isCheckAllEv(tableData.value);

	selectionAllData.value = [];
	mapChecked(tableData.value);
}
// 获取选中的数据  使用该方法前需要将 selectionAllData 原有数据清空
function mapChecked(rows: any) {
	for (let item of rows) {
		if (item.pageCheck) {
			selectionAllData.value.push(item);
			if (item.children && item.children.length) {
				mapChecked(item.children);
			}
		}
	}
}
// 处理自身以及子集选中状态
function handleCheckAll(row: any, checked: any) {
	row.pageCheck = checked;
	if (row.children && row.children.length) {
		row.children.forEach((item: any) => {
			handleCheckAll(item, checked);
		});
	}
}
// 判断数据是否全部选中
function isCheckAllEv(data: any) {
	let isCheckAll = true;
	let fn = (arr: any) => {
		for (let item of arr) {
			if (!item.pageCheck) {
				isCheckAll = false;
				break;
			}
			if (item.children && item.children.length) {
				fn(item.children);
			}
		}
	};
	fn(data);
	return isCheckAll;
}
// 逐级获取父级  父级集合
function getParent(data: any, parentId: any) {
	const parents = ref<any[]>([]);
	let fn = (arr: any, parentId: any) => {
		for (let item of arr) {
			if (item.id == parentId) {
				parents.value.push(item);
				if (item.parentId) {
					// 注意 此处用的 data 即还是得从原来得查找范围重新开始查找
					fn(data, item.parentId);
				}
				break;
			}
			if (item.children && item.children.length) {
				fn(item.children, parentId);
			}
		}
	};
	fn(data, parentId);
	return parents.value;
}

function cellClick(row: any, column: any, cell: any) {
	for (let i = 0; i < document.getElementsByClassName("current-cell").length; i++) {
		document.getElementsByClassName("current-cell")[i].classList.remove("current-cell");
	}
	cell.classList.add("current-cell");
}

function removeClass() {
	document.getElementsByClassName("current-cell")[0].classList.remove("current-cell");
}

// 绑定值回调
function onChange() {
	selectionAllData.value = [];
	mapChecked(tableData.value);
	emit("update:modelValue", selectionAllData.value);
}

function changeStatus() {
	selectionAllData.value = [];
	mapChecked(tableData.value);
	emit("update:modelValue", selectionAllData.value);
}
function changeStatusAndChild(data: any) {
	selectionAllData.value = [];
	mapChecked(tableData.value);
	emit("update:modelValue", selectionAllData.value);
	getHideChild(data["children"], data["isHideChild"]);
}

function getHideChild(data: any, zt: any) {
	const childs = ref<any[]>([]);
	let fn = (arr: any, zt: any) => {
		for (let item of arr) {
			item.isHide = zt;
			item.isHideChild = zt;
			childs.value.push(item);
			if (item.children && item.children.length) {
				fn(item.children, zt);
			}
		}
	};
	fn(data, zt);
	return childs.value;
}

//过滤监听
watch(
	() => props.modelValue,
	(val) => {
		value.value = val ? Number(val) : val;
	},
	{
		immediate: true
	}
);
useUpsert({
	async onOpened() {
		await service.base.sys.layers.list().then((res) => {
			list.value = res.filter((e) => e.id != Form.value?.form.id);
			list.value = res.filter((e) => {
				e.isCheck = 3;
				return e;
			});
		});
		if (props.modelValue.length > 0) {
			await service.base.sys.atlas.layerList({ idd: props.modelValue }).then((res) => {
				list.value = res.filter((e) => {
					if (e.atlasId !== null) {
						const treenode = e.treeNode.split("");
						if (treenode[0] == "Y") {
							e.isHide = "1";
						} else {
							e.isHide = "0";
						}
						if (treenode[1] == "Y") {
							e.isExpand = "1";
						} else {
							e.isExpand = "0";
						}
						if (treenode[2] == "R") {
							e.isCheck = 6;
						} else {
							if (treenode[2] == "C") {
								e.isCheck = 9;
							} else {
								e.isCheck = 3;
							}
						}
						if (treenode[3] == "Y") {
							e.isInit = "1";
						} else {
							e.isInit = "0";
						}
						e.pageCheck = true;
					}
					return e;
				});
			});
		}
	}
});
onMounted(() => {
	initData();
});
</script>

<style lang="scss" scoped>
.layers-check {
	position: relative;
	height: 400px;
	overflow-y: scroll;
	.check-page-all {
		position: absolute;
		top: 13px;
		left: 13px;
		z-index: 100;
	}
}
</style>
