/****************************************************************************

  main.cpp

****************************************************************************/

#include <string.h>
#include "glut.h"
#include <time.h>
#include "glui.h"

#include "time_int.h"
#include "graph.h"

#include "main2.h"
#include "structures.h"

#include "signature.h"


int Graph::show_attrs = 0;
float Graph::sep_fac = 1.0;
int Graph::sep_thres = 30;

extern int univs [6][12][32];
int unique_window = 120; // in minutes

double d_modelView_matrix[16];
double d_projection_matrix[16];
int d_viewport[4];

float xy_aspect;
int   last_x, last_y;
float rotationX = 0.0, rotationY = 0.0;
float sideRotationX = 0.0, sideRotationY = 0.0;
float tRotationX = 0.0, tRotationY = 0.0;
float fov, side_fov, tfov;

int moving, startx, starty;

int prevtstep = 0;

static float lightAngle = 0.0, lightHeight = 20;
int lightMoving = 0, lightStartX, lightStartY;

// graphics canvas dimensions
int mainwidth, mainheight;
int sidewidth, sideheight;
int mainx, mainy, sidex, sidey, controlx, controly;

//LWell W1;

char ifname[512];

BGPViewer B1;

Graph G1;
int show_time;

Signature S1;

GLUI_Checkbox   *basic_button, *class_button, *compare_button;
GLUI_Checkbox	*comann_box, *comraw_box;
GLUI_Checkbox	*text_or_box_box, *com_rd_box0, *com_rd_box1, *com_rd_box2, *com_rd_box3;
GLUI_Checkbox	*changes_only_box;
GLUI_Checkbox	*basic_box0, *basic_box1, *basic_box2;

GLUI_Spinner *time_spinner, *file_spinner, *comparison_spinner, *comparison_spinner2;
char filename[16];
GLUI_EditText *filename_text;
int file_num;
GLUI_StaticText *prefix_static_text;
char prefix_str[32];
GLUI_Spinner *peer1_spinner, *peer2_spinner, *peer3_spinner;
int animation_on;
int year, month, day, hour, min;
GLUI_StaticText *realtime_text;
GLUI_StaticText *updatetime_text;
char realtime_str[64];
char updatetime_str[64];
int inc_min, win_min;
int dnsfile_num1, dnsfile_num2, dnsfile_num3;
GLUI_Spinner *inc_min_spinner, *win_min_spinner, *incr_frac_spinner;
int incr_frac;


int publication;
int text_or_box;
int classification;
int show_periods;
int comparison;
int basic_mode;
int comparison_anns;
int comparison_raw;
int comparison_unique;
int draw_window_paths;
int com_rd_mode;
int changes_only;
int topright_mode;

// ********** These classes need the graph G1 **********************

#include "aggviz.h"
#include "pathviz.h"
#include "graphed.h"
#include "rawdataviz.h"
#include "linearnodes.h"

AggViz AV;
PathViz PV;
GraphEd GE;
RawDataViz RD;
LinearNodes LN;

#include "matrix.h"

Matrix M;

#include "instability.h"

Instability IS;
Regions RG;
Legend LG;

#include "comparison.h"

Comparison CM;

// ********** End these classes ************************************

GLUI_Spinner *uwin_spinner;

enum mouse_action { MOUSE_RIGHT_DOWN , MOUSE_ROTATE , MOUSE_DEFAULT , 
					MOUSE_DETAIL , MOUSE_SELECT_PATH , MOUSE_MEASURE };

mouse_action action;

int lastx, lasty;


void sideGlutDisplay( void );


int side_window;

bool playing = false;

extern int currentfile;
extern int numfiles;


GLUI *glui;


GLUI_Spinner *spinner1, *spinner2;


GLUI_Panel *panel2, *panel3, *panel4;
GLUI_Checkbox *svc, *sds, *sts, *wtcb, *otcb, *gtcb;


int show_date;
int begin_date;
int date_window;

extern int firstDate;

