#include <LINK/userobj/PostAnalyze.h>
#include <sys/types.h>
//#include <unistd.h> // changed



//********************************
// Global Variables
//********************************
int greedy_cut_count = 0;

Vertex*
getSmallestRankVertex(Graph* g) {

	SortedArray<Vertex*> vs = g->vertices();

	int num = 0; 
	int minNum = 0; 
	//int minNum = g->order() + 1;
	int tmp1 = 0;
	Vertex* tmp = vs.first(); 
	getAttribute((GraphObject*) tmp, "rank", minNum);

	Iterator<Vertex*> traverse(&vs);

	Vertex* v, *sv;
	while(traverse(v)) {
		getAttribute((GraphObject*) v, "rank", num);
		//cout << "In getSmallestRankVertex num : " << num << endl;
		//cout << "In getSmallestRankVertex minNum: " << minNum << endl;
		//cout << "Vertex in getSmallest : " << *v << endl;
		if (minNum > num) {
			minNum = num;
			sv = v;
		}
		//cout << "num = " << num << endl;
	}
cout << "minNum = " << minNum << endl;
//cout << "In getSmallestRankVertex Vetrex: " << *sv << endl;
return sv;
}


int
countCuts(Sequence<Vertex*> vs) {
	
	int placement = 0;
	int n_placement = 0;
	int count = 0;

	Iterator<Vertex*> traverse(&vs);
	Set<Vertex*> neighbors;

	Vertex* v1;
	Vertex* v2;
	while(traverse(v1)) {
		getAttribute((GraphObject*) v1, "partition", placement);
		if (placement == LEFT) {
			neighbors = v1->neighbors();
			Iterator<Vertex*> trav_neighbors(&neighbors);
			while(trav_neighbors(v2)) {
				getAttribute((GraphObject*) v2, "partition", n_placement);
					if(n_placement == RIGHT)
						count++;
			}
		}
	}
cout << "In count cuts function " << count << endl;
	return count;
}


void
log_file_cuts(char* path, int num_verts, double prob, int num_graph,
     char* type, char* bh_h, int seed, int KL_cuts, double kl_ave, double greedy_ave)
{
        char* buf;
	int this_num_graph = 0;
        ostrstream lss;
        ostrstream tss;
        fstream log_file;
        fstream file;

	if (KL_cuts > 0)    		// if a graph is not found then KL_cuts is -1
		 tss << path << "/" << "CountLog";
	else     tss << path << "/" << "Bad_Seeds";
	tss << ends;
	buf = tss.str();


        log_file.open(buf, ios::app);
        log_file.seekg(ios::end);
        log_file << "GetNumbers   " << num_verts << "    " << prob;
        log_file << "    " << type << "    " << bh_h << "    " << seed;
        log_file << "      " << KL_cuts <<  "       " << kl_ave << "          ";
        log_file << greedy_cut_count << "          " << greedy_ave << "     ";
        //log_file << getpid() <<  "     " << this_num_graph << endl; //changed
        log_file.close();
//cout << "In log status " << buf << endl;
        delete buf;
}





void
write_status(int n_verts, double prob, int percent, int num_graph, int flag, int kl_cuts,
 					        int seed, double kl_ave, double greedy_ave) {

	fstream status_file;
	char* wr;
	char* ng_g;
	char* dir_place = getenv("NUMBER_CUTS_LOG");
	if (percent > 5) wr = "bh";
		else wr = "h";
	//if (flag == 1) ng_g = "NONGREEDY";
		//else ng_g = "GREEDY"; 
	char* path = form_path(dir_place, "");   //defined in FindDistribution.cc

	if (flag == 1) ng_g = "ng";
		else ng_g = "g"; 
cout << "In write_status in GetNumbers path: " << path << endl;
	log_file_cuts(path, n_verts, prob, num_graph, ng_g, wr, seed, kl_cuts, kl_ave,
									   greedy_ave);
}


Graph* 
GetNumbers(int n_verts, double prob, int percent, int flag, int deviation, int seed) {

	Link_setSeed(seed);
	Sequence<Vertex*> vs;
	int done = 0;	
	int kl_cut_count = 0;
	//int greedy_cut_count = 0;
	Graph* g;
	Graph* induced_graph = NULL;
	double kl_ave = 0;
	double greedy_ave = 0;
	int kl_wins = 0;
	int greedy_wins = 0;
	int Loop = 0;
	int counter = 0;

	cout << "Loop " << Loop++ << endl;

	g = GenRandomGraph(n_verts, prob);

	kl_cut_count = KLFM(g);

	cout << "KLFM got cuts = " << kl_cut_count << endl;

	vs = PostAnalyze(g);

	induced_graph = Extract(g, percent, flag, vs, deviation);


	
	if (induced_graph != NULL) {      // a graph was found
		done = 1;
		Vertex *stopping_point = getSmallestRankVertex(induced_graph);
		cout << "Stopping vertex  :" << stopping_point << endl;
		Set<Set<Vertex*> > scc = StronglyConnectedComponents(induced_graph);
		cout << "In GetNumbers scc = " << scc << endl;
		Iterator<Set<Vertex*> > next_comp(&scc);
		Set<Vertex*> comp;
		while (next_comp(comp)) {
			if (comp.memberQ(stopping_point))
				break;
		}
		vs = PostAnalyze(g, comp);
		greedy_cut_count = countCuts(vs);

		cout << "Greedy got cuts = " << greedy_cut_count << endl;
		cout << "KLFM got cuts = " << kl_cut_count << endl;

		if (kl_cut_count > greedy_cut_count) kl_wins++;
			else                         greedy_wins++;
		counter++;
		kl_ave = (float)kl_wins/counter;
		greedy_ave = (float)greedy_wins/counter;

		write_graph(induced_graph, induced_graph->order(), prob, flag,
						    1, percent, seed);

		//write_graph(g, n_verts, prob, flag, 1, percent, seed);

		write_status(n_verts, prob, percent, Loop, flag, kl_cut_count, seed,
 								kl_ave, greedy_ave);
		write_status(induced_graph->order(), prob, percent, Loop, flag, 
						kl_cut_count, seed, kl_ave, greedy_ave);
	return induced_graph;
	}
	else write_status(n_verts, prob, percent, -1, flag, 0, seed, 0, 0);
return NULL;
}


/*
void
main(int argc, char* argv[])
{


int n_verts = atoi(argv[1]);
double prob = atof(argv[2]);
int percent = atoi(argv[3]);
int flag = atoi(argv[4]);
int deviation = atoi(argv[5]);
int seed = atoi(argv[6]);

int cuts = 0;
cout << *argv << endl;

Graph* g = GetNumbers(n_verts, prob, percent, flag, deviation, seed);


//cout << "Greedy got cuts:" << greedy_cut_count << endl;
}
*/
