<template>
  <div :class="addBefore ? 'el-tree-select' : 'el-tree-default'">
    <!-- <div class="tree-prefix">树选择</div> -->
    <template v-if="addBefore">
      <p
        class="el-tree-select-prefix-box"
        :class="[
          {'el-tree-select-prefix-box_disabled': disabled },
          size !== undefined ? `el-tree-select-prefix-box_${size}` : ''
        ]"
      >
        <slot name="prefix"></slot>
      </p>
    </template>
    <el-select
      :class="[
        {'tree-prefix-select': addBefore},
        {'tree-disabled-prefix': disabled },
        size !== undefined ? `tree-prefix-${size}-select` : ''
      ]"
      ref="select"
      v-model="treeStatus"
      value-key="id"
      :size="size"
      :disabled="disabled"
      treeSelect
      :filterable="filterable"
      @filterData="filterData"
      :style="styleObject"
      :multiple="showCheckbox"
      @change="selectChange"
      @remove-tag="removeTag"
      collapse-tags
      :clearable="clearable"
      :placeholder="placeholder"
      :tempList="tempList"
      :tempKey="tempKey"
      :tempLabel="tempLabel"
    >
      <!-- <template #prefix v-if="addBefore">
        <p class="prefix-box">
          <slot name="prefix"></slot>
        </p>
      </template> -->
      <!-- 这里不能删，删了data为空数组时不会出现 暂无内容 -->
      <el-option hidden value="xx" label="xx" key="xxxxx"></el-option>
      <!-- 这里不能删，会导致下拉展示内容出现错误 -->
      <el-option
        hidden
        v-for="(item, _index) in treeData"
        :value="item[nodeKey || props.label]"
        :label="item[props.label]"
        :key="_index"
      ></el-option>
      <el-tree
        class="el-tree-select-popper"
        ref="tree"
        :data="data"
        :node-key="nodeKey"
        :props="props"
        :defaultExpandAll="defaultExpandAll"
        :show-checkbox="showCheckbox"
        :expand-on-click-node="expandOnClickNode"
        :check-strictly="checkStrictly"
        @node-click="clickNode"
        @check-change="handleCheckChange"
        @check="checkTree"
        @current-change="currentChange"
        :isSelect="isSelect"
        :filter-node-method="filterNode"
        :lazy="lazy"
        :load="load"
        :class="customClass"
        :isOverflowHidden="isOverflowHidden"
        v-if="useSlot"
      >
        <template slot-scope="{ node, data }">
          <slot :node="node" :data="data"></slot>
        </template>
      </el-tree>
      <el-tree
        class="el-tree-select-popper"
        ref="tree"
        :data="data"
        :node-key="nodeKey"
        :props="props"
        :defaultExpandAll="defaultExpandAll"
        :show-checkbox="showCheckbox"
        :expand-on-click-node="expandOnClickNode"
        :check-strictly="checkStrictly"
        @node-click="clickNode"
        @check-change="handleCheckChange"
        @check="checkTree"
        @current-change="currentChange"
        :isSelect="isSelect"
        :filter-node-method="filterNode"
        :render-content="renderContent"
        :lazy="lazy"
        :load="load"
        :isolationParent="isolationParent"
        :class="customClass"
        :isOverflowHidden="isOverflowHidden"
        v-else
      >
      </el-tree>
    </el-select>
  </div>
</template>

<script>
import Emitter from "modesign-ui/src/mixins/emitter";
import { valueEquals } from "modesign-ui/src/utils/util";
import ElSelect from 'modesign-ui/packages/select';
import ElOption from 'modesign-ui/packages/option';

