
#include <stdio.h>
#include "graph.h"

NiceText Node::NT;

void Node::AddLink(Node *n) {
	int i;
	int dont = 0;
	for (i=0;i<nlinks;i++) {
		if (links[i] == n) dont = 1;
	}
	if (!dont) {
		links[nlinks] = n;
		nlinks++;
	}
}

void Node::AddTempLink(Node *n) { templink = n; }

void Node::RemoveTempLink() { templink = NULL; }

void Node::PermanizeLink() {
	if (templink != NULL) {
		AddLink(templink);
		templink = NULL;
	}	
}

void Node::Print() {
	int i;
	if (dfsflag == 1) return;
	dfsflag = 1;
	printf("nlinks %d x %d level %d maxlevel %d\n", nlinks, xcoord, level, maxlevel);
	for (i=0;i<nlinks;i++) {
		printf("%d %d\n", AS, links[i]->AS);
	}
	for (i=0;i<nlinks;i++) {
		links[i]->Print();
	}
}

int Node::SetLevel(int n) {
	int i;
	if (level<n) {
		maxlevel = level = n;
		for (i=0;i<nlinks;i++) {
			if (links[i]->SetLevel(n+1) > maxlevel) {
				maxlevel = links[i]->SetLevel(n+1);
			}
		}
	}
	return maxlevel;
}


int Node::NumInLevel(int n) {
	int i, r;
	r = 0;
	if ((level==n) && (countedlevel==0)) { r = 1; countedlevel = 1; }
	for (i=0;i<nlinks;i++) r += links[i]->NumInLevel(n);
	return r;
}

void Node::SetLinearX(int *next) {

	int i;
	if (linearX < 0) {
		linearX = next[level+1];
		next[level+1] = next[level+1] + 1;
	}
	for (i=0;i<nlinks;i++) links[i]->SetLinearX(next);	
}

void Node::Draw() {
	int i;
	char asstr[8];
	if (dfsflag == 1) return;
	dfsflag = 1;
	glColor3f(0.1,0.1,0.1);
	glPointSize(5);
	glBegin(GL_POINTS);
	glVertex2f(xcoord,(float)level);
	glEnd();

	sprintf(asstr,"%d",AS);
	glRasterPos3f(xcoord+0.05,level,-0.1);
	NT.font.Render(asstr);

	for (i=0;i<nlinks;i++) {
		glLineWidth(2);
		glBegin(GL_LINES);
		glVertex3f(xcoord,(float)level,-0.1);	
		glVertex3f(links[i]->xcoord,(float)links[i]->level,-0.1);
		glEnd();
		links[i]->Draw();
	}
}


int Node::DetectCycle() {
	int i;
	if (dfsflag) {
		return 1;
	} else {
		dfsflag = 1;
		for (i=0;i<nlinks;i++) {
			if (links[i]->DetectCycle()) {
				return 1;
			}
		}
		if (templink != NULL) {
			if (templink->DetectCycle()) {
				return 1;
			}
		}
		dfsflag = 0;
		return 0;
	}
}

void Node::InitDFS() {
	int i;
	if (dfsflag==0) {
		return;
	} else {
		dfsflag = 0;
		for (i=0;i<nlinks;i++) {
			links[i]->InitDFS();
		}
		if (templink!=NULL) templink->InitDFS();
	}
}


Graph::Graph(int sx, int sy, int xs, int ys) : Visualization(sx,sy,xs,ys) {
	int i;
	for (i=0;i<MAX_N_NODES_IN_GRAPH;i++) nodes[i] = NULL;
	selectedPoint = -1;
}


void Graph::Draw() {


	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(-0.5,(float)x+0.5,-0.5,(float)y+0.5);
			// left, right, bottom, top
	glViewport(startx, starty, xsize, ysize);
			// startx, starty, xsize, ysize
			// coordinates begin from lower left corner of window
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
    glDisable(GL_TEXTURE_2D);
	glDisable(GL_LIGHTING);
	nodes[root]->InitDFS();
	nodes[root]->Draw();
}

void Graph::DrawPath(int *nodenums, int len, int wid, float *colors, float depth) {
	int i, n1, n2;
	glColor4f(colors[0],colors[1],colors[2],colors[3]);
	for (i=0; i < len-1; i++) {
		n1 = nodenums[i];
		n2 = nodenums[i+1];
		glLineWidth(wid);
		glBegin(GL_LINES);
		glVertex3f(nodes[n1]->xcoord,(float)nodes[n1]->level,depth);
		glVertex3f(nodes[n2]->xcoord,(float)nodes[n2]->level,depth);
		glEnd();
	}
}


int Graph::DetectCycle() {
	nodes[root]->InitDFS();
	return nodes[root]->DetectCycle();
}

void Graph::Init() {
	int i;
	for (i=0;i<MAX_N_NODES_IN_GRAPH;i++) {
		if (nodes[i]!=NULL) {
			delete nodes[i];
			nodes[i] = NULL;
		}
	}
	selectedPoint = -1;
}

void Graph::SelectPoint(int i, int j) {
	int n;
	int set = 0;
	printf("select point called %d %d\n", i, j);
	for (n=0;(n<MAX_N_NODES_IN_GRAPH)&&(!set);n++) {
		if ((nodes[n]!=NULL) && (nodes[n]->xcoord == i) && (nodes[n]->level == j)) {
			selectedPoint = n;
			set = 1;
		}
	}
	if (!set) selectedPoint = -1; 
}

void Graph::MovePoint(int i, int j) {
	if (selectedPoint >= 0) {
		nodes[selectedPoint]->xcoord = i;
		nodes[selectedPoint]->level = j;
	}
}

