<template>
  <div class="el-tree-transfer">
    <el-row :gutter="20">
        <el-col :span="showCheckbox ? 10 : 12">
          <div class="el-tree-transfer__col">
            <div class="el-tree-transfer__head">{{checkTitle}}</div>
            <el-input v-if="showSearch && !renderFilter" class="el-tree-transfer__input"
              placeholder="输入关键字进行过滤"
              v-model="filterUncheckText">
            </el-input>
            <filter-input v-if="renderFilter" />
            <div :class="{'el-tree-transfer__tree': true, 'el-tree-transfer__tree--search': showSearch}">
              <el-tree
                      v-if="(filterUncheckText && filterHandle) || (renderFilter && loadSearchData.length >0)"
                      ref="searchTree"
                      key="searchTree"
                      :data="loadSearchData"
                      :render-content="renderWrapContent()"
                      :check-strictly="checkStrictly"
                      :default-expanded-keys="defaultExpandedKeys"
                      :default-checked-keys="myDefaultCheckedKeys"
                      :show-checkbox="showCheckbox"
                      :node-key="uniqueId"
                      :props="{
                         label: showName,
                         children: children,
                         isLeaf: leafKey,
                         hideCheckbox: 'hideCheckbox'
                      }"
                      @check-change="checkChange"
                      @node-click="nodeClick"
                      @set-default-check="setDefaultCheck">
              </el-tree>
              <el-tree
                v-else
                key="tree"
                ref="tree"
                :filter-node-method="filterNode"
                :data="data"
                :render-content="renderWrapContent()"
                :check-strictly="checkStrictly"
                :default-expanded-keys="defaultExpandedKeys"
                :default-checked-keys="myDefaultCheckedKeys"
                :show-checkbox="showCheckbox"
                :node-key="uniqueId"
                :lazy="lazy"
                :load="loadAsyncData"
                :props="{
                   label: showName,
                   children: children,
                   isLeaf: leafKey,
                   hideCheckbox: 'hideCheckbox'
                }"
                @check-change="checkChange"
                @node-click="nodeClick"
                @set-default-check="setDefaultCheck">
              </el-tree>
            </div>
          </div>
        </el-col>
        <el-col v-if="showCheckbox" style="height: 400px;" :span="4">
          <div class="el-tree-transfer__btngroup">
            <el-button type="primary" class="el-tree-transfer__btngroup__all" @click="checkAll">> 全选</el-button>
            <el-button class="el-tree-transfer__btngroup__clear" @click="clear">清空已选</el-button>
          </div>
        </el-col>
        <el-col :span="showCheckbox ? 10 : 12">
          <div class="el-tree-transfer__col">
            <div class="el-tree-transfer__head">{{checkedTitle}}</div>
            <el-input v-if="showSearch"
              class="el-tree-transfer__input"
              placeholder="输入关键字进行过滤"
              v-model="filterCheckText">
            </el-input>
            <div :class="{'el-tree-transfer__nodes': true, 'el-tree-transfer__nodes--search': showSearch}" ref="nodes">
              <el-scrollbar tag="div"
              :wrap-class="{'el-tree-transfer__scroll': true, 'el-tree-transfer__scroll--search': showSearch}">
                <template v-for="(i, index) in filterCheckNodes">
                  <div class="el-tree-transfer__list" v-if="i._classify && i.list.length">
                    <div class="el-tree-transfer__list__title">{{i._classify}}</div>
                    <template v-for="(item, in_index) in i.list">
                      <div class="el-tree-transfer__node" :key="`${item[uniqueId]}${in_index}`">
                        <span class="el-tree-transfer__node__label el-tree-transfer__node__label--group" :title="item[showName]">{{item[showName]}}</span>
                        <span class="el-icon-close el-tree-transfer__node__icon" @click="cancelCheck(item)"></span>
                      </div>
                    </template>
                  </div>
                  <div v-if="!i._classify" class="el-tree-transfer__node" :key="`${i[uniqueId]}${index}`">
                    <span class="el-tree-transfer__node__label" :title="i[showName]">{{i[showName]}}</span>
                    <span class="el-icon-close el-tree-transfer__node__icon" @click="cancelCheck(i)"></span>
                  </div>
                </template>
              </el-scrollbar>
              <!-- <template v-for="(i, index) in placeNodes">
                <div class="el-tree-transfer__placenode" :key="index"></div>
              </template> -->
            </div>
          </div>
        </el-col>
    </el-row>
  </div>
