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 ElTree from 'element-ui-for-gov/packages/tree';
import Store from 'element-ui-for-gov/src/utils/tree-store';

import SectionHeader from './section-header';
import SelectedList from './selected-list';

const prefix = 'el-user-picker';
export default {
  name: 'Transfer',
  inject: ['handleChangeUser', 'clearChecked', 'nodeKey', 'setTreeInstance'],
  props: {
    treeProps: Object,
    fieldNames: Object,
    grid: Object,
    checkedUsers: Array,
    filterNodeMethod: Function,
    defaultChecked: Array,
    renderChecked: Function,
    renderCheckedItem: Function,
    selectPanelButton: Function,
    radio: Boolean,
    isSearchCheckAll: Boolean,
    height: Number,
    checkOnClickNode: Boolean
  },
  components: {ElRow, ElCol, ElButton, ElTree, SectionHeader, SelectedList},
  data() {
    return {
      treeData: [],
      store: null,
      totalData: [],
      searchData: [],
      prevChecked: [],
      searchWrapHeight: 0
    };
  },
  created() {
    const {lazy, loadData, children, disabled} = this.treeProps;
    const {fieldNames} = this;
    this.store = new Store({
      key: this.nodeKey,
      label: data => data[fieldNames.parent] || data[fieldNames.userName],
      isLeaf: (data) => !!data[fieldNames.userName],
      hideCheckbox: 'hideCheckbox',
      children: children || 'children',
      disabled: disabled || 'disabled',
      data: []
    });
    !lazy ? loadData().then((data) => {
      this.store.initData(data);
      this.treeData = this.store.data;
      this.totalData = this.treeData;
      this.searchData = this.treeData;
      this.setDefaultChecked(this.defaultChecked);
    }) : this.setDefaultChecked(this.defaultChecked);
  },

  mounted() {
    this.setTreeInstance(this.treeProps.key, this);
    this.initFilterResize();
  },

  watch: {
    defaultChecked(users) {
      this.$nextTick(() => {
        this.setDefaultChecked(users);
      });
    },
    checkedUsers(arr) {
      let nodes = [];
      arr.forEach(item => {
        const cache = this.store.getNodes(item);
        nodes = nodes.concat(cache);
      });
      this.prevChecked = [].concat(nodes);
      // console.log('selected nodes: ', nodes);
      this.$nextTick(() => {
        this.setCheckedNodes(nodes);
      });
    }
  },
  methods: {
    initFilterResize() {
      const filterWrapper = this.$el.querySelector('.custom-filter-wrapper');
      if (filterWrapper) {
        try {
          const resizeObserver = new ResizeObserver(entries => {
            for (let entry of entries) {
              if (entry.contentRect.height > 0) {
                this.searchWrapHeight = filterWrapper.offsetHeight;
              }
            }
          });
          resizeObserver.observe(filterWrapper);
        } catch (e) {
          this.$nextTick(() => {
            this.searchWrapHeight = filterWrapper.offsetHeight;
          });
        }
      }
    },
    setDefaultChecked(keys) {
      // console.log(ids);
      let users = [];
      keys.forEach(user => {
        // console.log(user);
        let nodes = typeof user === 'object' ? [{data: user}] : this.store.getNodesByKey(user);
        if (nodes.length) {
          users.push(nodes[0].data);
        }
      });
      this.handleChangeUser(users);
    },
    handleCheck(node, {checkedNodes}) {
      if (this.radio) {
        let users = [];
        if (checkedNodes.includes(node)) {
          users = [node.data];
        }
        this.handleChangeUser(users);
      } else {
        const deleteArr = this.store.difference(this.prevChecked, checkedNodes.filter(node => node.isLeaf));
        // console.log(deleteArr);
        const users = checkedNodes.filter(node => node.isLeaf).map(item => item.data);

        const deleteUsers = deleteArr.filter(node => node.isLeaf).map(item => item.data);
        this.handleChangeUser(users, deleteUsers);
      }

    },
    getCheckedNodes() {
      const nodes = this.$refs['tree'].getCheckedNodes();
      const users = nodes.filter(node => node.isLeaf).map(item => item.data);
      if (this.radio) {
        if (users && users.length) {
          this.handleChangeUser(users, []);
        }
      } else {
        this.handleChangeUser(users, []);
      }
    },
    checkAll() {
      console.log('checkAll');
      const {checkAllMethod} = this.treeProps;
      if (checkAllMethod) {
        checkAllMethod(this, (users) => {
          this.handleChangeUser(users);
        });
      } else {
        const users = [];
        const traverse = (arr) => {
          arr.forEach(item => {
            if (item.isLeaf && !item.disabled) {
              users.push(item.data);
            } else if (item.children) {
              traverse(item.children);
            }
          });
        };
        if (this.isSearchCheckAll) {
          traverse(this.searchData);
        } else {
          traverse(this.totalData);
        }
        this.handleChangeUser(users);
      }
    },
    setCheckedNodes(nodes) {
      this.$refs['tree'].setCheckedNodes(nodes);
    },
    filter(value) {
      const filteredData = [];
      const traverse = (arr) => {
        arr.forEach(item => {
          if (this.filterNodeMethod(value, item, item)) {
            filteredData.push(item);
          } else if (item.children) {
            traverse(item.children);
          }
        });
      };
      traverse(this.totalData);
      this.searchData = filteredData;
      this.$refs['tree'].filter(value);
    },
    setTreeData(data) {
      this.store.initData(data, this.treeProps.lazy);
      this.treeData = this.store.data;
      this.searchData = this.store.data;
      this.setDefaultChecked(this.defaultChecked);
    },

    bfsRegisterNode(data, current) {
      const getChildren = (node) => {
        const children = this.treeProps.children || 'children';
        return typeof children === 'function' ? children(node) : node[children];
      };
      const queue = [{root: true, children: data}];
      const queueNode = [current];
      while (queue.length) {
        const head = queue.shift();
        const parent = queueNode.shift();
        if (Array.isArray(head.children)) {
          for (let i = 0, len = head.children.length; i < len; i++) {
            const node = this.store.registerNode(head.children[i]);
            node.parent = parent;
            parent.children.push(node);
            queue.push({
              ...head.children[i],
              children: getChildren(head.children[i])
            });
            queueNode.push(node);
          }
        }
      }
    },

    bfsTravel(node, cb) {
      const queue = [node];
      while (queue.length) {
        const head = queue.shift();
        cb && cb(head);
        if (Array.isArray(head.children)) {
          for (let i = 0; i < head.children.length ; i++) {
            queue.push(head.children[i]);
          }
        }
      }
    },

    loadDataAsync(node, resolve, isCheck) {
      const {loadDataAsync} = this.treeProps;
      // console.log('load', node);
      loadDataAsync(node.data ? node.data : node, data => {
        // console.log(data);
        if (data && data.length > 0) {
          const current = !node.parent ? {children: []} : node.data;
          this.bfsRegisterNode(data, current);
          if (!node.parent) {
            this.store.data = current.children;
            this.totalData = this.store.data;
            this.searchData = this.store.data;
          }

          if (!isCheck) {
            if (this.radio) {
              if (this.checkedUsers && this.checkedUsers.length && this.defaultChecked.length) {
                if (this.checkedUsers[0].id && this.checkedUsers[0].id === this.defaultChecked[0].id) {
                  this.setDefaultChecked([this.defaultChecked[0]]);
                }
              }
            } else {
              const sList = [];
              this.checkedUsers.forEach((node) => {
                this.defaultChecked.forEach((nodeD) => {
                  if (nodeD.key && nodeD.key === node.key) {
                    sList.push(node);
                  }
                });
              });
              this.setDefaultChecked(sList);
            }
          } else {
            const selectList = [];
            this.bfsTravel(current, (node) => {
              if (!node.disabled && node.isLeaf) {
                selectList.push(node.key);
              }
            });
            this.defaultChecked.forEach((item) => {
              if (!selectList.includes(item)) {
                selectList.push(item);
              }
            });
            this.setDefaultChecked(selectList);
          }
          return resolve(current.children);
        } else {
          return resolve([]);
        }
      }, isCheck);
    }
  },

  render() {
    const {treeData, fieldNames, treeProps, checkedUsers, $slots, renderChecked, renderCheckedItem, selectPanelButton, height, checkOnClickNode} = this;
    return (<ElRow>
      <ElCol span={10}>
        <div class={`${prefix}__section-wrapper`}>
          <SectionHeader title="待选列表" />
          {$slots.filter && <div class="custom-filter-wrapper">{$slots.filter}</div> }
          <div class={`${prefix}__section-content`} style={{height: `${height ? height - this.searchWrapHeight - 1 : 464 - this.searchWrapHeight}px`}}>
            <ElTree ref="tree"
              lazy={treeProps.lazy}
              data={treeData}
              nodeKey="id"
              load={this.loadDataAsync}
              props={{
                hideCheckbox: 'hideCheckbox',
                isLeaf: item => item.isLeaf
              }}
              show-checkbox
              checkOnClickNode={checkOnClickNode}
              expand-on-check={treeProps.lazy}
              filterNodeMethod={this.filterNodeMethod}
              {...{
                on: {
                  // 'check-change': treeProps.lazy ? this.handleCheckChange : this.getCheckedNodes,
                  'node-expand': treeProps.lazy ? this.getCheckedNodes : () => {},
                  'check': this.handleCheck
                }
              }}
            />
          </div>
        </div>
      </ElCol>
      <ElCol span={4} class={`${prefix}__section-btns`}>
        {!this.radio && <ElButton {...{on: {click: this.checkAll}}}>全选<i class="el-icon-arrow-right"/></ElButton>}
        <br />
        <ElButton {...{on: {click: this.clearChecked}}}>清空已选</ElButton>
      </ElCol>
      <ElCol span={10}>
        <SelectedList height={this.height} checkedUsers={checkedUsers} label={fieldNames.userName} renderChecked={renderChecked} renderCheckedItem={renderCheckedItem} selectPanelButton={selectPanelButton} />
      </ElCol>
    </ElRow>);
  }
};