export default {
  name: "ElTreeSelect",

  mixins: [Emitter],
  
  components: { ElSelect, ElOption },

  data() {
    return {
      treeData: [],
      isSelect: true,
      treeStatus: this.value,
    };
  },

  props: {
    addBefore: {
      type: Boolean,
      default: false
    },
    size: {
      type: String
    },
    disabled: {},
    value: {
      required: true,
    },
    filterable: {
      type: Boolean,
      default: false,
    },
    clearable: {
      type: Boolean,
      default: false,
    },
    placeholder: {
      type: String,
      default: "请选择",
    },
    selectWidth: {
      type: Number,
    },
    nodeKey: {
      type: String,
      default: "",
    },
    expandOnClickNode: {
      type: Boolean,
      default: true,
    },
    showCheckbox: {
      type: Boolean,
      default: false,
    },
    checkStrictly: {
      type: Boolean,
      default: false,
    },
    data: {
      type: Array,
      default: () => [],
    },
    defaultExpandAll: {},
    props: {
      type: Object,
      default: () => {
        return {
          children: "children",
          label: "label",
        };
      },
    },
    // 是否使用插槽
    useSlot: {
      type: Boolean,
      default: false,
    },
    renderContent: Function,
    lazy: {
      type: Boolean,
      default: false,
    },
    load: Function,
    // 是否去重
    isunique: {
      type: Boolean,
      default: false,
    },
    closeSelectVisible: {
      type: Boolean,
      default: true,
    },
    // 是否只是叶子节点
    leafOnly: {
      type: Boolean,
      default: false,
    },
    // 是否包含半选节点
    includeHalfChecked: {
      type: Boolean,
      default: false,
    },
    // 父级联动隔离
    isolationParent: {
      type: Boolean,
      default: false,
    },
    customClass: {
      type: String,
      default: ''
    },
    tempList: {
      // 备选数组，防止选择的id找不到对应label。比如离职人员，选了id找不到姓名
      type: Array,
      default: () => []
    },
    tempKey: {
      type: String,
      default: 'id'
    },
    tempLabel: {
      type: String,
      default: 'label'
    },
    notFilter: {
      type: Boolean,
      default: false
    },
    isOverflowHidden: {
      type: Boolean,
      default: false
    }
  },

  computed: {
    styleObject() {
      return this.selectWidth ? { width: `${this.selectWidth}px` } : "";
    },
  },

  watch: {
    value: {
      handler(val, oldVal) {
        if (!valueEquals(val, oldVal)) {
          this.dispatch("ElFormItem", "el.form.change", val);
        }

        // 多选时设置tree的勾选
        if (this.showCheckbox) {
          if (!Array.isArray(oldVal) && !Array.isArray(val)) return
          if (!Array.isArray(oldVal)) oldVal = ''
          oldVal &&
            oldVal.forEach((item) => {
              this.$nextTick(() => {
                this.$refs.tree.setMyChecked &&
                  this.$refs.tree.setMyChecked(item, false, true);
              });
            });
          this.$nextTick(() => {
            if (!Array.isArray(val)) return
            val && val.forEach((item) => {
              this.$refs.tree.setMyChecked &&
                this.$refs.tree.setMyChecked(item, true, true);
            });
          });
        }

        // 单选时设置tree的高亮
        if (!this.showCheckbox) {
          this.$nextTick(() => {
            let node = this.$refs.tree.getNode(val);
            if (node) {
              this.$refs.tree.setCurrentKey(val);
              const nodeData = this.$refs.tree.getCurrentNode();
              // this.treeData = [nodeData];
            }else {
              this.nodeKey && this.$refs.tree.setCurrentKey(null);
            }
          });
        }
        this.treeStatus = val;
      },
      immediate: true,
    },

    data: {
      handler(val) {
        this.treeData = this.treeToArray(val);
        if (this.value && this.value.length && this.showCheckbox) {
          if (this.$refs.tree !== undefined) {
            this.$refs.tree.setCheckedKeys(this.value);
          }
        }
      },
      immediate: true,
    },
  },

  methods: {
    removeTag(val) {
      this.$emit("remove-tag", val);
      if (val) {
        this.$refs.tree.setMyChecked &&
          this.$refs.tree.setMyChecked(val, false, true);
      }
    },
    selectChange(e) {
      // 有复选框时删除选中的标签
      if (this.showCheckbox) {
        const arrNew = [];
        e.forEach((item) => {
          const checked = this.treeData.find(
            (x) => x[this.nodeKey || this.props.label] === item
          );
          arrNew.push(checked);
          });
        this.$emit(
          "input",
          arrNew.map((item) => item[this.nodeKey || this.props.label])
        );
        this.$emit("change", arrNew);
      } else {
        this.$emit("input", "");
        this.$emit("change", "");
      }

    },
    checkTree(data, checked) {
      this.$emit("check", data, checked);
    },
    currentChange(data, nodeData) {
      this.$emit("current-change", data, nodeData);
    },
    handleCheckChange(data, checked, indeterminate) {
      this.$emit("check-change", data, checked, indeterminate);
      if (this.showCheckbox) {
        //设置选择框状态
        data[this.nodeKey || this.props.label] &&
          this.$refs.tree.setMyChecked &&
          this.$refs.tree.setMyChecked(data, checked, true);
        let res = this.$refs.tree.getCheckedNodes(this.leafOnly, this.includeHalfChecked); // 第一个是否只是叶子节点 第二个是否包含半选节点
        let arrLabel = [];
        let arr = [];
        let arrValue = [];
        res.forEach((item) => {
          arrLabel.push(item[this.props.label]);
          arr.push(item);
          arrValue.push(item[this.nodeKey || this.props.label]);
        });
        if (this.isunique) {
          if (!(this.$MODesignConfig.notFilter || this.notFilter)) {
            this.$emit("input", Array.from(new Set(arrValue)));
          } else {
            this.$emit("input", Array.from(new Set(this.value)));
          }
          // this.treeData = this.unique(arr);
          this.$emit("change", this.unique(arr));
        } else {
          if (!(this.$MODesignConfig.notFilter || this.notFilter)) {
            this.$emit("input", arrValue);
          }
          // this.treeData = arr;
          this.$emit("change", arr);
        }
      }
     // if(this.$refs.select){
     //   setTimeout(()=>{
     //     this.$refs.select.focus()
     //   },0.5)
     // }
    },
    clickNode(node, v1, v2) {
      this.$emit("node-click", node, v1, v2);
      if (node.disabled) {
        return;
      }
      if (!this.showCheckbox) {
        // this.treeData = [node];
        this.$emit("input", node[this.nodeKey || this.props.label]);
        const arrNew = [];
        const checked = this.treeData.find(
          (x) =>
            x[this.nodeKey || this.props.label] ===
            node[this.nodeKey || this.props.label]
        );
        arrNew.push(checked);
        this.$emit("change", arrNew);
        if(this.closeSelectVisible) {
          this.$refs.select.visible = false;
        }
      }
    },

    closeSelectBox(){
      if(this.$refs.select) {
        this.$refs.select.visible = false;
      }
    },

    filterData(val) {
      this.$refs.tree && this.$refs.tree.filter(val);
    },
    filterNode(value, data) {
      if (!value) return true;
      return data[this.props.label].toString().indexOf(value) !== -1;
    },

    // 去重
    unique(arr) {
      let obj = {};
      let data = arr.reduce((item, next) => {
        obj[next[this.nodeKey || this.props.label]]
          ? ""
          : (obj[next[this.nodeKey || this.props.label]] =
              true && item.push(next));
        return item;
      }, []);
      return data;
    },

    // 数结构扁平化处理
    treeToArray(tree) {
      let res = [];
      for (const item of tree) {
        const { children, ...i } = item;
        if (children && children.length) {
          res = res.concat(this.treeToArray(children));
        }
        res.push(i);
      }
      return res;
    },
  }
};
</script>
