import { ref, watch } from 'vue';
import { isNil, isUndefined } from 'lodash-es';
import { concat } from '../_util/utils';

let uid = 1;
const getUid = () => {
  return uid++;
};
var useData = _ref => {
  let {
    props,
    emit
  } = _ref;
  const nodeList = new Map();
  const allKeys = ref([]);
  watch(allKeys, () => {
    emit('update:nodeList', nodeList);
  }, {
    immediate: true
  });
  const transformNode = (item, indexPath, level) => {
    const value = item[props.valueField];
    const label = item[props.labelField];
    const children = item[props.childrenField];
    const hasChildren = !!(Array.isArray(children) && children.length);
    let isLeaf;
    if (!isNil(item.isLeaf)) {
      isLeaf = item.isLeaf;
    } else if (hasChildren) {
      isLeaf = false;
    } else if (props.remote) {
      isLeaf = false;
    } else {
      isLeaf = true;
    }
    let copy;
    const newItem = {
      origin: item,
      prefix: item.prefix,
      suffix: item.suffix,
      disabled: item.disabled,
      selectable: item.selectable,
      checkable: item.checkable,
      draggable: isUndefined(item.draggable) ? true : item.draggable,
      value,
      label,
      isLeaf,
      children,
      hasChildren,
      level,
      indexPath: [...indexPath, value]
    };
    if (!nodeList.get(value)) {
      // Object.assign比解构快很多
      copy = Object.assign({}, newItem);
      copy.isExpanded = ref(false);
      copy.isIndeterminate = ref(false);
      copy.isChecked = ref(false);
    } else {
      copy = nodeList.get(value);
      Object.assign(copy, newItem);
    }
    copy.uid = getUid();
    return copy;
  };
  const flatNodes = function () {
    let nodes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
    let children = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
    let indexPath = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
    let level = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
    let parent = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : undefined;
    return nodes.reduce((res, node) => {
      const copy = transformNode(node, indexPath, level);
      // 收集 parent
      copy.parent = parent;
      // 扁平化
      nodeList.set(copy.value, copy);
      res.push(copy.value);
      children.push(copy);
      if (copy.hasChildren) {
        const children = [];
        const keys = flatNodes(copy.children, children, copy.indexPath, level + 1, copy);
        copy.children = children;
        copy.childrenPath = keys;
        // 比 Array.concat 快
        concat(res, keys);
      }
      return res;
    }, []);
  };
  watch([() => props.data], () => {
    allKeys.value = flatNodes(props.data);
  }, {
    immediate: true,
    deep: true
  });
  return {
    nodeList,
    allKeys
  };
};

export { useData as default };
