// -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; -*-
////////////////////////////////////////////////////////////////////
//
// $Id: graph.cpp 844 2011-10-13 22:05:28Z Sebastian Kupferschmid $
//
////////////////////////////////////////////////////////////////////

#include "graph.h"
#include "edge.h"
#include "node.h"
#include "options.h"

#include <cstdio>
#include <climits>
#include <cassert>

using namespace std;

Graph::Graph() : 
    nodes(),
    edges(), 
    targets(),
    initial(NULL)
{}

Node* Graph::getNode(int id) {
    Node* tmp = new Node(id);
    pair<map_t::iterator, bool> pos = nodes.insert(make_pair(id, tmp));
    if (!pos.second) {
	delete tmp;
    } 
    return pos.first->second;
}

vector<Node*>& Graph::getTargets() {
    return targets;
}

void Graph::labelNode(int node, const char* label) {
    getNode(node)->label = label;
}

void Graph::addEdge(int from, int to) {
    Edge* edge = new Edge(getNode(from), getNode(to));
    edges.push_back(edge);
}

void Graph::setTarget(int node) {
    Node* target = getNode(node);
    target->distance = 0;
    targets.push_back(target);
}

void Graph::setInitial(int node) {
    initial = getNode(node);
}

void Graph::show(ostream& o, const option& opts) const {
    bool first = true;
    for (map_t::const_iterator it = nodes.begin(); it != nodes.end(); ++it) {
	Node* node = it->second;
	if (opts.include_dead_end || node->distance < INT_MAX) {
	    if (!first) {
		o << endl;		
	    }
	    first = false;
	    o << *node << " : " << node->distance;
	} 
    }
}

void Graph::show(const char* filename, const option& opts) const {
    FILE* file = fopen(filename, "a");
    bool first = true;
    for (map_t::const_iterator it = nodes.begin(); it != nodes.end(); ++it) {
	Node* node = it->second;
	if (opts.include_dead_end || node->distance < INT_MAX) {
	    if (!first) {
		fprintf(file, "\n");
	    }
	    first = false;
	    fprintf(file, "%s : %d", node->label.c_str(), node->distance);
	} 
    }
    fclose(file);
}

void Graph::dump(ostream& o) const {
    for (map_t::const_iterator it = nodes.begin(); it != nodes.end(); ++it) {
	const Node* node = it->second;
	if (node->distance == 0) {
	    o << node->id << " [peripheries=3];";
	}
	o << node->id << " [label=\"" << node->label<< "\"];" << endl;
	if (node->id == 0) {
	    o << node->id << " [peripheries=2];";
	}
    }
    for (int i = 0; i < edges.size(); i++) {
	const Edge* edge = edges[i];
	o << edge->from->id << " -> " << edge->to->id << ";" << endl;
    }
}

ostream& operator<<(std::ostream& o, const Graph& g) {
    for (int i = 0; i < g.edges.size(); i++) {
	o << *g.edges[i] << endl;
    }
    return o;
}

