/*
 * Copyright (c) 1999 Johnny C. Lam.
 * All rights reserved.
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  The author makes no representations
 * about the suitability of this software for any purpose.  It is
 * provided "as is" without express or implied warranty.
 */

#include <iostream>
#include <iterator_utility>
#include <stack>

/*
 * Write the subtree below the given root, exclusive.
 */
template <class Tree>
void
WriteTreeTopology(ostream& ostr, const Tree& tree,
		  const typename graph_traits<Tree>::node_type& root,
		  string prefix, const string& padding)
{
    typedef typename graph_traits<Tree>::node_type node_type;
    typedef typename node_type::adj_nodes_iterator adj_nodes_iterator;

    adj_nodes_iterator a = root.adj_nodes_begin();
    adj_nodes_iterator end = root.adj_nodes_end();

    if (a == end)
	return;
    prefix += padding;
    while (successor(a) != end) {
	ostr << prefix << "|--" << tree.value(*a) << endl;
	WriteTreeTopology(ostr, tree, *a, prefix + "|  ", padding);
	++a;
    }
    ostr << prefix << "`--" << tree.value(*a) << endl;
    WriteTreeTopology(ostr, tree, *a, prefix + "   ", padding);
}

template <class Tree>
void
WriteRootedTree(ostream& ostr, const Tree& tree,
		const typename graph_traits<Tree>::node_type& root)
{
    typedef typename graph_traits<Tree>::node_type node_type;
    typedef typename graph_traits<Tree>::edge_type edge_type;
    typedef typename graph_traits<Tree>::weight_type weight_type;
    typedef typename node_type::adj_edges_iterator adj_edges_iterator;
    
    node_map<int> ids(tree.topology());
    int index = 1;
    
    ostr << "{" << endl;
    
    // parent of 0 indicates node is root
    ids[root] = index++;
    ostr << "\t" << ids[root]
	 << "\t" << 0
	 << "\t" << 0
	 << "\t" << tree.value(root)
	 << endl;

    /*
     * This seemingly useless step to reverse the order of the edges
     * is to make this function write the same output order as 
     * WriteTreeTopology.
     */    
    adj_edges_iterator adj = root.adj_edges_begin();
    adj_edges_iterator adj_end = root.adj_edges_end();
    std::stack<edge_type> reverser;
    while (adj != adj_end) {
	reverser.push(*adj);
	++adj;
    }
    std::stack<edge_type> qu;
    while (!reverser.empty()) {
	qu.push(reverser.top());
	reverser.pop();
    }
    
    while (!qu.empty()) {
	edge_type e = qu.top();
	node_type u = e.target();
	qu.pop();
	
	ids[u] = index++;
	ostr << "\t" << ids[u]
	     << "\t" << ids[e.source()]
	     << "\t" << tree.weight(e)
	     << "\t" << tree.value(u)
	     << endl;
	adj = u.adj_edges_begin();
	adj_end = u.adj_edges_end();
	while (adj != adj_end) {	// the same seemingly useless step.
	    reverser.push(*adj);
	    ++adj;
	}
	while (!reverser.empty()) {
	    qu.push(reverser.top());
	    reverser.pop();
	}
    }
    
    ostr << "}" << endl;
}
