# Source: algorithm/predecessors.js

    import flatten from 'lodash/fp/flatten'
    import uniq from 'lodash/fp/uniq'
    import * as Graph from '../graph'
    import * as Node from '../node'

    /**
     * Return all predecessors of a node or port, until a given subset.
     * @param {Location|Array<Location>} node Look for predecessors of this location(s).
     * @param {Predicate} predicate A predicate function (Node -> Boolean) that decides whether a node should
     * be included in the predecessor chain (true) or if it should be left out (false).
     * @param {Portgraph} graph The graph
     * @returns {Array<Node>} The nodes between the input node and `other` without both inputs.
     */

    export function predecessorsUntil (locs, predicate, graph) {
      if (!Array.isArray(locs)) return predecessorsUntil([locs], predicate, graph)
      if (locs.length === 0) return []
      const preds = flatten(locs.map((l) => Graph.predecessors(l, graph)))
        .map((n) => Graph.node(n, graph))
        .filter(predicate)
      return uniq(preds.concat(predecessorsUntil(preds, predicate, graph)))
    }

    /**
     * Return all predecessors of a node or port, until a given subset.
     * @param {Location|Array<Location>} node Look for predecessors of this location(s).
     * @param {Node|Array<Node>} other A node or an array of node indicating where to stop
     * @param {Portgraph} graph The graph
     * @returns {Array<Node>} The nodes between the input node and `other` without both inputs.
     */
    export function predecessorsUpTo (locs, other, graph) {
      if (!Array.isArray(other)) return predecessorsUpTo(locs, [other], graph)
      return predecessorsUntil(locs, (n) => !other.some(Node.equal(n)), graph)
    }

    /**
     * Return all predecessors of a node or port.
     * @param {Location|Array<Location>} node Look for predecessors of this location(s).
     * @param {Portgraph} graph The graph
     * @returns {Array<Node>} The preceeding nodes between of the input node (without the input node).
     */
    export const predecessors = (locs, graph) => predecessorsUntil(locs, () => true, graph)