/*
 * 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.
 */

// -*- C++ -*-

#include <iostream>

template <typename T, typename W>
ostream&
operator<<(ostream& ostr, const stl_graph<T,W>& g)
{
    typedef stl_graph<T,W> Graph;
    
    ostr << "{" << endl;
    
    node_map<int> nodes(g.topology());
    ostr << "    " << "{";
    if (g.n_size() == 0)
	ostr << "}" << endl;
    else {
	ostr << endl;
	typename Graph::const_node_iterator n = g.n_begin();
	typename Graph::const_node_iterator end = g.n_end();
	while (n != end) {
	    nodes[*n] = n->id();
	    ostr << "        " << nodes[*n]
		 << "\t" << g.value(*n) << ";" << endl;
	    ++n;
	}
	ostr << "    " << "}" << endl;
    }
    
    edge_map<int> edges(g.topology());
    ostr << "    " << "{";
    if (g.e_size() == 0)
	ostr << "}" << endl;
    else {
	ostr << endl;
	typename Graph::const_edge_iterator e = g.e_begin();
	typename Graph::const_edge_iterator end = g.e_end();
	int j = 1;
	while (e != end) {
	    edges[*e] = j;
	    ostr << "        " << edges[*e]
		 << "\t" << g.weight(*e) << ";" << endl;
	    ++e;
	    ++j;
	}
	ostr << "    " << "}" << endl;
    }
    
    ostr << "    " << "{";
    if (g.e_size() == 0)
	ostr << "}" << endl;
    else {
	ostr << endl;
	typename Graph::const_edge_iterator e = g.e_begin();
	typename Graph::const_edge_iterator end = g.e_end();
	while (e != end) {
	    ostr << "        " << edges[*e]
		 << "\t" << nodes[e->source()]
		 << "\t" << nodes[e->target()] << ";" << endl;
	    ++e;
	}
	ostr << "    " << "}" << endl;
    }
    
    ostr << "}";
    return ostr;
}

///////////////////////////////////////////////////////////////////////////
//
// template <typename T, typename W>
// istream &
// operator >>(ostream &istr, stl_graph<T,W> &g)
//
// Reads a graph from the istream of the form:
//
// {
// 	{
//		1  N1;
//		2  N2;
//		...
//		n  Nn;
// 	}
//	{
//		1  E1;
//		2  E2;
//		...
//		m  Em;
//	}
//	{
//		1  Nx Ny;
//		1  Nu Nv;
//		...
//		m  Ns Nt;
//	}
// }
//
///////////////////////////////////////////////////////////////////////////

template <typename T, typename W>
istream&
operator>>(istream& istr, stl_graph<T,W>& g)
{
    typedef stl_graph<T,W> Graph;
    char c;
    
    istr >> c;			// graph open brace
    
    std::map<int, Graph::node> node_id_map;
    int node_id;
    T node_data;
    istr >> c;			// nodes open brace
    istr >> c;			// potential nodes close brace
    while (c != '}') {
	istr.putback(c);
	istr >> node_id;	// node id
	istr >> node_data;	// node data
	istr >> c;		// semicolon
	node_id_map[node_id] = g.add_node(node_data);
	istr >> c;		// potential nodes close brace
    }
    
    std::map<int, W> edge_id_map;
    int edge_id;
    W edge_data;
    istr >> c;			// edges open brace
    istr >> c;			// potential edges close brace
    while (c != '}') {
	istr.putback(c);
	istr >> edge_id;	// edge id
	istr >> edge_data;	// edge data
	istr >> c;		// semicolon
	edge_id_map[edge_id] = edge_data;
	istr >> c;		// potential edges close brace
    }
    
    int n1, n2;
    istr >> c;			// links open brace
    istr >> c;			// potential links close brace
    while (c != '}') {
	istr.putback(c);
	istr >> edge_id;	// edge id
	istr >> n1 >> n2;	// source id & target id
	istr >> c;		// semicolon
	g.add_edge(node_id_map[n1], node_id_map[n2],
		   edge_id_map[edge_id]);
	istr >> c;		// potential links close brace
    }
    
    istr >> c;			// graph close brace
    
    return istr;
}
