<template>
  <div class="el-transfer-panel">
    <p class="el-transfer-panel__header">
      <el-checkbox
        v-model="allChecked"
        @change="handleAllCheckedChange"
        :indeterminate="isIndeterminate"> 
        {{ title }}
        <span>{{ checkedSummary }}</span>
      </el-checkbox>
    </p>
    
    <div :class="['el-transfer-panel__body', hasFooter ? 'is-with-footer' : '']">
      <el-input
        class="el-transfer-panel__filter"
        v-model="query"
        size="small"
        :placeholder="placeholder"
        @mouseenter.native="inputHover = true"
        @mouseleave.native="inputHover = false"
        v-if="filterable">
        <i slot="prefix"
          :class="['el-input__icon', 'el-icon-' + inputIcon]"
          @click="clearQuery"
        ></i>
      </el-input>
      <el-scrollbar 
        :class="{ 'is-filterable': filterable }"
        class="el-transfer-panel__list"
        v-show="nodes.length > 0">
        <el-ztree
              class="select-ztree" 
              ref="tree"
              :setting="setting"
              :nodes="nodes" 
              @onCollapse="onCollapse"
              @onExpand="onExpand"
              @onClick="onClick"
              @onCheck="onCheck"
              @onCreated="handleCreated"
              />  
      </el-scrollbar>
      <!--<p
        class="el-transfer-panel__empty"
        v-show="hasNoMatch">{{ t('el.transfer.noMatch') }}</p>-->
      <p
        class="el-transfer-panel__empty"
        v-show="nodes.length === 0 && !hasNoMatch">{{ t('el.transfer.noData') }}</p>
    </div>
    <p class="el-transfer-panel__footer" v-if="hasFooter">
      <slot></slot>
    </p>
  </div>
</template>

