<template>
	<el-tree
    :data="cData"
    :empty-text="emptyText"
    :node-key="nodeKey"
    :props="props"
    :render-after-expand="renderAfterExpand"
    :load="load"
    :render-content="renderContent"
    :highlight-current="highlightCurrent"
    :default-expand-all="defaultExpandAll"
    :expand-on-click-node="expandOnClickNode"
    :check-on-click-node="checkOnClickNode"
    :auto-expand-parent="autoExpandParent"
    :default-expanded-keys="expandedKeys"
    :show-checkbox="showCheckbox"
    :check-strictly="checkStrictly"
    :default-checked-keys="checkedKeys"
    :current-node-key="currentNodeKey"
    :filter-node-method="filterNodeMethod"
    :accordion="accordion"
    :indent="indent"
    :icon="icon"
    :lazy="lazy"
    :draggable="draggable"
    :allow-drag="allowDrag"
    :allow-drop="allowDrop"
    @node-click="nodeClick"
    @node-contextmenu="nodeContextmenu"
    @check-change="checkChange"
    @check="check"
    @current-change="currentChange"
    @node-expand="nodeExpand"
    @node-collapse="nodeCollapse"
    @node-drag-start="nodeDragStart"
    @node-drag-enter="nodeDragEnter"
    @node-drag-leave="nodeDragLeave"
    @node-drag-over="nodeDragOver"
    @node-drag-end="nodeDragEnd"
    @node-drop="nodeDrop"
	>
		<template #default="{ data }" v-if="actions.length > 0">
      <div class="title-div">
        <div>
          <span>{{ data.title}}</span>
        </div>
        <div class="title-div-slot">
          <el-popover>
            <template #reference>
              <el-icon><more /></el-icon>
            </template>
            <el-menu>
              <el-menu-item
                v-for="(action, index) in actions"
                :key="index"
                @click="action.callback(action, {key: data.key, title: data.title})"
              >
                {{ action.name }}
              </el-menu-item>
            </el-menu>
          </el-popover>
        </div>
      </div>
		</template>
	</el-tree>
</template>

<script>
import { getAction, postAction } from "/@/request/http";
import _ from "lodash";
import { More } from "@element-plus/icons";

