#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

//File-backed weighted graph
class tomgraph {
private:
	void seek_to_line(int linenum);
public:
	void open(char *filename);
	bool exists(int nodeid);
	int node_count(void);
	int connection_count(void);
	bool is_connected(int nodea, int nodeb, int *weight);
	bool is_connected(int nodea, int nodeb);
	int get_connection_weight(int nodea, int nodeb);
	bool is_connected_bidir(int nodea, int nodeb);
private:
	ifstream graphfile; //The file that actually contains the graph info
};

//Seek to the beginning of the given (1-indexed) line number
void tomgraph::seek_to_line(int linenum){
	int t;
	string junkstring;
	graphfile.seekg (0, ios::beg);
	for (int t = 1; t < linenum; t++)
        std::getline(graphfile, junkstring);
}

//Nope, no error checking.
void tomgraph::open(char *filename) {
	graphfile.open(filename);
}

int tomgraph::node_count(void) {
	//Number of nodes (and therefore highest node id, nodes being 1-indexed) is the first line of the file
	int max;
	graphfile.seekg (0, ios::beg); //Gotta seek to the line we want first...
	graphfile >> max;
	return max;
}

int tomgraph::connection_count(void) {
	int ccount;
	seek_to_line(2);
	graphfile >> ccount;
	return ccount;
}

bool tomgraph::exists(int nodeid){
	return !(nodeid > node_count()); //if the ID is more than the max, it's invalid
}

bool tomgraph::is_connected(int nodea, int nodeb, int *weight_container) {
	int ccount;
	int t;
	int from;
	int to;
	int weight;
	//First check that both nodes actually exist
	if (!exists(nodea) || !exists(nodeb)) {
		return false;
	}
	ccount=connection_count();
	seek_to_line(3);
	for (t=1; t <= ccount; t++) {
		graphfile >> from;
		graphfile >> to;
		graphfile >> weight;

		if ((from == nodea) && (to == nodeb)) {
			*weight_container=weight;
			return true;
		}
	}
	//&weight_container's value is undefined if the edge don exits
	return false;
}

bool tomgraph::is_connected(int nodea, int nodeb) {
	int dummy; //just gonna throw this out
	return is_connected(nodea, nodeb, &dummy);
}

int tomgraph::get_connection_weight(int nodea, int nodeb) {
	int weight;
	return is_connected(nodea, nodeb, &weight);
	return weight;
}

bool tomgraph::is_connected_bidir(int nodea, int nodeb) {
	return (is_connected(nodea,nodeb) || is_connected(nodeb,nodea));
}

//array-backed weighted graph
//We use a (modified) file-backed tomgraph to load the graph data into memory
class arraygraph {
private:

public:
	void open(char *filename);
	bool exists(int nodeid);
	int node_count(void);
	int weight(int nodea, int nodeb);
	void print();
private:
	int count;
	vector <vector <int> > edges; //A vector of vectors! [Inception Noise]
};

//Only call .open() once. A second call will leave the old graph's dessicated corpse around the edges of the new one.
void arraygraph::open(char *filename){
	int count;
	int x, y;
	tomgraph loader;

	loader.open(filename);

	count=loader.node_count();

	//delete edges;
	//edges = new vector <vector <int> >;

	for (x=1; x <= count; x++) {
		for (y=1; y <= count; y++) {
			int weight;
			if (loader.is_connected(x,y,&weight) || loader.is_connected(y,x,&weight)) {
				edges[x-1][y-1]=weight;
			} else {
				edges[x-1][y-1]=0; //0 represents "no edge"
			}
		}
	}
}

int arraygraph::node_count() {
	return count;
}

bool arraygraph::exists(int nodeid){
	return !(nodeid > count); //if the ID is more than the max, it's invalid
}

//Instead of having an is_connected function or something like that, we just have a weight getter
//A weight of 0 represents the absence of a connection; anything else represents an edge with that weight.
int arraygraph::weight(int a, int b) {
	return edges[a][b];
}

void arraygraph::print() {
	int x,y;
	for (x=1; exists(x); x++) {
		cout << x;
		for (y=1; exists(y) <= count; y++) {
			cout << edges[x-1][y-1];
		}
		cout << endl;
	}
}

int main(int argc, char *argv[]) {
	arraygraph thegraph;
	thegraph.open(argv[1]);
	return 0;
}