<script>
  import ElCheckboxGroup from 'vue-element-plus/packages/checkbox-group';
  import ElCheckbox from 'vue-element-plus/packages/checkbox';
  import ElInput from 'vue-element-plus/packages/input';
  import Locale from 'vue-element-plus/src/mixins/locale';

  export default {
    mixins: [Locale],

    name: 'ElTransferPanel',

    componentName: 'ElTransferPanel',

    components: {
      ElCheckboxGroup,
      ElCheckbox,
      ElInput,
      OptionContent: {
        props: {
          option: Object
        },
        render(h) {
          const getParent = vm => {
            if (vm.$options.componentName === 'ElTransferPanel') {
              return vm;
            } else if (vm.$parent) {
              return getParent(vm.$parent);
            } else {
              return vm;
            }
          };
          const panel = getParent(this);
          const transfer = panel.$parent || panel;
          return panel.renderContent
            ? panel.renderContent(h, this.option)
            : transfer.$scopedSlots.default
              ? transfer.$scopedSlots.default({ option: this.option })
              : <span>{ this.option[panel.labelProp] || this.option[panel.keyProp] }</span>;
        }
      }
    },

    props: {
      renderContent: Function,
      placeholder: String,
      title: String,
      filterable: Boolean,
      format: Object,
      filterMethod: Function,
      defaultChecked: Array,
      props: Object,
      // 参考 ztree 设置
      setting: {
        type: Object,
        default: function() {
          return {};
        }
      },
      // 参考 ztree 设置
      nodes: {
        type: Array,
        default: function() {
          return [];
        }
      }
    },

    data() {
      return {
        allChecked: false,
        query: '',
        inputHover: false,
        checkChangeByUser: true,
        ztreeObj: '',
        curData: [],
        checkCount: 0,
        nocheckCount: 0,
        isIndeterminate: true,
        expasnds: []
      };
    },

    watch: {
      curData(val, oldVal) {
        this.updateAllChecked();
        if (this.checkChangeByUser) {
          const movedKeys = val.concat(oldVal)
            .filter(v => val.indexOf(v) === -1 || oldVal.indexOf(v) === -1);
          this.$emit('checked-change', val, movedKeys);
        } else {
          this.$emit('checked-change', val);
          this.checkChangeByUser = true;
        }
      },
      nodes(val) {
        this.resetDeepObj(val, this.keyProp, this.expasnds);
        this.checkChangeByUser = false;
        this.curData = [];
      },

      checkableData() {
        this.updateAllChecked();
      },

      defaultChecked: {
        immediate: true,
        handler(val, oldVal) {
          // if (oldVal && val.length === oldVal.length &&
          //   val.every(item => oldVal.indexOf(item) > -1)) return;
          // const checked = [];
          // const checkableDataKeys = this.checkableData.map(item => item[this.keyProp]);
          // val.forEach(item => {
          //   if (checkableDataKeys.indexOf(item) > -1) {
          //     checked.push(item);
          //   }
          // });
          // this.checkChangeByUser = false;
          // this.checked = checked;
        }
      },
      query(val) {
        if (val !== '') {this.$refs.tree.fuzzySearch(val, true, true);}
      }
    },

    computed: {
      // filteredData() {
      //   return this.nodes.filter(item => {
      //     if (typeof this.filterMethod === 'function') {
      //       return this.filterMethod(this.query, item);
      //     } else {
      //       const label = item[this.labelProp] || item[this.keyProp].toString();
      //       return label.toLowerCase().indexOf(this.query.toLowerCase()) > -1;
      //     }
      //   });
      // },

      checkableData() {
        // return this.filteredData.filter(item => !item[this.disabledProp]);
      },

      checkedSummary() {
        return `${ this.checkCount }/${ this.checkCount + this.nocheckCount}`;
      },

      hasNoMatch() {
        return this.query.length > 0; // && this.filteredData.length === 0;
      },

      inputIcon() {
        return this.query.length > 0 && this.inputHover
          ? 'circle-close'
          : 'search';
      },

      labelProp() {
        return this.props.label || 'label';
      },

      keyProp() {
        return this.props.key || 'key';
      },

      disabledProp() {
        return this.props.disabled || 'disabled';
      },

      hasFooter() {
        return !!this.$slots.default;
      }
    },

    methods: {
      updateAllChecked() {
        this.updateSummary();
        this.allChecked = this.checkCount === (this.checkCount + this.nocheckCount) && this.checkCount > 0;
        if (this.allChecked) {
          this.isIndeterminate = false;
        }
      },

      handleAllCheckedChange(value) {
        var nodes = this.ztreeObj.getNodes();
        nodes.forEach(item => {
          if (item.chkDisabled && item.children) {
            item.children.forEach(child => {
              this.ztreeObj.checkNode(child, value, true, true);
            });
          }
          this.ztreeObj.checkNode(item, value, true, true);
        });
        this.isIndeterminate = false;
      },

      clearQuery() {
        if (this.inputIcon === 'circle-close') {
          this.query = '';
        }
      },
      onCollapse(event, treeId, treeNode) {
        var val = treeNode[this.keyProp];
        var index = this.expasnds.indexOf(val);
        if (index >= 0 && !treeNode.open) {
          this.expasnds.splice(index, 1);
        }
      },
      onExpand(event, treeId, treeNode) {
        var val = treeNode[this.keyProp];
        var bExits = this.expasnds.indexOf(val) >= 0;
        if (!bExits && treeNode.open) {
          this.expasnds.push(val);
        }
      },
      onClick(evt, treeId, treeNode) {
  
      },
      onCheck(evt, treeId, treeNode) {
        var checkedNodes = this.ztreeObj.getCheckedNodes(true).filter(item => {return !item.children;}).map(item => {return item[this.keyProp];});
        this.curData = checkedNodes;
  
      },
      handleCreated(ztreeObj) {
        this.ztreeObj = ztreeObj;
        ztreeObj.expandNode(ztreeObj.getNodes()[0], true);
        this.curData = [];
        ztreeObj.setting.callback.beforeClick = ((treeId, treeNode)=>{
          return false;
        });
      },
      updateSummary() {
        if (this.ztreeObj) {
          this.checkCount = this.ztreeObj.getCheckedNodes(true).length;
          this.nocheckCount = this.ztreeObj.getCheckedNodes(false).length;
          this.isIndeterminate = this.checkCount > 0;
        }
      },
      resetDeepObj(data, key, settingData) {
        for (let i = 0;i < data.length;i++) {
          let item = data[i];
          var bExits = settingData.indexOf(item[key]) >= 0;
          if (bExits) {
            item.open = true;
          }
          if (item.children) {
            this.resetDeepObj(item.children, key, settingData);
          }
        }
      }
    }
  };
</script>