export default {
	name: "HmElementTree",
  components: {
    More
  },
	props: {
		/**
		 * 数据
		 */
		data: {
			type: Array,
			default: function () {
				return [
					{
						title: "0-0",
						key: "0-0",
						children: [
							{
								title: "0-0-0",
								key: "0-0-0",
								children: [
									{ title: "0-0-0-0", key: "0-0-0-0" },
									{ title: "0-0-0-1", key: "0-0-0-1" },
									{ title: "0-0-0-2", key: "0-0-0-2" },
								],
							},
							{
								title: "0-0-1",
								key: "0-0-1",
								children: [
									{ title: "0-0-1-0", key: "0-0-1-0" },
									{ title: "0-0-1-1", key: "0-0-1-1" },
									{ title: "0-0-1-2", key: "0-0-1-2" },
								],
							},
							{
								title: "0-0-2",
								key: "0-0-2",
							},
						],
					},
					{
						title: "0-1",
						key: "0-1",
						children: [
							{ title: "0-1-0-0", key: "0-1-0-0" },
							{ title: "0-1-0-1", key: "0-1-0-1" },
							{ title: "0-1-0-2", key: "0-1-0-2" },
						],
					},
					{
						title: "0-2",
						key: "0-2",
					},
				];
			},
		},
		/**
		 * 操作按钮
		 */
		actions: {
			type: Array,
			default: function () {
				return [
					{
						name: "添加子级",
						callback: function (action, item) {
							console.log("添加子级: ", action, item);
						},
					},
					{
						name: "删除",
						callback: function (action, item) {
							console.log("删除: ", action, item);
						},
					},
					{
						name: "重命名",
						callback: function (action, item) {
							console.log("重命名: ", action, item);
						},
					},
				];
			},
		},
		/**
		 * 内容为空展示文本
		 */
		emptyText: {
			type: String,
		},
		/**
		 * 树节点唯一标识
		 */
		nodeKey: {
			type: String,
			default: "id",
		},
		/**
		 * GET URL
		 */
		url: {
			type: String,
		},
		/**
		 * GET Params
		 */
		params: {
			type: Object,
		},
    /**
     * 数据父字段
     */
    parentColumn: {
      type: String,
      default: 'parentId'
    },
		/**
		 * 远程数据映射
		 */
		dataMap: {
			type: Object,
			default: function () {
				return {
					key: "key",
					title: "title",
				};
			},
		},
		/**
		 * 配置选项
		 */
		props: {
			type: Object,
			default: function(){
        return {
          children: 'children',
          label: 'label',
        }
      },
		},
		
		/**
		 * 是否在第一次展开某个树节点后才渲染其子节点
		 */
		renderAfterExpand: {
			type: Boolean,
			default: true,
		},
		/**
		 * 加载子树数据的方法
		 */
		load: {
			type: Function,
		},
    /**
		 * 树节点的内容区的渲染 Function
		 */
		renderContent: {
			type: Function,
		},
		/**
		 * 是否高亮当前选中节点
		 */
		highlightCurrent: {
      type: Boolean,
      default: false
    },
    /**
		 * 是否默认展开所有节点
		 */
    defaultExpandAll: {
      type: Boolean,
      default: false
    },
    /**
		 * 是否在点击节点的时候展开或者收缩节点
		 */
    expandOnClickNode: {
      type: Boolean,
      default: true
    },
    /**
		 * 是否在点击节点的时候选中节点
		 */
    checkOnClickNode: {
      type: Boolean,
      default: false
    },
    /**
     * 展开子节点的时候是否自动展开父节点
     */
    autoExpandParent: {
      type: Boolean,
      default: true
    },
    /**
     * 默认展开的节点的 key 的数组
     */
    defaultExpandedKeys: {
      type: Array,
      default: function(){
        return []
      }
    },
    /**
     * 节点是否可被选择
     */
    showCheckbox: {
      type: Boolean,
      default: false
    },
		/**
		 * 在显示复选框的情况下，是否严格的遵循父子不互相关联的做法
		 */
		checkStrictly: {
			type: Boolean,
			default: false,
		},
		/**
		 * 默认勾选的节点的 key 的数组
		 */
		checkedKeys: {
			type: Array,
			default: function(){
        return []
      },
		},
		/**
		 * 当前选中的节点
		 */
		currentNodeKey: {
			type: String,
		},
    /**
		 * 对树节点进行筛选时执行的方法
		 */
		filterNodeMethod: {
			type: Function,
		},
    /**
		 * 是否每次只打开一个同级树节点展开
		 */
		accordion: {
			type: Boolean,
      default: false
		},
    /**
		 * 是否每次只打开一个同级树节点展开
		 */
		accordion: {
			type: Boolean,
      default: false
		},
    /**
		 * 自定义图标
		 */
		icon: {
			type: String,
		},
    /**
     * 是否懒加载子节点
     */
    lazy: {
      type: Boolean,
      default: false
    },
    /**
     * 是否开启拖拽节点功能
     */
    draggable: {
      type: Boolean,
      default: false
    },
    /**
     * 判断节点能否被拖拽
     */
    allowDrag: {
      type: Function,
    },
    /**
     * 拖拽时判定目标节点能否成为拖动目标位置
     */
    allowDrop: {
      type: Function,
    }
	},
	data() {
		return {
			expandedKeys: ["0-0-0", "0-0-1"],
			originCheckedKeys: [],
			cCheckedKeys: ["0-0-0"],
			selectedKeys: [],
			cData: [],
			cActions: [],
		};
	},
	watch: {
		checkedKeys: {
			handler: function (value, oldValue) {
				this.cCheckedKeys = value;
			},
			deep: true,
		},
		url(value) {
			this.getData(value);
		},
		params: {
			handler: function (value) {
				console.log("params change");
				this.getData(null, value);
			},
			deep: true,
		},
		cData: {
			handler: function (value) {
				this.cData = value;
			},
			deep: true,
		},
		cActions: {
			handler: function (value) {
				this.cActions = value;
			},
			deep: true,
		},
	},
	mounted() {
		console.log(`mounted: `, this.data);
		if (this.checkedKeys != null && typeof this.checkedKeys != "undefined") {
			this.cCheckedKeys = JSON.parse(JSON.stringify(this.checkedKeys));
			this.originCheckedKeys = JSON.parse(JSON.stringify(this.checkedKeys));
		}

		this.cData = this.data;
		this.cActions = this.actions;
		this.getData();
	},
	methods: {
		getData(url, params) {
			let self = this;
			url = url || this.url;
			console.log("请求使用的url", url);
			params = params || (this.params ? JSON.parse(JSON.stringify(this.params)) : {});
			getAction(url, params).then((res) => {
				if (res.result.treeList) {
					self.cData = res.result.treeList;
				} else {
          let flatData = res.result ? (res.result.records || res.result) : res.data;
          if (self.dataMap.key && self.dataMap.title) {
            self.cData = self.convertArrayToTree(flatData, self.parentColumn, self.dataMap);
          }
				}
			});
		},
    /**
     * 将生成的Rest接口的数据转换成树状结构
     */
    convertArrayToTree(arr, parentColumn, dataMap) {
      parentColumn = parentColumn || 'parentId';
      var map = {}, node, roots = [], i;
  
      for (i = 0; i < arr.length; i += 1) {
        map[arr[i].id] = i; // initialize the map
        arr[i].children = []; // initialize the children
      }
      
      for (i = 0; i < arr.length; i += 1) {
        node = arr[i];
        node.key = node[dataMap.key];
        node.title = node[dataMap.title];
        if (node[parentColumn]) {
          // if you have dangling branches check that map[node.parentId] exists
					if (typeof arr[map[node[parentColumn]]] == 'undefined') {
						console.log(`找不到数组中的：`, map[node[parentColumn]], parentColumn)
						continue;
					}
          arr[map[node[parentColumn]]].children.push(node);
        } else {
          roots.push(node);
        }
      }
      return roots;
    },
		nodeClick(e){
      this.$emit("nodeClick", e);
    },
    nodeContextmenu(e){
      this.$emit("nodeContextmenu", e);
    },
    checkChange(e){
      this.$emit("checkChange", e);
    },
    check(e){
      this.$emit("check", e);
    },
    currentChange(e){
      this.$emit("currentChange", e);
    },
    nodeExpand(e){
      this.$emit("nodeExpand", e);
    },
    nodeCollapse(e){
      this.$emit("nodeCollapse", e);
    },
    nodeDragStart(e){
      this.$emit("nodeDragStart", e);
    },
    nodeDragEnter(e){
      this.$emit("nodeDragEnter", e);
    },
    nodeDragLeave(e){
      this.$emit("nodeDragLeave", e);
    },
    nodeDragOver(e){
      this.$emit("nodeDragOver", e);
    },
    nodeDragEnd(e){
      this.$emit("nodeDragEnd", e);
    },
    nodeDrop(e){
      this.$emit("nodeDrop", e);
    },
	},
};
</script>

<style scoped>
.ant-tree {
	width: 100%;
}
.ant-tree :deep(.ant-tree-node-content-wrapper) {
	width: 98.9%;
}

.title-div {
  width: 100%;
	display: flex;
	justify-content: space-between;
	align-items: center;
}
.title-div-slot {
	margin-right: 12px;
}
.ant-menu-inline,
.ant-menu-vertical,
.ant-menu-vertical-left {
	border-right: 0px solid #f0f0f0;
}
</style>