
#ifndef AGGVIZ_H
#define AGGVIZ_H


class AggViz {

public:

	float startx, starty, xsize, ysize;

	int detailstart, detailend; // 0-511
	int selectedBound; // 0-start, 1-end
	int bothBoundsRefX;
	int StartRef, EndRef;

	
	int rawstart, rawend;
	int selectedRawBound;
	int bothRawBoundsRefX;
	int StartRawRef, EndRawRef;

	int rawStartTime;
	int rawWindowTime;
	int rawStartSlot;
	int rawEndSlot;

	int rawdatadetail; // 0-511

	AggViz() : detailstart(0) , detailend(0) , selectedBound(0) , rawdatadetail(0) ,
	rawStartSlot(0), rawEndSlot(0) { };

	void Init(float sx, float sy, float xs, float ys) {
		startx = sx; starty = sy; xsize = xs; ysize = ys;
	};

	void selectBound(int x) {
		int sd, ed;
		sd = x - detailstart; if (sd<0) sd = -sd;
		ed = x - detailend; if (ed<0) ed = -ed;
		if (sd < ed) {
			selectedBound = 0;
		} else {
			selectedBound = 1;
		} 
		if ((sd>4)&&(ed>4)&&(x>detailstart)&&(x<detailend)) {
			selectedBound = 2; // move both bounds
			bothBoundsRefX = x;
			StartRef = detailstart;
			EndRef = detailend;
		}
	};

	void moveBound(int x) {
		int temp;
		if (selectedBound == 2) {
			detailstart = (x - bothBoundsRefX) + StartRef;
			detailend = (x - bothBoundsRefX) + EndRef;
			if (detailstart >= 505) detailstart = 505;
			if (detailend >= 505) detailend = 505;
			if (detailstart < 0) detailstart = 0;
			if (detailend < 0) detailend = 0;
			return;
		}
		if (selectedBound == 0) {
			detailstart = x;
		} else if (selectedBound == 1) {
			detailend = x;
		}
		if (detailend < detailstart) {
			temp = detailend;
			detailend = detailstart;
			detailstart = temp;
		}
	};

	void selectRawBound(int x) {
		int sd, ed;
		sd = x - rawstart; if (sd<0) sd = -sd;
		ed = x - rawend; if (ed<0) ed = -ed;
		if (sd < ed) {
			selectedRawBound = 0;
		} else {
			selectedRawBound = 1;
		} 
		if ((sd>4)&&(ed>4)&&(x>rawstart)&&(x<rawend)) {
			selectedRawBound = 2; // move both bounds
			bothRawBoundsRefX = x;
			StartRawRef = rawstart;
			EndRawRef = rawend;
		}
	};


	void moveRawBound(int x, Graph *gptr) {
		int temp;
		float frac;
		if (selectedRawBound == 2) {
			rawstart = (x - bothRawBoundsRefX) + StartRawRef;
			rawend = (x - bothRawBoundsRefX) + EndRawRef;
			if (rawstart >= 512) rawstart = 511;
			if (rawend >= 512) rawend = 511;
			if (rawstart < 0) rawstart = 0;
			if (rawend < 0) rawend = 0;
		} else {
			if (selectedRawBound == 0) {
				rawstart = x;
			} else if (selectedRawBound == 1) {
				rawend = x;
			}
			if (rawend < rawstart) {
				temp = rawend;
				rawend = rawstart;
				rawstart = temp;
			}
		}
		frac = (float)rawstart / 512.0;
		rawStartSlot = detailstart + (int)(frac * (float)(detailend - detailstart + 1));
		rawStartTime = gptr->paths[0]->univtime;
		rawStartTime += (detailstart + (int)(frac * (float)(detailend - detailstart + 1))) * gptr->tinter;
		frac = (float)rawend / 512.0;
		rawEndSlot = detailstart + (int)(frac * (float)(detailend - detailstart + 1));
		rawWindowTime = gptr->paths[0]->univtime;
		rawWindowTime += (detailstart + (int)(frac * (float)(detailend - detailstart + 1))) * gptr->tinter;
		rawWindowTime -= rawStartTime;
		rawdatadetail = rawStartSlot;
	
	};



	void moveRawDataDetail(int x) {
		rawdatadetail = x;
		rawStartSlot = x;
		rawEndSlot = x+1;
		rawstart = rawend = 0;
	};

