import { deepClone } from './tools';

const getTreeDepth = function(node) {
  if (undefined === node || null == node) {
    return 0;
  }
  // 返回结果
  let r = 0;
  // 树中当前层节点的集合。
  let currentLevelNodes = [node];
  // 判断当前层是否有节点
  while (currentLevelNodes.length > 0){
    // 当前层有节点，深度可以加一。
    r++;
    // 下一层节点的集合。
    let nextLevelNodes = new Array();
    // 找到树中所有的下一层节点，并把这些节点放到 nextLevelNodes 中。
    for (let i = 0; i < currentLevelNodes.length; i++) {
      let e = currentLevelNodes[i];
      if (isHasChildren(e)) {
        nextLevelNodes = nextLevelNodes.concat(e.children);
      }
    }
    // 令当前层节点集合的引用指向下一层节点的集合。
    currentLevelNodes = nextLevelNodes;
  }
  return r;
};

const isHasChildren = function(node){
  let flag = false;
  if (node.children && node.children.length > 0) {
    flag = true;
  }
  return flag;
};

// 非递归遍历树
const traverseTree = function(node, callback) {
  if (!node) {
    return;
  }
  let stack = [];
  stack.push(node);
  let tmpNode;
  while (stack.length > 0) {
    tmpNode = stack.pop();
    callback(tmpNode);
    if (tmpNode.children && tmpNode.children.length > 0) {
      for (let i = tmpNode.children.length - 1; i >= 0; i--) {
        stack.push(tmpNode.children[i]);
      }
    }
  }
};
// 对子节点进行搜索。
const searchEach = function(node, value, valueName){
  let depth = getTreeDepth(node);
  for (let i = 0; i < depth - 1; i++) {
    // 记录【删除不匹配搜索内容的叶子节点】操作的次数。
    // 如果这个变量记录的操作次数为0，表示树形结构中，所有的
    // 叶子节点(不包含只有根节点的情况)都匹配搜索内容。那么就没有必要再
    // 在循环体里面遍历树了.
    let spliceCounter = 0;

    // 遍历树形结构
    traverseTree(node, n=>{
      if (isHasChildren(n)) {
        let children = n.children;
        let length = children.length;

        // 找到不匹配搜索内容的叶子节点并删除。为了避免要删除的元素在数组中的索引改变，从后向前循环,
        // 找到匹配的元素就删除。
        for (let j = length - 1; j >= 0; j--) {
          let e3 = children[j];
          if (!isHasChildren(e3) && e3[valueName].indexOf(value) <= -1) {
            children.splice(j,1);
            spliceCounter++;
          }
        } // end for (let j = length - 1; j >= 0; j--)
      }
    }); // end this.traverseTree(node, n=>{

    // 所有的叶子节点都匹配搜索内容，没必要再执行循环体了。
    if (spliceCounter === 0) {
      break;
    }
  }
};

const search = function(nodeList, value, valueName){
  if (value === '') {
    return;
  }
  if (nodeList && nodeList.length > 0) {
    nodeList.forEach((n,i,a)=>{
      searchEach(n, value, valueName);
    });

    // 没有叶子节点的根节点也要清理掉
    let length = nodeList.length;
    for (let i = length - 1; i >= 0; i--) {
      let e2 = nodeList[i];
      if (!isHasChildren(e2) && e2[valueName].indexOf(value) <= -1) {
        nodeList.splice(i, 1);
      }
    }
  }
};

export const filterTree = function(treeData, value, valueName) {
  const data = deepClone(treeData);
  search(data, value, valueName);
  return data;
};
/**
 * 树中批量查找对象
 * @param {*} treeData
 * @param {*} values
 * @param {*} valueName
 * @param {*} isChildren
 */
export const findMultiTree = function(treeData, values, valueName, isChildren) {
  const data = deepClone(treeData);
  const results = [];
  const findItem = (list) => {
    (list || []).map(e => {
      const value = typeof valueName === 'function' ? valueName(e) : e[valueName];
      if (values.some(item => value === item)) {
        const item = deepClone(e);
        item.children = isChildren ?  item.children : undefined;
        results.push(item);
      }
      if (e.children && e.children.length > 0){
        findItem(e.children);
      }
    });
  };
  findItem(data);
  return results;
};

/**
 * 树中查找对象
 * @param {*} treeData
 * @param {*} value
 * @param {*} valueName
 * @param {*} childrenName
 */
export const findTree = function(treeData, value, valueName, childrenName = 'children') {
  let result = {};
  const findItem = (list) => {
    return list.some(e => {
      if (e[valueName] === value) {
        result = e;
        return true;
      } else {
        if (e[childrenName] && e[childrenName].length > 0){
          return findItem(e[childrenName]);
        }
      }
    });
  };
  findItem(treeData);
  return result;
};
/**
 * 树长度
 * @param {*} treeData
 */
export const treeLength = function(treeData) {
  let length = 0;
  const findItem = (list) => {
    (list || []).map(e => {
      length = length + 1;
      if (e.children && e.children.length > 0){
        findItem(e.children);
      }
    });
  };
  findItem(treeData);
  return length;
};

/**
 * 树转list
 * @param {*} treeData
 */
export const toList = function(treeData) {
  let result = [];
  const findItem = (list) => {
    (list || []).map(e => {
      const item = deepClone(e);
      delete item.children;
      result.push(item);
      if (e.children && e.children.length > 0){
        findItem(e.children);
      }
    });
  };
  findItem(treeData);
  return result;
};
/**
 * 将list进行分组生成一个2层的分组树
 * @param {*} list
 * @param {*} groupname
 * @param {*} varname
 */
export const convertList2Tree = (list, groupname, varname) => {
  const result = [];
  list.map(e => {
    let itemData = result.find(item => item[varname] === e[groupname]);
    if (itemData) {
      if (itemData.children) {
        itemData.children.push(e);
      } else {
        itemData.children = [e];
      }
    } else {
      let obj = {};
      obj[varname] = e[groupname];
      obj.children = [e];
      result.push(obj);
    }
  });
  return result;
};

export default {
  treeLength,
  toList
};
