// BreadthFirstOrder and its companion functions ended up not giving the
// right solution, but I'm leaving them here as a useful generic tree
// algorithm.
package day07

func BreadthFirstOrder(root *Node) []*Node {
	seen := make(map[rune]bool)
	return breadthFirstOrderR(root, seen)
}

func findTreeRoot(depMap map[rune]*Node) *Node {
	for _, node := range depMap {
		if len(node.Parents) == 0 {
			return node
		}
	}

	return nil
}

func breadthFirstOrderR(node *Node, seen map[rune]bool) []*Node {
	order := []*Node{}

	// handle root
	if len(node.Parents) == 0 {
		order = append(order, node)
		seen[node.Name] = true
	}

	// add children we haven't seen before
	for _, child := range node.Children {
		if _, ok := seen[child.Name]; !ok {
			order = append(order, child)
			seen[child.Name] = true
		}
	}

	// recurse
	for _, child := range node.Children {
		order = append(order, breadthFirstOrderR(child, seen)...)
	}

	return order
}