<template>
  <transition name="fade">
    <ul :class="wrapClasses">
      <li>
        <div :class="titleWrapClasses" :style="titleStyle">
          <span :class="[prefix+'-arrow']" @click.stop="toggleExpand">
            <Icon
              v-if="node[childKey]&&!node.loading"
              :type="iconType"
              :class="{expanded:expanded}"
            ></Icon>
            <Icon v-if="node.loading" :type="loadIcon" class="load" />
          </span>
          <span @click.stop="clickTitle" :class="[prefix+'-title-content']">
            <i
              v-if="(!parentSelectDisabled||(parentSelectDisabled&&!node[childKey]))&&checkable&&checkPosition==='left'"
              class="left-check-icon"
              :class="[unCheckIcon?'unCheckIcon vsu-ion vsu-ion-'+unCheckIcon:prefix+'-check-box']"
            ></i>
            <span
              :class="[prefix+'-title']"
              :title="node[titleKey]+(node.length!==undefined?('（'+node.length+'）'):'')"
            >
              {{node[titleKey]}}
              <span
                :class="[prefix+'-length']"
                v-if="node.length!==undefined"
              >（{{node.length}}）</span>
            </span>
            <i
              v-if="(!parentSelectDisabled||(parentSelectDisabled&&!node[childKey]))&&checkable&&checkPosition==='right'"
              class="right-check-icon"
              :class="[unCheckIcon?'unCheckIcon vsu-ion vsu-ion-'+unCheckIcon:prefix+'-check-box']"
            ></i>
          </span>
          <DropDown v-if="editable&&action&&action.length" :class="[prefix+'-action-wrapper']" align="right" @on-click="handleAction">
            <span :class="[prefix+'-action-title']">...</span>
            <DropDownList slot="list">
                <DropDownItem v-for="(item,index) in action" :key="index" :name="item.name">{{item.title}}</DropDownItem>
            </DropDownList>
          </DropDown>
        </div>
        <div
          :class="bodyWrapClasses"
          :style="{display: expanded?'block':'none'}"
          v-if="node[childKey]"
        >
          <TreeNode
            v-for="(itm,i) in node[childKey]"
            :key="i"
            :node="itm"
            :level="level+1"
            :action="itm.action"
            :data_id="itm.id"
            :data_name="itm[titleKey]"
            :disabled="itm.disabled"
            :id="(tRootId)?(tRootId+itm.id):''"
            :expand="itm.expand"
            :check="itm.check"
          ></TreeNode>
        </div>
      </li>
    </ul>
  </transition>
