filter.js

import {
  List
} from 'immutable';

import {
  deepMapOutwards
} from './map';

import {
	asList,
	isLeaf,
	pick
} from './utils';

/**
 * @module filter
 */

/**
 * Once fully applied, this iterates through nodes in the provided tree, passing them through a `filter` function.
 * Only nodes which return a truthy value from the `filter` function will be present in the modified tree.
 * Nodes are processed branch by branch in the order that Immutable maps through the child iterables, outwards from the root node to leaf nodes.
 * Sibling nodes are processed in the order that Immutable iterates through collections.
 * 
 * @param {Filterer} filterer The function to be called for each node in the tree, the results of which will be used to create the modified tree.
 * @param {ChildPath} [childPath=null] An `Array` or `List` of keys indicating where to find each node's children from within each node.
 * @return {InputFunction} A partially applied function which accepts a single tree `Iterable`, and returns the modified tree `Iterable`.
 */

function deepFilter(filterer, childPath=null) {
  childPath = asList(childPath);
  return (tree) => tree.update(deepMapOutwards((item, nodePath) => {
    return isLeaf(item, childPath)
      ? item
      : item.updateIn(childPath, kids => {
        return kids.filter((kid, kidKey) => filterer(kid, nodePath.push(kidKey), tree));
      });
  }, childPath));
}

export {
  deepFilter
}