	void DrawOverviewBounds() {

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluOrtho2D(0,512,0,10);
				// left, right, bottom, top
		glViewport(startx, starty, xsize, 0.5 * ysize);
				// startx, starty, xsize, ysize
				// coordinates begin from lower left corner of window
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
	    glDisable(GL_TEXTURE_2D);
		glDisable(GL_LIGHTING);

		glPushMatrix();
		glColor3f(0.5,0.5,0.5);
		glBegin(GL_LINES);
		glVertex2i(detailstart,0);
		glVertex2i(detailstart,10);
		glVertex2i(detailend,0);
		glVertex2i(detailend,10);
		glEnd();
		if (publication) {
			glColor3f(0.3,0.3,0.9);
		} else {
			glColor3f(0.0,0.0,0.3);
		}
		glBegin(GL_QUADS);
		glVertex3f((float)detailstart,0.0,-0.5);
		glVertex3f((float)detailstart,10.0,-0.5);
		glVertex3f((float)detailend,10.0,-0.5);
		glVertex3f((float)detailend,0.0,-0.5);
		glEnd();
		glColor3f(0.6,0.0,0.0);
		glBegin(GL_LINES);
		glVertex2i(rawdatadetail,0);
		glVertex2i(rawdatadetail,10);
		glEnd();
		glBegin(GL_QUADS);
		glVertex3f((float)rawStartSlot,0.0,-0.4);
		glVertex3f((float)rawStartSlot,10.0,-0.4);
		glVertex3f((float)rawEndSlot,10.0,-0.4);
		glVertex3f((float)rawEndSlot,0.0,-0.4);
		glEnd();

		glPopMatrix();

	};


	void DrawDetailBounds() {
		

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluOrtho2D(0,512,0,10);
				// left, right, bottom, top
		glViewport(startx, starty + 0.5*ysize, xsize, 0.5 * ysize);
				// startx, starty, xsize, ysize
				// coordinates begin from lower left corner of window
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
	    glDisable(GL_TEXTURE_2D);
		glDisable(GL_LIGHTING);

		glPushMatrix();
		glColor3f(0.5,0.5,0.5);
		glBegin(GL_LINES);
		glVertex2i(rawstart,0);
		glVertex2i(rawstart,10);
		glVertex2i(rawend,0);
		glVertex2i(rawend,10);
		glEnd();
		glColor3f(0.6,0.0,0.0);
		glBegin(GL_QUADS);
		glVertex3f((float)rawstart,0.0,-0.5);
		glVertex3f((float)rawstart,10.0,-0.5);
		glVertex3f((float)rawend,10.0,-0.5);
		glVertex3f((float)rawend,0.0,-0.5);
		glEnd();

		glPopMatrix();

	};



	void Draw() { 

		char str[64];
		int i;

		// ****************** bounds ************************************************************** 


		DrawOverviewBounds();



		// ****************** time line, total number of announcements ****************** 

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluOrtho2D(0,512,0,G1.maxnumanns);
				// left, right, bottom, top
		glViewport(startx, starty, xsize, 0.2 * ysize);
				// startx, starty, xsize, ysize
				// coordinates begin from lower left corner of window
	    glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
	    glDisable(GL_TEXTURE_2D);
		glDisable(GL_LIGHTING);

		glPushMatrix();
	    G1.DrawTimeLine(-1);
		glColor3f(0.5,0.5,0.5);
		glBegin(GL_LINES);
		glVertex3f(0.0,0.0,0.0);
		glVertex3f(512.0,0.0,0.0);
		glEnd();
	    glPopMatrix();

		// ****************** label this display ***********************************************

		if (!publication) {
			glMatrixMode(GL_PROJECTION);
			glLoadIdentity();
			gluOrtho2D(0,160,0,5);
					// left, right, bottom, top
			glViewport(startx, starty, xsize, 0.2 * ysize);
					// startx, starty, xsize, ysize
					// coordinates begin from lower left corner of window
			glMatrixMode(GL_MODELVIEW);
			glLoadIdentity();
			glDisable(GL_TEXTURE_2D);
			glDisable(GL_LIGHTING);
			glColor3f(1.0,1.0,1.0);
			strcpy(str,"Num updates (all time)");
			for (i=0;i<strlen(str);i++) {
				glRasterPos3f(1.0+(float)i,1.0,1.0);
				glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10,str[i]);
			}
		}