GLUI_Spinner *date_spinner;
GLUI_Spinner *begin_date_spinner;
GLUI_Spinner *date_window_spinner;

GLUI_Checkbox *begin_date_chkbx1;
GLUI_Checkbox *begin_date_chkbx2;


GLUI_Spinner *matrix_x_spinner, *matrix_y_spinner;
int matrix_x, matrix_y;
GLUI_Spinner *brightness_spinner;
float brightness;
int color_by_route;

int fixedbegin;



void tgaOut(char * fileName);

void output_cb(int id) {

	tgaOut("image.tga");

}

void readfile_cb(int id) {

	G1.readMRT(ifname);
	S1.GenerateEvents(&G1);
	S1.OutputEvents("signature.txt");
	IS.ReadIFile("signature.txt"); // must occur after MakeGraph because of univ
    glutSetWindow(side_window);  
	glutPostRedisplay();

}

void basic_cb(int id) {

	if (basic_mode) {
		AV.Init(0.15*sidewidth,0.01*sideheight,0.8*sidewidth,0.24*sideheight);
		RD.raw_data_time_window = 2 * G1.tinter;
		classification = 0;
		comparison = 0;
		class_button->set_int_val(0);
		compare_button->set_int_val(0);
	}
    glutSetWindow(side_window);  
	glutPostRedisplay();

}

void classification_cb(int id) {

	if (classification) {
		AV.Init(0.0,0.01*sideheight,sidewidth,0.24*sideheight);
		RD.raw_data_time_window = 2 * G1.tinter;
		comparison = 0;
		basic_button->set_int_val(0);
		compare_button->set_int_val(0);
	}
    glutSetWindow(side_window);  
	glutPostRedisplay();

}

