// Toyota.cpp

#include "Intel_Compatibility.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <list>
#include <algorithm>
#include <map>

using namespace std;

struct Reaction {
        unsigned int r1;
        unsigned int r2;
        unsigned int p1;
        unsigned int p2;
        float rate;
};

void ProcessReaction(Reaction &r, int z, list<pair<int, int> > &affectedChemicals) {
	if(z == 0)
		return;
	
	int one = 0;
	if(r.r1 == z) one--;
	if(r.r2 == z) one--;
	if(r.p1 == z) one++;
	if(r.p2 == z) one++;

	if(one != 0) {
		for(list<pair<int, int> >::iterator iter = affectedChemicals.begin(); iter != affectedChemicals.end(); iter++)
			if(iter->first == z)
				return;

		pair<int, int> p(z, one);
		affectedChemicals.push_back(p);
	}
}

// Compute Affected Chemicals for a Reaction
void ComputeAffectedChemicalsForReaction(Reaction &r, list<pair<int, int> > &affectedChemicals) {
	affectedChemicals.clear();
	ProcessReaction(r, r.r1, affectedChemicals);
	ProcessReaction(r, r.r2, affectedChemicals);
	ProcessReaction(r, r.p1, affectedChemicals);
	ProcessReaction(r, r.p2, affectedChemicals);
}

int main(int argc, char* argv[]) {
	// Argument 1 = Reaction file
	// Argument 2 = Chemical file
	// Argument 3 = Output Dependency Graph File
	
	map<int, list<int> > CSM;
	map<int, list<int> > DSM;
	
	cout << "Num Arguments = " << argc << std::endl;
	
	// -----------------------------------------------------
	ifstream rxnInput(argv[1]);

	int numReactions = 0;
	rxnInput >> numReactions;

	vector<Reaction> rxns;
	list<int> SDG;
	list<int> DDG;

	for(int i = 0; i < numReactions; i++) {
		Reaction r;
		rxnInput >> r.r1 >> r.r2 >> r.p1 >> r.p2 >> r.rate;
		rxns.push_back(r);
	}

	rxnInput.close();
	
	cout << "Num Reactions = " << numReactions << std::endl;
	
	// -----------------------------------------------------
	ifstream chemInput(argv[2]);
	
	int numChemicals = 0;
	chemInput >> numChemicals;
	chemInput.close();

	for(int i = 0; i < numChemicals; i++) {
		CSM[i];
		DSM[i];
	}

	cout << "Num Chemicals = " << numChemicals << std::endl;
	
	// -----------------------------------------------------
	
	// Now for each reaction
	for(int i = 0; i < numReactions; i++) {
		if(rxns[i].r1 == rxns[i].r2) {
			if(rxns[i].r1 != 0)
				DSM[rxns[i].r1].push_back(i);
		} else {
			if(rxns[i].r1 != 0)
				CSM[rxns[i].r1].push_back(i);
			if(rxns[i].r2 != 0)
				CSM[rxns[i].r2].push_back(i);
		}
	}

	// Now output the Dependency Graph File
	ofstream output(argv[3]);

	cout << "Output DG to " << string(argv[3]) << std::endl;
	
	// First we output for each reaction which chemicals are affected.
	// Second we output for each chemical the size of the CSM and DSM
	// Third we output the CSM and DSM
	// For each reaction compute which chemical's it affects
	for(int i = 0; i < numReactions; i++) {
		list<pair<int, int> > affectedChemicals;
		ComputeAffectedChemicalsForReaction(rxns[i], affectedChemicals);
		output << affectedChemicals.size() << std:: endl;
		for(list<pair<int, int> >::iterator iter = affectedChemicals.begin(); iter != affectedChemicals.end(); iter++)
			output << "\t" << iter->first << "\t" << iter->second << std::endl;
	}

	output << std::endl << std::endl;
	
	for(int i = 0; i < numChemicals; i++)
		output << CSM[i].size() << "	" << DSM[i].size() << std::endl;

	output << std::endl << std::endl;

	for(int i = 0; i < numChemicals; i++) {
		for(list<int>::iterator iter = CSM[i].begin(); iter != CSM[i].end(); iter++)
			output << *iter << std::endl;
		for(list<int>::iterator iter = DSM[i].begin(); iter != DSM[i].end(); iter++)
			output << "\t" << *iter << std::endl;
	}
	
	return 0;
}