		// ****************** time line, paths **************************************************** 

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluOrtho2D(0,512,-1,2*(G1.ndistinctpaths+1));
				// left, right, bottom, top
		glViewport(startx, starty + 0.25 * ysize, xsize, 0.2 * ysize);
				// startx, starty, xsize, ysize
				// coordinates begin from lower left corner of window
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
	    glDisable(GL_TEXTURE_2D);
		glDisable(GL_LIGHTING);

		glPushMatrix();
		G1.DrawTimeDistinctPaths(-1);
		glPopMatrix();

		// ****************** label this display ***********************************************

		if (!publication) {
			glMatrixMode(GL_PROJECTION);
			glLoadIdentity();
			gluOrtho2D(0,160,0,5);
					// left, right, bottom, top
			glViewport(startx, starty + 0.25 * ysize, xsize, 0.2 * ysize);
					// startx, starty, xsize, ysize
					// coordinates begin from lower left corner of window
		    glMatrixMode(GL_MODELVIEW);
			glLoadIdentity();
		    glDisable(GL_TEXTURE_2D);
			glDisable(GL_LIGHTING);
			glColor3f(1.0,1.0,1.0);
			strcpy(str,"Unique routes (all time)");
			for (i=0;i<strlen(str);i++) {
				glRasterPos3f(1.0+(float)i,1.0,1.0);
				glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10,str[i]);
			}
		}

	
		
		// ****************** bounds ************************************************************** 

		DrawDetailBounds();
	
		
		// ****************** window distinct paths **************************************************** 

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluOrtho2D(0,512,-1,2*(G1.ndistinctpaths+1));
				// left, right, bottom, top
		glViewport(startx, starty + 0.5*ysize, xsize, 0.2 * ysize);
				// startx, starty, xsize, ysize
				// coordinates begin from lower left corner of window
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
	    glDisable(GL_TEXTURE_2D);
		glDisable(GL_LIGHTING);

		glPushMatrix();
		G1.DrawNewWinDistinctPaths(detailstart, detailend);
		glPopMatrix();

		
		// ****************** label this display ***********************************************

		if (!publication) {
			glMatrixMode(GL_PROJECTION);
			glLoadIdentity();
			gluOrtho2D(0,160,0,5);
					// left, right, bottom, top
			glViewport(startx, starty + 0.5 * ysize, xsize, 0.2 * ysize);
					// startx, starty, xsize, ysize
					// coordinates begin from lower left corner of window
		    glMatrixMode(GL_MODELVIEW);
			glLoadIdentity();
		    glDisable(GL_TEXTURE_2D);
			glDisable(GL_LIGHTING);
			glColor3f(1.0,1.0,1.0);
			strcpy(str,"Unique routes (window)");
			for (i=0;i<strlen(str);i++) {
				glRasterPos3f(1.0+(float)i,1.0,1.0);
				glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10,str[i]);
			}
		}
			
		// ****************** window path lengths **************************************************** 

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluOrtho2D(0,512,-1,15);
				// left, right, bottom, top
		glViewport(startx, starty + 0.75*ysize, xsize, 0.2 * ysize);
				// startx, starty, xsize, ysize
				// coordinates begin from lower left corner of window
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
	    glDisable(GL_TEXTURE_2D);
		glDisable(GL_LIGHTING);

		glPushMatrix();
		G1.DrawPathLengths(detailstart, detailend);
		glPopMatrix();
	
		// ****************** label this display ***********************************************

		if (!publication) {
			glMatrixMode(GL_PROJECTION);
			glLoadIdentity();
			gluOrtho2D(0,160,0,5);
					// left, right, bottom, top
			glViewport(startx, starty + 0.75 * ysize, xsize, 0.2 * ysize);
					// startx, starty, xsize, ysize
					// coordinates begin from lower left corner of window
			glMatrixMode(GL_MODELVIEW);
			glLoadIdentity();
			glDisable(GL_TEXTURE_2D);
			glDisable(GL_LIGHTING);
			glColor3f(1.0,1.0,1.0);
			strcpy(str,"AS route length (window)");
			for (i=0;i<strlen(str);i++) {
				glRasterPos3f(1.0+(float)i,1.0,1.0);
				glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10,str[i]);
			}
		}	
	};



};

#endif