void comparison_cb(int id) {

	if (comparison) {	
		AV.Init(0.0,0.01*sideheight,sidewidth,0.29*sideheight);
		RD.raw_data_time_window = 2 * CM.graphs[0]->tinter;
		classification = 0;
		basic_button->set_int_val(0);
		class_button->set_int_val(0);
	} else {	
		AV.Init(0.0,0.01*sideheight,sidewidth,0.24*sideheight);
		RD.raw_data_time_window = 2 * G1.tinter;
	}

    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void clear_cb(int id) {

	int i;
	for (i=0;i<N_SHADOW;i++) {
		G1.shadowpaths[i] = -1;
	}
    glutSetWindow(side_window);  
	glutPostRedisplay();

}


void com_rd_cb(int id) {


	if (id==0) {
		com_rd_box0->set_int_val(1);
		com_rd_box1->set_int_val(0);
		com_rd_box2->set_int_val(0);
	} else if (id==1) {
		com_rd_box0->set_int_val(0);
		com_rd_box1->set_int_val(1);
		com_rd_box2->set_int_val(0);
	} else if (id==2) {
		com_rd_box0->set_int_val(0);
		com_rd_box1->set_int_val(0);
		com_rd_box2->set_int_val(1);
	}

	com_rd_mode = id;

    glutSetWindow(side_window);  
	glutPostRedisplay();

}

unsigned char imageBufferRGBA_ptr[10000000];

void tgaOut(char * fileName) {
	// create the TGA header
	unsigned char header[18];


    glutSetWindow(side_window);  
	glutPostRedisplay();	
	glReadBuffer(GL_FRONT);
	glReadPixels(0,0,(GLsizei)sidewidth,(GLsizei)sideheight,GL_RGBA, GL_UNSIGNED_BYTE, imageBufferRGBA_ptr);
	
	for(int counter=0;counter<18;counter++)
	{
		header[counter]=0;
	}
	header[2]=2;
	header[12]=sidewidth%256;
	header[13]=sidewidth/256;
	header[14]=sideheight%256;
	header[15]=sideheight/256;
	header[16]=24;
	header[17]=24;

	unsigned char RGB[3];
	FILE *file_ptr;
	file_ptr=fopen(fileName,"wb");
	if(file_ptr==NULL)
	{
		printf("unable to write to %s\n",fileName);
		return ;
	}
	fwrite(header,18,1,file_ptr);
	int x,y;
	int actualWidth;
	actualWidth = sidewidth;
	// for each pixel
	for(y=0;y<sideheight;y++) {
		for(x=0;x<sidewidth;x++) {
			RGB[0]=*(imageBufferRGBA_ptr+(x+y*actualWidth)*4+0);
			RGB[1]=*(imageBufferRGBA_ptr+(x+y*actualWidth)*4+1);
			RGB[2]=*(imageBufferRGBA_ptr+(x+y*actualWidth)*4+2);
			// have to swap the R and B as you save
			fwrite(RGB+2,1,1,file_ptr);
			fwrite(RGB+1,1,1,file_ptr);
			fwrite(RGB+0,1,1,file_ptr);
		}
	}
	fclose(file_ptr);
	return;
}



void ResetTime() {
	printf("time is reset\n");
	if (G1.npaths>0) {
		year = G1.paths[0]->year;
		month = G1.paths[0]->month;
		day = G1.paths[0]->day;
		hour = G1.paths[0]->hour;
		min = G1.paths[0]->min;
	}
	sprintf(realtime_str,"%d / %d  / %d %d : %d", year, month, day, hour, min);
	sprintf(updatetime_str,"%d / %d  / %d %d : %d", G1.paths[0]->year, 
		G1.paths[0]->month, G1.paths[0]->day, G1.paths[0]->hour, G1.paths[0]->min);

}


void AdvanceRealTime() {

	int newtime;
	int currentunivtime;
	int beginning;

	currentunivtime = 0;
	currentunivtime += univs[year-UNIVSTARTYEAR][month-1][day-1] * 24 * 60;
	currentunivtime -= univs[G1.paths[0]->year-UNIVSTARTYEAR][G1.paths[0]->month-1][G1.paths[0]->day-1] * 24 * 60;
	currentunivtime += hour * 60;
	currentunivtime += min;
	currentunivtime += inc_min;


	min += inc_min;
	while (min >= 60) { min -= 60; hour++; };
	while (hour >= 24) { hour -= 24; day++; };
	while ( ((month==2)&&(day>29)&&(year%400==0)) ||
			((month==2)&&(day>28)&&(year%100==0)&&(year%400!=0)) ||
			((month==2)&&(day>29)&&(year%4==0)) ||
			((month==2)&&(day>28)&&(year%4!=0)) ||
			(((month == 9)||(month == 4)||(month == 6)||(month == 11))&&(day>30)) ||
			(day>31) ) {
		if ((month == 9)||(month == 4)||(month == 6)||(month == 11)) {
			day -= 30; month++;
		} else if (month==2) {
			day -= 28; month++;
		} else {
			day -= 31; month++;
		}
	}
	while (month > 12) { month -= 12; year++; };


	newtime = show_time + 1;
	beginning = 0;
	if (newtime >= G1.npaths) {
		ResetTime();
		currentunivtime = 0;
		currentunivtime += univs[year-UNIVSTARTYEAR][month-1][day-1] * 24 * 60;
		currentunivtime -= univs[G1.paths[0]->year-UNIVSTARTYEAR][G1.paths[0]->month-1][G1.paths[0]->day-1] * 24 * 60;
		currentunivtime += hour * 60;
		currentunivtime += min;
		newtime = 1;
		beginning = 1;
	}
	while ((!beginning)&&(currentunivtime>G1.paths[newtime]->univtime)) {
		newtime++;
		if (newtime >= G1.npaths) { 
			ResetTime(); 
			newtime = 1; 
			beginning = 1;
		};
	}
	show_time = newtime - 1;
	sprintf(realtime_str,"%d / %d  / %d %d : %d", year, month, day, hour, min);
	sprintf(updatetime_str,"%d / %d  / %d %d : %d", G1.paths[show_time]->year, 
		G1.paths[show_time]->month, G1.paths[show_time]->day, G1.paths[show_time]->hour, G1.paths[show_time]->min);
	realtime_text->set_text(realtime_str);
	updatetime_text->set_text(updatetime_str);
	time_spinner->set_int_val(show_time);



}



/**************************************** control_cb() *******************/
/* GLUI control callback                                                 */

void file_spinner_cb(int id) {

	char fname[32];
	char numstr[8];	

	strcpy(fname,"../data/soon.");
	sprintf(numstr,"%d.txt",file_num);
	strcat(fname,numstr);
	G1.Init();
	G1.MakeGraph(fname);
	G1.PrintPaths();
	G1.PrintGraph();
	ResetTime(); 

    time_spinner->set_int_limits( 0, G1.npaths - 1 );

	peer1_spinner->set_int_val(-1);
	peer2_spinner->set_int_val(-1);
	peer3_spinner->set_int_val(-1);

	//sprintf(prefix_str,"%d",file_num);
	//strcat(prefix_str,".0.0.0/8");
	strcpy(prefix_str,G1.ipadd);
	prefix_static_text->set_text(prefix_str);


    glutSetWindow(side_window);  
	glutPostRedisplay();

}


void dns_button_cb(int id) {
	char fname[64];
	char numstr[32];	

	strcpy(fname,"../data/dns.");
	sprintf(numstr,"%d-%d-%d", dnsfile_num1, dnsfile_num2, dnsfile_num3);
	strcat(fname,numstr);
	G1.Init();
	G1.MakeGraph(fname);
	//G1.PrintPaths();
	//G1.PrintGraph();
	ResetTime(); 

    time_spinner->set_int_limits( 0, G1.npaths - 1 );

	peer1_spinner->set_int_val(-1);
	peer2_spinner->set_int_val(-1);
	peer3_spinner->set_int_val(-1);


    glutSetWindow(side_window);  
	glutPostRedisplay();

}

void nomap_cb(int id) {
    glutSetWindow(side_window);  
	glutPostRedisplay();

}

void topright_cb(int id) {
	if (id==0) {
		basic_box0->set_int_val(1);
		basic_box1->set_int_val(0);
		basic_box2->set_int_val(0);
	} else if (id==1) {
		basic_box0->set_int_val(0);
		basic_box1->set_int_val(1);
		basic_box2->set_int_val(0);
	} else if (id==2) {
		basic_box0->set_int_val(0);
		basic_box1->set_int_val(0);
		basic_box2->set_int_val(1);
	}
	topright_mode = id;
    glutSetWindow(side_window);  
	glutPostRedisplay();

}

void filename_cb(int id) {

	char fname[32];

	strcpy(fname,"../data/");
	strcat(fname,filename);
	G1.Init();
	G1.MakeGraph(fname);
	G1.PrintPaths();
	G1.PrintGraph();


    glutSetWindow(side_window);  
	glutPostRedisplay();
}


void time_spinner_cb(int id) {
	if (show_time >= G1.npaths) {
		show_time = 0;
	}
    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void advance_time_cb(int id) {
	G1.AdvanceTime(show_time);
	if (show_time >= G1.npaths) {
		show_time = 0;
	}
	time_spinner->set_int_val(show_time);

	year = G1.paths[show_time]->year;
	month = G1.paths[show_time]->month;
	day = G1.paths[show_time]->day;
	hour = G1.paths[show_time]->hour;
	min = G1.paths[show_time]->min;
	sprintf(realtime_str,"%d / %d  / %d %d : %d", year, month, day, hour, min);
	sprintf(updatetime_str,"%d / %d  / %d %d : %d", G1.paths[show_time]->year, 
		G1.paths[show_time]->month, G1.paths[show_time]->day, G1.paths[show_time]->hour, G1.paths[show_time]->min);
	realtime_text->set_text(realtime_str);
	updatetime_text->set_text(updatetime_str);

    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void date_spinner_cb(int id) {

	if (id==0) { // if date_spinner changed
		if (fixedbegin) {
			date_window = datediff(show_date,begin_date);
			date_window_spinner->set_int_val(date_window);
		} else {
			begin_date = date_off(firstDate,-date_window);
			begin_date_spinner->set_int_val(begin_date);
		}
	} else if (id==1) { // if begin_date_spinner changed
		if (fixedbegin) {
			date_window = datediff(show_date,begin_date);
			date_window_spinner->set_int_val(date_window);
		}
	} else if (id==2) { // if date_window_spinner changed
		if (!fixedbegin) {
			begin_date = date_off(firstDate,-date_window);
			begin_date_spinner->set_int_val(begin_date);
		}
	}

    glutSetWindow(side_window);  
	glutPostRedisplay();
	
}

void matrix_cb(int id) {
	if (id==0) M.setx(matrix_x);
	if (id==1) M.sety(matrix_y);
	if (id==2) M.Init();
}

void redraw_func(int id) {

    glutSetWindow(side_window);  
	glutPostRedisplay();
}



/**************************************** myGlutKeyboard() **********/

void myGlutKeyboard(unsigned char Key, int x, int y)
{
  switch(Key)
  {
  case 27: 
  case 'q':
    exit(0);
    break;
  };
  
  glutPostRedisplay();
}


/***************************************** myGlutMenu() ***********/

void myGlutMenu( int value )
{
  myGlutKeyboard( value, 0, 0 );
}




/***************************************** myGlutIdle() ***********/

void myGlutIdle( void )
{

	if (animation_on) {
		AdvanceRealTime();
		M.Advance(inc_min);
	    glutSetWindow(side_window);  
		glutPostRedisplay();
	}

/*
	if (playing) {
	    glutSetWindow(side_window);  
		glutPostRedisplay();
	}
*/
	
}


void sideGlutDisplay( void )
{

	
	int currentunivtime;
	int i, j, t, cont;

	double screenx, screeny, screenz;

	if (publication) {
		glClearColor(1.0,1.0,1.0,0.0);
	} else {
		glClearColor(0.0,0.0,0.0,0.0);
	}
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	if (!comparison) {
		AV.Draw(); // Aggregate Visualization Unit
	} else {
		CM.DrawAgg(); // Comparison Visualization Unit
	}

	

	if (classification) {
		if (show_periods) RG.Draw(); // Regions Visualization Unit
		IS.Draw(); // Instability Classification Visualization Unit
		LG.Draw(); // Legend Unit
	} else if (!comparison) {
		if (topright_mode==0) { 
			//GE.Draw(); // Graph Edit Unit
			PV.Draw(); // Path Visualization Unit
		} else if (topright_mode==1) {
			LN.Draw(); // Linear Topology Visualization Unit
		}
		RD.Draw(); // Raw Data Visualization Unit
	} else {
		CM.DrawMap(); // Comparison Visualization Unit
		if (comparison_raw) CM.DrawRawData(); // Comparison Visualization Unit
	}
	
	glutSwapBuffers(); 


}

/***************************************** myGlutMouse() **********/

void sideGlutMouse(int button, int state, int x, int y )
{
	int i;

	double objx,objy,objz;

	double offx,offy,offz;

	int ix, iy;
	y = sideheight - y;

	if ( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {

		printf("point %d %d clicked\n", x, sideheight - y);


		if ((float)y<(AV.starty+0.50*AV.ysize)) {
			AV.selectBound((int)(512.0*((float)x-AV.startx)/AV.xsize));
			PV.selectBound((int)(512.0*((float)x-AV.startx)/AV.xsize));
			GE.selectBound((int)(512.0*((float)x-AV.startx)/AV.xsize));
			action = MOUSE_DEFAULT;
		} else if ((float)y<AV.ysize) {
			AV.selectRawBound((int)(512.0*((float)x-AV.startx)/AV.xsize));
			RD.mode = 1;
			action = MOUSE_DETAIL;
		} else if ((!comparison)&&((float)x>RD.FindStartMeasures())) {
			lastx = x;
			lasty = y;
			printf("mouse measure\n");
			action = MOUSE_MEASURE;
		} else {
			lastx = x;
			lasty = y;
			action = MOUSE_SELECT_PATH;
			if (!comparison) {
				GE.highlightPath(RD.highlightPath(y));
			} else {
				CM.highlightPath(x,y);
			}
			
		}

	} else if ( button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN ) {
		if ((float)y<(0.49*AV.ysize)) {
			RD.moveBound((int)(512.0*((float)x-AV.startx)/AV.xsize));
			RD.mode = 0;
			AV.moveRawDataDetail((int)(512.0*((float)x-AV.startx)/AV.xsize));
			action = MOUSE_RIGHT_DOWN;
		}	
  
	} else if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) {  
	
	} else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {  

		if (action == MOUSE_SELECT_PATH) {
			G1.highlightedpath = -1;	
			for (i=0;i<CM.nfiles;i++) {
				CM.graphs[i]->highlightedpath = -1;
			}
		}
	} 



	glutSetWindow(side_window);  
	glutPostRedisplay();


		
}


/***************************************** myGlutMotion() **********/

void sideGlutMotion(int x, int y )
{

	double objx,objy,objz;

	int ix, iy;

	y = sideheight - y;

	if (action == MOUSE_DEFAULT) {
		AV.moveBound((int)(512.0*((float)x-AV.startx)/AV.xsize));
		PV.moveBound((int)(512.0*((float)x-AV.startx)/AV.xsize));
		GE.moveBound((int)(512.0*((float)x-AV.startx)/AV.xsize));
	} else if (action == MOUSE_RIGHT_DOWN) {
		RD.moveBound((int)(512.0*((float)x-AV.startx)/AV.xsize));
		AV.moveRawDataDetail((int)(512.0*((float)x-AV.startx)/AV.xsize));
		RD.mode = 0;
	} else if (action == MOUSE_ROTATE) {
		PV.setRotation(x-lastx,y-lasty);
		lastx = x;
		lasty = y;
	} else if (action == MOUSE_DETAIL) {
		if (!comparison) {
			AV.moveRawBound((int)(512.0*((float)x-AV.startx)/AV.xsize), &G1);
		} else {
			AV.moveRawBound((int)(512.0*((float)x-AV.startx)/AV.xsize), CM.graphs[0]);
		}
		RD.detailstarttime = AV.rawStartTime;
		RD.detailwindow = AV.rawWindowTime;
		RD.mode = 1;
	} else if (action == MOUSE_MEASURE) {
		RD.SetMeasure(x);
	}
	
	glutSetWindow(side_window);  
	glutPostRedisplay();
}

/**************************************** myGlutReshape() *************/

void sideGlutReshape( int x, int y )
{
  xy_aspect = (float)x / (float)y;
  //glViewport( 0, 0, x, y );

	sidewidth = x;
	sideheight = y;

  glutPostRedisplay();
}

/********************* myGlutKeyboard() **********/

void sideGlutKeyboard(unsigned char Key, int x, int y)
{
  switch(Key)
  {
  case 27: 
  case 'q':
    exit(0);
    break;
  };
  
  glutPostRedisplay();
}





/**************************************** main() ********************/

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

	int dummy;

	// set variables controlling window dimensions


	sidewidth = 1000;
	sideheight =800;

	sidex = 0;
	sidey = 20;

	controlx = 1010;
	controly = 20;


	AV.Init(0.15*sidewidth,0.01*sideheight,0.8*sidewidth,0.24*sideheight);
	PV.Init(0.45*sidewidth,0.3*sideheight,0.45*sidewidth,0.7*sideheight);
	GE.Init(0.25*sidewidth,0.25*sideheight,0.4*sidewidth,0.3*sideheight);	
	RD.Init(0.0,0.28*sideheight,sideheight,0.7*sideheight);
	IS.Init(0.0,0.25*sideheight,sidewidth,0.5*sideheight);
	RG.Init(0.0,0.0,sidewidth,sideheight);
	LG.Init(0.1*sidewidth,0.7*sideheight,0.8*sidewidth,0.2*sideheight);
	CM.Init(0.0,0.01*sideheight,sidewidth,0.29*sideheight);
	CM.InitRD(0.0,0.01*sideheight,0.7*sidewidth,0.99*sideheight);
	CM.InitM(0.7*sidewidth,0.5*sideheight,0.3*sidewidth,0.5*sideheight);
	LN.Init(0.3*sidewidth,0.3*sideheight,0.7*sidewidth,0.7*sideheight);


	glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
  
	side_window = glutCreateWindow( "BGPViz" );
	glutPositionWindow( sidex , sidey );
	glutReshapeWindow( sidewidth , sideheight );

	glutDisplayFunc( sideGlutDisplay );
	glutReshapeFunc( sideGlutReshape );  
	glutKeyboardFunc( sideGlutKeyboard );
	glutMotionFunc( sideGlutMotion );
	glutMouseFunc( sideGlutMouse );


	glEnable(GL_DEPTH_TEST);
	show_date = firstDate;
	begin_date = firstDate;
	date_window = 0;


	//G1.readMRT("../data/roota.mrt.txt");
	G1.readStats("../data/stats.txt");
	RG.ReadIFile("../data/regions.txt");

	CM.ReadMaster("../data/comparison.txt");

	RD.raw_data_time_window = 2 * G1.tinter;

	S1.GenerateEvents(&G1);
	S1.OutputEvents("signature.txt");
	IS.ReadIFile("signature.txt"); // must occur after MakeGraph because of univ

	//G1.PrintPaths();
	//G1.PrintGraph();
	ResetTime();

	side_fov = fov = tfov = 40.0;

	animation_on = 0;

	/******** BEGIN GLUI **********************************/


	printf( "GLUI version: %3.2f\n", GLUI_Master.get_version() );

	glui = GLUI_Master.create_glui( "Control Panel", 0, controlx, controly ); 
                                  /* name, flags, x, and y */
	/*** Add invisible panel to hold rest of controls ***/
	GLUI_Panel *panel1 = glui->add_panel( "", GLUI_PANEL_NONE );
	/*** Start a new column in this panel ***/
	glui->add_column_to_panel(panel1, false); /* 'false' means don't draw bar */



	GLUI_Panel *modes_panel = glui->add_panel_to_panel( panel1, "Modes" );
	basic_button = glui->add_checkbox_to_panel( modes_panel, "Basic", &basic_mode, 0, basic_cb);
	basic_mode = 1;
	basic_button->set_int_val(1);
	class_button = glui->add_checkbox_to_panel( modes_panel, "Classification", &classification, 0, classification_cb);
	classification = 0;
	compare_button = glui->add_checkbox_to_panel( modes_panel, "Comparison", &comparison, 0, comparison_cb);
	comparison = 0;


	GLUI_Panel *basic_panel = glui->add_panel_to_panel( panel1, "Basic Options" );
/*
	glui->add_edittext_to_panel( basic_panel, "Input file", GLUI_EDITTEXT_TEXT,
		ifname, 0, readfile_cb);

	brightness_spinner = glui->add_spinner_to_panel( basic_panel, "Brightness", GLUI_SPINNER_FLOAT, &brightness, 0, redraw_func);
	brightness_spinner->set_float_limits(0.0,1.0);
	brightness_spinner->set_float_val(0.5);
*/
	brightness = 1.0;
	basic_box0 = glui->add_checkbox_to_panel( basic_panel, "Topology Map", &dummy, 0, topright_cb);
	basic_box1 = glui->add_checkbox_to_panel( basic_panel, "Arcs", &dummy, 1, topright_cb);
	basic_box2 = glui->add_checkbox_to_panel( basic_panel, "Measures", &dummy, 2, topright_cb);
	topright_mode = 0;
	basic_box0->set_int_val(1);
	basic_box1->set_int_val(0);
	basic_box2->set_int_val(0);
	/*
	glui->add_checkbox_to_panel( basic_panel, "Publication", &publication, 0, redraw_func);
	publication = 0;
	glui->add_checkbox_to_panel( basic_panel, "Draw Window Paths", &draw_window_paths, 0, redraw_func);
	draw_window_paths = 0;
	*/
	glui->add_button_to_panel(basic_panel, "Clear Highlight Paths", 0, clear_cb);

/*
	GLUI_Panel *class_panel = glui->add_panel_to_panel( panel1, "Classification Results" );

	glui->add_checkbox_to_panel( class_panel, "Show Periods", &show_periods, 0, redraw_func);
	show_periods = 0;
*/
  

	GLUI_Panel *comparison_panel = glui->add_panel_to_panel( panel1, "Text Options" );
/*
	comann_box = glui->add_checkbox_to_panel( comparison_panel, "Show Num Announements", &comparison_anns, 0, redraw_func);
	comann_box->set_int_val(1);
	glui->add_checkbox_to_panel( comparison_panel, "Show Unique Routes", &comparison_unique, 0, redraw_func);
	comraw_box = glui->add_checkbox_to_panel( comparison_panel, "Show Raw Data", &comparison_raw, 0, redraw_func);
	comraw_box->set_int_val(1);
*/
	comparison_anns = 1;
	comparison_unique = 1;
	comparison_raw = 1;

	/*
	text_or_box_box = glui->add_checkbox_to_panel( comparison_panel, "Text/Box", &text_or_box, 0, redraw_func);
	text_or_box_box->set_int_val(0);
	text_or_box = 0;
	com_rd_box0 = glui->add_checkbox_to_panel( comparison_panel, "Sequential", &dummy, 0, com_rd_cb);
	com_rd_box1 = glui->add_checkbox_to_panel( comparison_panel, "Overlapping", &dummy, 1, com_rd_cb);
	com_rd_box2 = glui->add_checkbox_to_panel( comparison_panel, "3D", &dummy, 2, com_rd_cb);
	com_rd_box0->set_int_val(1); com_rd_box1->set_int_val(0); com_rd_box2->set_int_val(0);
	com_rd_box3 = glui->add_checkbox_to_panel( comparison_panel, "Color by route", &color_by_route, 0, redraw_func);
	com_rd_box3->set_int_val(1);
	*/
	color_by_route = 1;
	glui->add_checkbox_to_panel( comparison_panel, "Show Attributes", &(Graph::show_attrs), 0, redraw_func);
	/*
	comparison_spinner = glui->add_spinner_to_panel( comparison_panel, "Separation Factor", GLUI_SPINNER_FLOAT, &(Graph::sep_fac), 0, redraw_func);
	comparison_spinner->set_float_limits(0.0,1.0);
	comparison_spinner->set_float_val(1.0);
	comparison_spinner2 = glui->add_spinner_to_panel( comparison_panel, "Separation Threshold", GLUI_SPINNER_INT, &(Graph::sep_thres), 0, redraw_func);
	comparison_spinner2->set_int_limits(10,100);
	comparison_spinner2->set_int_val(30);
	glui->add_statictext_to_panel(comparison_panel,"Linear Path Options");
	changes_only_box = glui->add_checkbox_to_panel( comparison_panel, "Path / Change", &changes_only, 0, redraw_func);
	changes_only_box->set_int_val(0);
	*/
	changes_only = 0;

	/******** Clean up ***********************************************/
	//glui->set_main_gfx_window( side_window );
	GLUI_Master.set_glutIdleFunc( myGlutIdle );
	glutMainLoop();

	return 0;

}