</template>
<script>
import Icon from "../icon";
import DropDown from "../drop-down";
import Emitter from "../../mixins/emitter";
import { findComponentUpward } from "../../utils/assist";
import { prefix } from "../var";
const treePrefix = prefix + "tree";
const treeNodePrefix = prefix + "tree-node";
export default {
  name: "TreeNode",
  componentName: "TreeNode",
  components: { Icon,DropDown },
  mixins: [Emitter],
  props: {
    level: {
      type: [String, Number]
    },
    node: {
      type: Object,
      default() {
        return {};
      }
    },
    action:{
      type:[Object,Array],
      default() {
        return [];
      }
    },
    expand: {
      //展开
      type: Boolean,
      default: false
    },
    check: {
      //选中
      type: Boolean,
      default: false
    },
    disabled: {
      //禁止
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      tprefix:treePrefix,
      prefix: treeNodePrefix,
      expanded: this.expand,
      selected: false,
      checkable: false,
      unCheckIcon: false,
      checkPosition: "",
      checked: this.check,
      forbided: this.disabled,
      // selected:false,
      // accordion:false,
      data: this.node,
      iconType: "triangle-down",
      loadIcon: "loading",
      type: "single",
      multiDisabledChild: false,
      titleKey: "title",
      childKey: "childs",
      tRootId:'',
      selectedTreeId:[],
      selectedTree:[],
      parentSelectDisabled:false,
      editable:false,
      familySelect:false,
      defaultLeft:0
    };
  },
  computed: {
    wrapClasses() {
      return [
        `${treeNodePrefix}`,
        {
          [`${treeNodePrefix}-disabled`]: this.forbided
        }
      ];
    },
    titleWrapClasses() {
      return [
        `${treeNodePrefix}-title-wrap`,
        {
          [`${treeNodePrefix}-title-active`]: this.selected,
          [`${treeNodePrefix}-title-check`]: this.checked
        }
      ];
    },
    arrowClasses() {
      return `${treeNodePrefix}-title-arrow`;
    },
    titleClasses() {
      return `${treeNodePrefix}-title`;
    },
    bodyWrapClasses() {
      return `${treeNodePrefix}-body`;
    },
    titleStyle() {
      return {
        "padding-left": 18 * this.level + this.defaultLeft + "px"
      };
    }
  },
  watch: {
    check(check) {
      if (check === false) {
        this.checked = false;
      }
    },
    expand(val) {
      this.expanded = val;
    }
  },
  methods: {
    // 寻找当前节点下符合条件的所有节点
    findChild(cb) {
      const find = function(child) {
        const name = child.$options.componentName;
        if (name) {
          cb(child);
        }
        if (child.$children.length) {
          child.$children.forEach(innerChild => {
            find(innerChild, cb);
          });
        }
      };
      this.$children.forEach(child => {
        find(child);
      });
    },
    // 寻找当前节点上符合条件的所有父节点
    findParent(cb) {
      const find = function(parent, cb) {
        let checked = true;
        parent.$children.forEach(child => {
          const name = child.$options.componentName;
          if (name) {
            if (child.checked === false) {
              checked = false;
            }
          }
        });
        cb(parent, checked);

        if (parent.$parent) {
          find(parent.$parent, cb);
        }
      };
      find(this.$parent, cb);
    },
    handleAction(type){
      this.dispatch("Tree", "on-action", {
        type:type,
        data:this.node
      })
    },
    handleCheck() {
      this.checked = !this.checked;
      if(this.familySelect){
        // 选中/不选中下面的子节点
        this.findChild(child => {
          child.checked = this.checked;
          if (this.multiDisabledChild && this.checked) {
            child.forbided = true;
          } else {
            child.forbided = false;
          }
          this.dispatch("Tree", "on-check", child);
        });
      }
      this.dispatch("Tree", "on-check", this);
      
      if(this.parentSelectDisabled){
        return;
      }
      if(this.familySelect){
        // 选中/不选中上面的父节点
        this.$nextTick(() => {
          this.findParent((parent, checked) => {
            parent.checked = checked;
            if (parent.multiDisabledChild && parent.checked) {
              parent.findChild(child => {
                if (child.level !== 0) {
                  child.forbided = true;
                }
                this.dispatch("Tree", "on-check", child);
              });
            }
            this.dispatch("Tree", "on-check", parent);
          });
        });
      }
    },
    clickTitle(e) {
      if (this.forbided) {
        return;
      }
      if(this.parentSelectDisabled&&this.node[this.childKey]){
        return;
      }
      if (this.type === "single") {
        this.handleSelect();
        if(this.selectTree){
          this.UpdateSelectedTree(e);
        }
      } else {
        this.handleCheck();
      }
    },
    handleSelect() {
      this.selected = true;
      this.dispatch("Tree", "on-select", this);
    },
    UpdateSelectedTree(e){
      this.selectedTree = [];
      this.selectedTreeId = [];
      this.updateSelectedTreeId(e)
      this.dispatch("Tree", "on-update-selectedtree", {
        id:this.selectedTreeId,
        tree:this.selectedTree
      });

    },
    updateSelectedTreeId(e){
      this.findNode(e.target);
      this.selectedTree.reverse();
      this.selectedTreeId.reverse();
    },
    findNode(node){
      /**
       * 节点的类可能有多个，设置成数组检查
       */
      let nodeClasses = node.className?node.className.split(" "):"";
      if(nodeClasses.includes(this.prefix)){
        this.selectedTreeId.push(node.attributes['data_id'].value)
        this.selectedTree.push({
          id:node.attributes['data_id'].value,
          [this.titleKey]:node.attributes['data_name'].value
        })
        this.findNode(node.parentNode)
      }else if(nodeClasses.includes(this.tprefix)){
        return false
      }else{
        this.findNode(node.parentNode)
      }
    },
    toggleExpand() {
      const item = this.node;
      if (item.forbided) return;

      //async loading
      if (this.node[this.childKey]&&this.node[this.childKey].length === 0) {
        const tree = findComponentUpward(this, "Tree");
        if (tree && tree.loadData) {
          this.$set(this.node, "loading", true);
          tree.loadData(item, children => {
            this.$set(this.node, "loading", false);
            if (children.length) {
              this.$set(this.data, "childs", children);
              this.$nextTick(() => this.toggleExpand());
            }
          });
          return;
        }
      }

      if (this.node[this.childKey] && this.node[this.childKey].length) {
        this.expanded = !this.expanded;
      }
      // 以下方法先禁掉，当前业务无需此功能，并且此功能没有写完全
      // this.selected = !this.selected;
      // if(this.expanded&&this.accordion){

      // }
      // this.dispatch('Tree', 'on-click', this);
    }
  },
  mounted() {
    const Tree = findComponentUpward(this, "Tree");
    if (Tree) {
      this.checkable = Tree.checkable ;
      this.unCheckIcon = Tree.unCheckIcon ? Tree.unCheckIcon : false;
      this.iconType = Tree.iconType;
      this.loadIcon = Tree.loadIcon;
      this.checkPosition = Tree.checkPosition;
      this.multiDisabledChild = Tree.multiDisabledChild;
      this.tRootId = Tree.id;
      this.selectTree = Tree.selectTree;
      this.familySelect = Tree.familySelect;
      this.parentSelectDisabled = Tree.parentSelectDisabled;
      this.titleKey = Tree.titleKey;
      this.childKey = Tree.childKey;
      this.type = Tree.type;
      this.editable = Tree.editable;
      this.defaultLeft = Tree.defaultLeft;
      // this.accordion = Tree.accordion;
      if (
        !!Tree.defaultExpanded &&
        Tree.defaultExpanded.length &&
        Tree.defaultExpanded.indexOf(this.node.id) > -1
      ) {
        this.expanded = true;
      }
      if (
        !!Tree.defaultChecked &&
        Tree.defaultChecked.length &&
        Tree.defaultChecked.indexOf(this.node.id) > -1
      ) {
        this.checked = true;
      }
    }
    if (this.checkable) {
      if(this.familySelect){
        if (this.$parent.checked) {
          this.checked = true;
        }
        if (this.checked) {
          this.findChild(child => {
            child.checked = this.checked;
            if (this.multiDisabledChild && this.checked) {
              child.forbided = true;
            } else {
              child.forbided = false;
            }
          });
        }
      }
    }
  }
};
</script>