</template>

<script>
import ElTree from 'element-ui-for-gov/packages/tree';
import ElInput from 'element-ui-for-gov/packages/input';
import ElRow from 'element-ui-for-gov/packages/row';
import ElCol from 'element-ui-for-gov/packages/col';
import ElButton from 'element-ui-for-gov/packages/button';
import Radio from 'element-ui-for-gov/packages/radio';
import ElScrollbar from 'element-ui-for-gov/packages/scrollbar';
let _this;
export default {
  name: 'ElTreeTransfer',
  components: {
    ElTree,
    ElInput,
    ElRow,
    ElCol,
    ElButton,
    Radio,
    ElScrollbar,
    FilterInput: {
      render() {
        console.log('FilterInput-render', _this);
        if (_this.renderFilter) {
          return _this.renderFilter((data) => {
            _this.loadSearchData = data;
          });
        }
        return '';
      }
    }
  },
  props: {
    showSearch: {
      type: Boolean,
      default: false
    },
    checkTitle: {
      type: String,
      default: '待选'
    },
    checkedTitle: {
      type: String,
      default: '已选'
    },
    data: {
      type: Array
    },
    renderContent: {
      type: Function
    },
    checkStrictly: {
      type: Boolean,
      default() {
        return false;
      }
    },
    defaultExpandedKeys: {
      type: Array,
      default() {
        return [];
      }
    },
    defaultCheckedKeys: {
      type: Array
    },
    getLeafOnly: {
      type: Boolean,
      default() {
        return false;
      }
    },
    showCheckbox: {
      type: Boolean,
      default() {
        return true;
      }
    },
    uniqueId: {
      type: String,
      default: 'id'
    },
    showName: {
      type: String,
      default: 'label'
    },
    leafKey: {
      type: String,
      default: 'isLeaf'
    },
    children: {
      type: String,
      default: 'children'
    },
    lazy: {
      type: Boolean,
      default: false
    },
    load: {
      type: Function,
      default() {
        return () => {};
      }
    },
    defaultCheckedNodes: {
      type: Array
    },
    isSearchCheckAll: {
      type: Boolean,
      default: true
    },
    renderChecked: {
      type: Function
    },
    filterHandle: Function,
    renderFilter: Function
  },
  data() {
    return {
      radio: '',
      radioNode: {},
      filterUncheckText: '',
      filterCheckText: '',
      currentNodes: [],
      setRadioDefault: false,
      myDefaultCheckedKeys: [],
      nodeMap: {},
      searchData: [],
      loadSearchData: []
    };
  },
  created() {
    _this = this;
  },
  mounted() {
    if (this.$refs.tree && this.$refs.tree.store) {
      this.searchData = this.$refs.tree.store.root;
    }
  },
  methods: {
    asyncChangeCurrentNodes() {
      if (this.lazy) {
        let unLoadCheckedNodes = [];
        let treeCheckedNodes = this.getNodes();
        if (this.currentNodes && this.currentNodes.length) {
          this.currentNodes.forEach(node => {
            if (!this.nodeMap[node[this.uniqueId]]) {
              unLoadCheckedNodes.push(node);
            }
          });
        }
        // 自定义搜索过滤重复数据
        const keyMaps = [];
        this.currentNodes = treeCheckedNodes.concat(unLoadCheckedNodes).filter(node => {
          if (keyMaps.indexOf(node[this.uniqueId]) === -1) {
            keyMaps.push(node[this.uniqueId]);
            return true;
          } else {
            return false;
          }
        });
      } else {
        this.currentNodes = this.getNodes();
      }

    },
    _register(node) {
      if (node[this.uniqueId]) {
        this.nodeMap[node[this.uniqueId]] = node;
      }
      if (node[this.children] && node[this.children].length) {
        node[this.children].forEach(cNode => {
          this._register(cNode);
        });
      }
    },
    loadAsyncData(node, resolve) {
      this.load(node, (data) => {
        if (data && data.length) {
          data.forEach(dNode => {
            this._register(dNode);
          });
        }
        resolve(data);
        if (this.$refs.tree && this.$refs.tree.store) {
          this.searchData = this.$refs.tree.store.root;
        }
      });
    },
    initDefaultCheck() {
      if (!this.showCheckbox) {
        this.radio = this.myDefaultCheckedKeys[0];
        let node = this.findNode(this.radio, this.data || []) || {};
        this.radioNode = node;
        if (node && node[this.uniqueId]) {
          this.currentNodes = [node];
        }
      } else {
        this.currentNodes = this.getNodes();
      }
    },
    initDefaultCheckedNodes() {
      if (this.defaultCheckedNodes && this.defaultCheckedNodes.length) {
        this.currentNodes = this.defaultCheckedNodes;
        let keys = this.defaultCheckedNodes.map(node => node[this.uniqueId]);
        this.myDefaultCheckedKeys = keys;
        if (this.radio) {
          this.radio = this.defaultCheckedNodes[0][this.uniqueId];
          this.radioNode = this.defaultCheckedNodes[0];
        }
      }
    },
    stopRadio(e) {
      e.stopPropagation();
    },
    renderWrapContent() {
      if (this.renderContent && typeof this.renderContent === 'function') {
        return (h, { node, data, store }) => {
          return (<span class="wrap-tree-node">
            {(!this.showCheckbox && !node.hideCheckbox) && <Radio nativeOnClick={this.stopRadio} value={this.radio} onInput={this.$_handleRadio} label={data[this.uniqueId]} disabled={node.disabled === true}></Radio>}
            {this.renderContent(h, { node, data, store })}
          </span>);
        };
      } else {
        return (h, { node, data, store }) => {
          return (
            <span class="wrap-tree-node">
              {(!this.showCheckbox && !node.hideCheckbox) && <Radio nativeOnClick={this.stopRadio} value={this.radio} onInput={this.$_handleRadio} label={data[this.uniqueId]} disabled={node.disabled === true}></Radio>}
              <span class="el-icon-folder wrap-tree-node__icon"></span>
              <span>{node.label}</span>
            </span>);
        };
      }
    },
    findNode(id, array) {
      for (let i = 0; i < array.length;i++) {
        if (array[i][this.uniqueId] === id) {
          return array[i];
        }
        if (array[i].children && array[i].children.length) {
          return this.findNode(id, array[i].children);
        }
      }
    },
    getNodes() {
      if (!this.showCheckbox) {
        return this.radioNode;
      }
      let tree = this.$refs.tree || this.$refs.searchTree;
      let nodes = tree && tree.getCheckedNodes(this.getLeafOnly);
      console.log('getNodes', nodes);
      return nodes;
    },
    getCheckedNodes() {
      return this.currentNodes;
    },
    filterNode(value, data) {
      if (!value) return true;
      return data[this.showName].indexOf(value) !== -1;
    },
    checkChange(...value) {
      console.log('checkChange');
      if (!this.showCheckbox) {
        this.currentNodes = [this.getNodes()];
      } else {
        this.asyncChangeCurrentNodes();
      }
      this.$emit('check-change', ...value);
    },
    nodeClick(...value) {
      this.$emit('node-click', ...value);
    },
    cancelCheck(node) {
      if (!this.showCheckbox) {
        this.radio = '';
        this.radioNode = {};
        this.currentNodes = [];
      } else {
        if (this.myDefaultCheckedKeys && this.myDefaultCheckedKeys.length) {
          // 回显节点中删除该节点
          for (let i = 0;i < this.myDefaultCheckedKeys.length;i++) {
            if (this.myDefaultCheckedKeys[i] === node[this.uniqueId]) {
              let arr = this.myDefaultCheckedKeys;
              arr.splice(i, 1);
              this.myDefaultCheckedKeys = arr;
              break;
            }
          }
        }
        // 树节点中取消该节点选中
        this.$refs.tree && this.$refs.tree.setChecked(node[this.uniqueId], false);
        // 已选节点中删除该节点
        for (let i = 0;i < this.currentNodes.length;i++) {
          if (this.currentNodes[i][this.uniqueId] === node[this.uniqueId]) {
            let arr = this.currentNodes;
            arr.splice(i, 1);
            this.currentNodes = arr;
            break;
          }
        }
      }
    },
    $_handleRadio(value) {
      this.radio = value;
      let node = {};
      const tree = this.$refs.tree || this.$refs.searchTree;
      try {
        node = tree && tree.getNode(value).data || {};
      } catch (e) {
        console.log(e);
      }
      this.radioNode = node;
      this.currentNodes = [node];
      this.$emit('check-change', node);
    },
    checkAll() {
      if (this.$refs.tree && this.$refs.tree.store) {
        const store = this.$refs.tree.store;
        const traverse = (node) => {
          if (node.data && node.data[this.uniqueId] && node.data[this.showName] && !node.data.disabled) {
            this.$refs.tree.setChecked(node.data[this.uniqueId], true);
          }
          if (node.childNodes) {
            node.childNodes.forEach((cNode) => {
              traverse(cNode);
            });
          }
        };
        if (this.isSearchCheckAll) {
          if (this.searchData && this.searchData.length) {
            this.searchData.forEach(node => {
              if (node.data && node.data[this.uniqueId] && node.data[this.showName] && !node.data.disabled) {
                this.$refs.tree.setChecked(node.data[this.uniqueId], true);
              }
            });
          } else {
            traverse(this.searchData);
          }
        } else {
          traverse(store.root);
        }
        // this.currentNodes = result;
      }
    },
    clear() {
      const arr = this.currentNodes;
      arr.forEach(item => {
        this.$refs.tree.setChecked(item[this.uniqueId], false);
      });
      this.currentNodes = [];
      this.myDefaultCheckedKeys = [];
    },
    setDefaultCheck({store, data}) {
      if (this.showCheckbox) {
        this.$nextTick(() => {
          this.asyncChangeCurrentNodes();
        });
      } else if (!this.setRadioDefault) {
        if (this.lazy && this.defaultCheckedNodes && this.defaultCheckedNodes.length) {
          this.radio = this.defaultCheckedNodes[0][this.uniqueId];
          this.radioNode = this.defaultCheckedNodes[0];
          this.currentNodes = [this.defaultCheckedNodes[0]];
          this.setRadioDefault = true;
          return;
        }
        if (!store && data && data.length && this.myDefaultCheckedKeys && this.myDefaultCheckedKeys[0]) {
          data.forEach(item => {
            if (item[this.uniqueId] === this.myDefaultCheckedKeys[0]) {
              this.radio = this.myDefaultCheckedKeys[0];
              this.radioNode = item;
              this.currentNodes = [item];
              this.setRadioDefault = true;
            }
          });
        } else if (store && this.myDefaultCheckedKeys && this.myDefaultCheckedKeys[0]) {
          if (store.nodesMap && store.nodesMap[this.myDefaultCheckedKeys[0]]) {
            let node = store.nodesMap[this.myDefaultCheckedKeys[0]].data;
            this.radio = this.myDefaultCheckedKeys[0];
            this.radioNode = node;
            this.currentNodes = [node];
            this.setRadioDefault = true;
          }
        }
      }
    },
    setCheckedKeys(keys) {
      if (this.$refs.tree) {
        this.$refs.tree.setCheckedKeys(keys);
        this.currentNodes = this.getNodes();
      }
    }
  },
  computed: {
    filterCheckNodes() {
      if (this.showCheckbox) {
        let arr = this.currentNodes.filter((item) => {
          return item[this.showName] && (item[this.showName].indexOf(this.filterCheckText) !== -1);
        });
        if (this.renderChecked && typeof this.renderChecked === 'function') {
          return this.renderChecked(arr);
        }
        return arr;
      } else {
        return this.currentNodes;
      }
    }
  },
  watch: {
    filterUncheckText(val) {
      if (this.filterHandle) {
        this.filterHandle(val, (data) => {
          this.loadSearchData = data;
        });
        return;
      }
      if (this.$refs.tree && this.$refs.tree.store) {
        const store = this.$refs.tree.store;
        const filteredNode = [];
        const traverse = (node) => {
          if (node.data && node.data[this.uniqueId] && node.data[this.showName]) {
            if (this.filterNode(val, node.data)) {
              filteredNode.push(node);
            }
          }
          if (node.childNodes) {
            node.childNodes.forEach((cNode) => {
              traverse(cNode);
            });
          }
        };
        traverse(store.root);
        this.searchData = filteredNode;
      }
      this.$refs.tree.filter(val);
    },
    data: {
      handler() {
        this.$nextTick(() => {
          this.initDefaultCheck();
          if (this.$refs.tree && this.$refs.tree.store) {
            this.searchData = this.$refs.tree.store.root;
          }
        });
      }
    },
    defaultCheckedKeys: {
      handler() {
        if (!(this.defaultCheckedNodes && this.defaultCheckedNodes.length)) {
          this.myDefaultCheckedKeys = this.defaultCheckedKeys;
          this.$nextTick(() => {
            this.initDefaultCheck();
          });
        }
      },
      immediate: true
    },
    defaultCheckedNodes: {
      handler() {
        this.$nextTick(() => {
          this.initDefaultCheckedNodes();
        });
      },
      immediate: true
    }
  }

};
</script>
