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

  main.cpp

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

#include <string.h>
#include "glut.h"
#include <time.h>
#include "glui.h"
#include "structures.h"
#include "histogram.h"
#include "oasc.h"
#include "client.h"
#include "dynamics.h"

MyClient C1;

int sidewidth = 650;
int sideheight = 850;


DynamicsViz DV(0,0,600,850);
OASCViz OA(0,0,600,850);

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 mainx, mainy, sidex, sidey, controlx, controly, controlx2, controly2, controlx3, controly3;
//BGPViewer B1;


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


double de_modelView_matrix[16];
double de_projection_matrix[16];
int de_viewport[4];

clock_t old_time;
int receiving;

int make_movie = 0;
int movie_frame = 0;

enum mouse_action { MOUSE_ROTATE , MOUSE_ZOOM , MOUSE_MOVE_HISTOGRAM , MOUSE_MOVE_MEASURE, MOUSE_NOTHING ,
MOUSE_ROTATE_SCATTERPLOT };

mouse_action action;


extern float FishEyeFocus[2];

void sideGlutDisplay( void );

void myGlutDisplay( void );

int side_window;


bool playing = false;

/** Pointers to the windows and some of the controls we'll create **/
GLUI *glui;
GLUI *perday_glui;
GLUI *perupdate_glui;
GLUI *mode_glui;
GLUI *dynamics_glui;


GLUI_Checkbox *mode_chkbx[2];

GLUI_Checkbox *granular_chkbx[2];
GLUI_Spinner *perupdate_date_spinner, *perupdate_time_spinner, *perupdate_window_spinner, *perupdate_incr_spinner;
GLUI_Checkbox *perupdate_chkbx[2];
GLUI_Spinner *preprocess_begin_spinner, *preprocess_end_spinner;
GLUI_Spinner *begin_date_spinner, *end_date_spinner;


GLUI_Checkbox *dimension_chkbx[2];

GLUI_Spinner *ASFocus0_spinner;
int ASFocus0;

GLUI_StaticText *highlight_ip_text;

GLUI_Spinner *spinner1, *spinner2;

GLUI_Panel *panel2, *panel3, *panel4;
GLUI_Checkbox *svc, *sds, *sts, *wtcb, *otcb, *gtcb;
GLUI_Checkbox *prefixmask_chkbx0, *prefixmask_chkbx1;
GLUI_Checkbox *receiving_box;
GLUI_Checkbox *minute_checkbox;


GLUI_Spinner *dynamics_date_spinner;

GLUI_Checkbox *dynamics_display_chkbx[2];
GLUI_Checkbox *dynamics_aux_chkbx[5];

GLUI *realtime_glui; 
GLUI_Panel *realtime_panel1;
GLUI_Spinner *realtime_startdate_spinner;
GLUI_Spinner *realtime_starttime_spinner;
GLUI_Spinner *realtime_enddate_spinner;
GLUI_Spinner *realtime_endtime_spinner;

GLUI_Panel *aslines_panel;
GLUI_Spinner *aslines_spinner1;
GLUI_Spinner *aslines_spinner2;
GLUI_Spinner *aslines_spinner3;


int DisregardAS0;
int DisregardAS1;
int DisregardAS2;
int DisregardAS3;
int DisregardAS4;

int disregard_related;



int suppress_from;
int suppress_to;
int suppress_related;




extern int firstDate;
extern int currentDate;

int currentiDate;

GLUI_Spinner *date_spinner;
GLUI_Spinner *date_window_spinner;

GLUI_Spinner *delay_spinner;
float delay;

GLUI_Checkbox *begin_date_chkbx1;
GLUI_Checkbox *begin_date_chkbx2;

int fixedbegin;



GLUI_Checkbox *showcubes_chkbx;
GLUI_Checkbox *showprojection_chkbx;

int show_date, begin_date, date_window;

int window_mode;

/********** User IDs for callbacks ********/
#define LIGHT0_ENABLED_ID    200
#define LIGHT1_ENABLED_ID    201
#define LIGHT0_INTENSITY_ID  250
#define LIGHT1_INTENSITY_ID  251

/********** Miscellaneous global variables **********/

GLfloat light0_ambient[] =  {0.1f, 0.1f, 0.3f, 1.0f};
GLfloat light0_diffuse[] =  {.6f, .6f, 1.0f, 1.0f};
GLfloat light0_position[] = {.5f, .5f, 1.0f, 0.0f};

GLfloat light1_ambient[] =  {0.1f, 0.1f, 0.3f, 1.0f};
GLfloat light1_diffuse[] =  {.9f, .6f, 0.0f, 1.0f};
GLfloat light1_position[] = {-1.0f, -1.0f, 1.0f, 0.0f};

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


void tgaOut(char * fileName);

void screendump_cb(int id) {
	tgaOut("image.tga");
}


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 granular_cb(int id) {
	granular_chkbx[id]->set_int_val(1);
	granular_chkbx[1-id]->set_int_val(0);
	OA.per = id;
	if (id==0) { perday_glui->show(); perupdate_glui->hide();
	} else { perday_glui->hide(); perupdate_glui->show();
	}
    glutSetWindow(side_window);  
	glutPostRedisplay();
}


void MakeFrame() {

	char fname[32];

	sprintf(fname,"../movie/frame%03d.tga",movie_frame);
	tgaOut(fname);
	movie_frame++;

}

void makeframe_cb(int id) {
	MakeFrame();
}

void change_realtime_cb(int id) {
	realtime_glui->show();
}


void realtime_commit_cb(int id) {
	realtime_glui->hide();
}

void date_spinner_cb(int id) {
	OA.SetDate(OA.current_date);
	date_spinner->set_int_val(OA.current_date);
	perupdate_date_spinner->set_int_val(OA.current_date);
    glutSetWindow(side_window);  
	glutPostRedisplay();	
}


void time_spinner_cb(int id) {
    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void window_spinner_cb(int id) {
    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void incr_spinner_cb(int id) {
    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void perupdate_chkbx_cb(int id) {
    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void perupdate_playbutton_cb(int id) {
	playing = true;
    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void perupdate_stopbutton_cb(int id) {
	playing = false;
    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void perupdate_advancebutton_cb(int id) {
	if (OA.perupdate_incr_type==0) { // if update by entry
		OA.current_entry += OA.perupdate_incr;
	} else {
	}
	if ((OA.current_entry + OA.perupdate_window) >= OA.numdetail) OA.current_entry = 0;
	OA.perupdate_time = 0;
	if (OA.numdetail>0) OA.perupdate_time = OA.detailOASC[OA.current_entry].ctime;
	perupdate_time_spinner->set_int_val(OA.perupdate_time);
    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void perupdate_backbutton_cb(int id) {
	if (OA.perupdate_incr_type==0) { // if update by entry
		OA.current_entry -= OA.perupdate_incr;
	} else {
	}
	if (OA.current_entry < 0) OA.current_entry = 0;
	OA.perupdate_time = 0;
	if (OA.numdetail>0) OA.perupdate_time = OA.detailOASC[OA.current_entry].ctime;
	perupdate_time_spinner->set_int_val(OA.perupdate_time);
    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void dynamics_date_spinner_cb(int id) {

	DV.SetDate(DV.current_date);
	dynamics_date_spinner->set_int_val(DV.current_date);
    glutSetWindow(side_window);  
	glutPostRedisplay();	

}


void dynamics_advancebutton_cb( int id ) {
	DV.AdvanceDate();
	dynamics_date_spinner->set_int_val(DV.current_date);
    glutSetWindow(side_window);  
	glutPostRedisplay();
}


void dynamics_backbutton_cb( int id ) {
	DV.BackDate();
	dynamics_date_spinner->set_int_val(DV.current_date);
    glutSetWindow(side_window);  
	glutPostRedisplay();
}


void dynamics_playbutton_cb( int id ) {
	playing = true;
    glutSetWindow(side_window);  
	glutPostRedisplay();
}


void dynamics_stopbutton_cb( int id ) {
	playing = false;
    glutSetWindow(side_window);  
	glutPostRedisplay();
}


void dimension_cb(int id) {
	int i;
	for (i=0;i<2;i++) dimension_chkbx[i]->set_int_val(0);
	dimension_chkbx[id]->set_int_val(1);
	OA.dimension_flag = id;
    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void preprocess_cb(int id) {

	OA.PreProcess("../data_aux/counts.txt");
    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void rangebutton_cb(int id) {

	OA.ReadCount("../data_aux/counts.txt");
	date_spinner->set_int_limits( OA.first_date, OA.last_date );
	perupdate_date_spinner->set_int_limits( OA.first_date, OA.last_date );
    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void redraw_func(int id) {

    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void depth_spinner_cb( int id ) {

	spinner2->set_float_val(spinner2->get_float_val()+10.0);

};

void playbutton_cb( int id ) {
	playing = true;
    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void stopbutton_cb( int id ) {
	playing = false;
    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void advancebutton_cb( int id ) {

	OA.AdvanceDate();
	date_spinner->set_int_val(OA.current_date);
	perupdate_date_spinner->set_int_val(OA.current_date);
	perupdate_time_spinner->set_int_val(OA.perupdate_time);
    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void backbutton_cb( int id ) {

	OA.BackDate();
	date_spinner->set_int_val(OA.current_date);
	perupdate_date_spinner->set_int_val(OA.current_date);
	perupdate_time_spinner->set_int_val(OA.perupdate_time);
    glutSetWindow(side_window);  
	glutPostRedisplay();

}

void highlight_AS_cb(int id) {
	if (id==0) {
		OA.AddHighlightAS(ASFocus0);
	} else if (id==1) {
		OA.RemoveHighlightAS(ASFocus0);
	}
    glutSetWindow(side_window);  
	glutPostRedisplay();
}

void country_cb(int id) {
	printf("name is %s\n", OA.CN.cname);
	OA.CN.ReadCountry("../data_aux/countries.txt");
    glutSetWindow(side_window);  
	glutPostRedisplay();
}


void highlight_ip_cb(int id) {


}

void mode_cb(int id) {
	if (id==0) {
		mode_chkbx[0]->set_int_val(1);
		mode_chkbx[1]->set_int_val(0);
		glui->show();
		if (OA.per==0) {
			perday_glui->show();
		} else {
			perupdate_glui->show();
		}
		dynamics_glui->hide();
	} else if (id==1) {
		mode_chkbx[0]->set_int_val(0);
		mode_chkbx[1]->set_int_val(1);
		glui->hide();
		perday_glui->hide();
		perupdate_glui->hide();
		dynamics_glui->show();
	}
	window_mode = id;

    glutSetWindow(side_window);  
	glutPostRedisplay();
	
}


void dynamics_aux_cb(int id) {
	for (int i=0;i<5;i++) {
		if (i==id) {
			dynamics_aux_chkbx[i]->set_int_val(1);
		} else {
			dynamics_aux_chkbx[i]->set_int_val(0);
		}
	}
	DV.aux_mode = id;
    glutSetWindow(side_window);  
	glutPostRedisplay();
}


void control_cb( int control )
{

}

/**************************************** 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 )
{

	int nreceived;
	clock_t new_time;

	new_time = clock();

	if (((double)(new_time-old_time)/(double)CLOCKS_PER_SEC)>delay) { 
		if (playing) {

			if (window_mode==0) {				
				if (OA.per==0) {
					advancebutton_cb(0);			
				} else {
					perupdate_advancebutton_cb(0);
				}
			} else {
				dynamics_advancebutton_cb(0);
			}


			if (make_movie) MakeFrame();
			glutSetWindow(side_window);  
			glutPostRedisplay();

		}
		if (receiving) {
			nreceived = C1.socket_main();
			realtime_startdate_spinner->set_int_val(C1.startdate);
			realtime_starttime_spinner->set_int_val(C1.starttime);
			glutSetWindow(side_window);  
			glutPostRedisplay();
		}
		old_time = new_time;

		
	}
	
}


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

void myGlutReshape( int x, int y )
{

}


/************************************************** draw_axes() **********/
/* Disables lighting, then draws RGB axes                                */

void draw_axes( float scale )
{

}



void sideGlutDisplay( void )
{
  
	int i;

	float actualLogWidth, actualLogHeight, wrongLogWidth, wrongLogHeight;

	
	double modelView_matrix[16];
	double projection_matrix[16];
	int viewport[4];

	double dummy;

	double ax, ay, bx, by;


	glClearColor(1.0,1.0,1.0,1.0);
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );



	if (window_mode==0) {
		OA.Draw();
	} else {
		DV.Draw();
	}


  // flush to screen

	printf("\n\n\n********************************************************************* \n\n\n");


  glutSwapBuffers(); 

}




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

void sideGlutMotion(int x, int y )
{

	int d;

	if (action == MOUSE_ROTATE) {
		sideRotationY = sideRotationY + (x - last_x);
		while (sideRotationY > 360.0) sideRotationY -= 360.0;
		while (sideRotationY < 0.0) sideRotationY += 360.0;
		sideRotationX = sideRotationX + (y - last_y);
		while (sideRotationX > 360.0) sideRotationX -= 360.0;
		while (sideRotationX < 0.0) sideRotationX += 360.0;
		last_x = x;
		last_y = y;
		glutPostRedisplay();
	} else if (action == MOUSE_ZOOM) {
		side_fov += (float) (y - last_y);
	} else if (action == MOUSE_MOVE_HISTOGRAM) {
		if (window_mode==0) {
			OA.H.ScreenToData(x,d);
			if (d>=0) {
				OA.current_date = d;
				date_spinner_cb(0);
			}
		} else {
			DV.H.ScreenToData(x,d);
			if (d>=0) {
				DV.current_date = d;
				dynamics_date_spinner_cb(0);
			}
		}

	} else if (action == MOUSE_MOVE_MEASURE) {
		DV.MV.SetMeasureMul(x);
	} else if (action == MOUSE_ROTATE_SCATTERPLOT) {
		OA.SP.x_rot += x - last_x;
		OA.SP.y_rot += y - last_y;
	}

	last_x = x;
	last_y = y;

	glutPostRedisplay(); 

}




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

	int d, m;
	unsigned int ud;

	if (window_mode==0) { // OASC visualization
		if ( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
			if (OA.S.ClickDetected(x,sideheight-y)) {
				OA.S.ScreenToData(x,sideheight-y,d);
				OA.highlighted_AS_clicked = d;
				printf("click detected %d\n", d);
			} else if ((OA.dimension_flag==0) && (OA.Q.ClickDetected(x,sideheight-y))) {
				OA.Q.ScreenToData(x,sideheight-y,ud,m);
				printf("integer clicked %u %d\n", ud, m);
				OA.highlighted_IP_prefix.P.IntToIPAddress(ud);
				OA.highlighted_IP_prefix.P.Mask = m - 8;
				OA.highlighted_IP_prefix.P.ReMask();
				OA.highlighted_IP_prefix.P.GenerateText();
				highlight_ip_text->set_text(OA.highlighted_IP_prefix.P.text);
			} else if ((OA.dimension_flag==1) && (OA.SP.ClickDetected(x,sideheight-y))) {
				last_x = x; last_y = y;
				action = MOUSE_ROTATE_SCATTERPLOT;
			} else if (OA.H.ClickDetected(x,sideheight-y)) {
				OA.H.ScreenToData(x,d);
				if (d>=0) {
					OA.current_date = d;
					date_spinner_cb(0);
				}
				action = MOUSE_MOVE_HISTOGRAM;
			}
		} else if ( button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
			action = MOUSE_NOTHING;
		}
	} else { // dynamics visualization
		if ( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
			if (DV.H.ClickDetected(x,sideheight-y)) {
				DV.H.ScreenToData(x,d);
				if (d>=0) {
					DV.current_date = d;
					dynamics_date_spinner_cb(0);
				}
				action = MOUSE_MOVE_HISTOGRAM;
			} else if ((DV.aux_mode==1) && (DV.MV.ClickLabelDetected(x,sideheight-y))) {
				DV.MV.SelectMeasureMul(x);
				action = MOUSE_MOVE_MEASURE;
			}
		} else if ( button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
			if (action == MOUSE_MOVE_MEASURE) {
				DV.MV.SetMeasureMul(x);
			}
			action = MOUSE_NOTHING;
		}
	}

	
	sideGlutDisplay();
	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() ********************/

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

	int i;
	int dummy;

	sidex = 5;
	sidey = 30;

	sidewidth = 745;
	sideheight = 850;
	

	controlx = 760;
	controly = 30;
	controlx2 = 760;
	controly2 = 150;
	controlx3 = 760;
	controly3 = 610;


  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_LIGHTING);
  glEnable( GL_NORMALIZE );

  glEnable(GL_LIGHT0);
  glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
  glLightfv(GL_LIGHT0, GL_POSITION, light0_position);

  glEnable(GL_LIGHT1);
  glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);
  glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
  glLightfv(GL_LIGHT1, GL_POSITION, light1_position);


  glEnable(GL_DEPTH_TEST);

	

	OA.Init();
	OA.first_date = OA.current_date = 20020101;
	OA.last_date = 20020301;
	OA.preprocess_begin = 20020101;
	OA.preprocess_end = 20020501;
	OA.ReadCount("../data_aux/counts.txt");
	OA.ReadDaily(20020101);
	OA.ReadDetail(20020101);
	OA.perupdate_time = 0;
	if (OA.numdetail>0) OA.perupdate_time = OA.detailOASC[0].ctime;
	OA.current_entry = 0;

	DV.readStats("../data_dynamics/198.41.0.0.24.txt");
	DV.GenerateSigAnEvents();

	side_fov = fov = tfov = 40.0;

	old_time = clock();

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


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

  glui = GLUI_Master.create_glui( "OASC", 0, controlx2, controly2 ); 
                                  /* name, flags, x, and y */
  perday_glui = GLUI_Master.create_glui( "Per day controls", 0, controlx3, controly3 ); 
  perupdate_glui = GLUI_Master.create_glui( "Per day controls", 0, controlx3, controly3 ); 

  mode_glui = GLUI_Master.create_glui( "OASC or Dynamics", 0, controlx, controly );

  
  dynamics_glui = GLUI_Master.create_glui( "Dynamics", 0, controlx2, controly2 ); 

  GLUI_Panel *mode_panel1 = mode_glui->add_panel( "", GLUI_PANEL_NONE );
  GLUI_Panel *mode_panel2 = mode_glui->add_panel_to_panel ( mode_panel1, "", GLUI_PANEL_NONE );
  mode_chkbx[0] = mode_glui->add_checkbox_to_panel( mode_panel2, "OASC", &dummy, 0, mode_cb);
  mode_chkbx[1] = mode_glui->add_checkbox_to_panel( mode_panel2, "Dynamics", &dummy, 1, mode_cb);
  mode_cb(0);


  /*** Add invisible panel to hold rest of controls ***/
  GLUI_Panel *panel1 = glui->add_panel( "", GLUI_PANEL_NONE );

  GLUI_Panel *panel2 = glui->add_panel_to_panel ( panel1, "", GLUI_PANEL_NONE );

  /***** per day or per update *****/
  GLUI_Panel *granular_panel = glui->add_panel_to_panel( panel2, "Per day or update" );
  granular_chkbx[0] = glui->add_checkbox_to_panel( granular_panel, "Per day", &dummy, 0, granular_cb);
  granular_chkbx[1] = glui->add_checkbox_to_panel( granular_panel, "Per update", &dummy, 1, granular_cb);
  granular_cb(0);

  GLUI_Panel *display_panel2 = glui->add_panel_to_panel( panel2, "Display Options 1" );
  
  //glui->add_checkbox_to_panel( display_panel2, "IP Prefix Detail", &(showDetail[0]), 0, (GLUI_Update_CB)initdetail_cb);
  OA.show_lines = 1;
  glui->add_checkbox_to_panel( display_panel2, "Show IP-AS Lines", &(OA.show_lines), 0, redraw_func);
  //glui->add_checkbox_to_panel( display_panel2, "Frequent Filter", &(B1.frequentFlag), 0, redraw_func);
  for (i=0;i<8;i++) OA.show_type[i] = 0;
  for (i=2;i<6;i++) OA.show_type[i] = 1;
  glui->add_checkbox_to_panel( display_panel2, "OS", &(OA.show_type[0]), 0, redraw_func);
  glui->add_checkbox_to_panel( display_panel2, "OM", &(OA.show_type[1]), 0, redraw_func);
  glui->add_checkbox_to_panel( display_panel2, "CSM", &(OA.show_type[2]), 0, redraw_func);
  glui->add_checkbox_to_panel( display_panel2, "CMS", &(OA.show_type[3]), 0, redraw_func);
  glui->add_checkbox_to_panel( display_panel2, "CMM", &(OA.show_type[4]), 0, redraw_func);
  glui->add_checkbox_to_panel( display_panel2, "CSS", &(OA.show_type[5]), 0, redraw_func);
  glui->add_checkbox_to_panel( display_panel2, "H", &(OA.show_type[6]), 0, redraw_func);
  glui->add_checkbox_to_panel( display_panel2, "B", &(OA.show_type[7]), 0, redraw_func);


  //glui->add_checkbox_to_panel( as_detail_options_panel, "AS Background", &(fade[0]), 0, redraw_func);
  //glui->add_checkbox_to_panel( as_detail_options_panel, "Suppress From", &suppress_from, 0, redraw_func);
  //glui->add_checkbox_to_panel( as_detail_options_panel, "Suppress To", &suppress_to, 0, redraw_func);
  //glui->add_checkbox_to_panel( as_detail_options_panel, "Suppress All Related", &suppress_related, 0, redraw_func);

/*
  GLUI_Panel *realtime_panel = glui->add_panel_to_panel( panel2, "Real Time Options" );
  glui->add_button_to_panel(realtime_panel, "Change Real Time", 0, change_realtime_cb);

  receiving_box = glui->add_checkbox_to_panel( realtime_panel, "Receive Data", &receiving, 0, redraw_func);
  receiving_box->set_int_val(0);
  receiving = 0;

  minute_checkbox = glui->add_checkbox_to_panel( realtime_panel, "Minute by minute", &(C1.minutebyminute), 0, redraw_func);
  C1.minutebyminute = 1;
  minute_checkbox->set_int_val(1);
*/

  
  GLUI_Panel *preprocess_panel = glui->add_panel_to_panel( panel2, "Preprocess" );
  preprocess_begin_spinner = glui->add_spinner_to_panel( preprocess_panel, "begin date", GLUI_SPINNER_INT, &(OA.preprocess_begin), 0, redraw_func);
  preprocess_begin_spinner->set_int_limits(20000000,30000000);
  preprocess_end_spinner = glui->add_spinner_to_panel( preprocess_panel, "end date", GLUI_SPINNER_INT, &(OA.preprocess_end), 0, redraw_func);
  preprocess_end_spinner->set_int_limits(20000000,30000000);
  glui->add_button_to_panel(preprocess_panel, "Pre-Process", 0, preprocess_cb);
  

  /*
  GLUI_Panel *screendump_panel = glui->add_panel_to_panel( panel2, "Screen Dump" );
  glui->add_button_to_panel(screendump_panel, "To File", 0, screendump_cb);
*/


  /***** New panel for 3D *****/
/*
  GLUI_Panel *mode3d_panel = glui->add_panel_to_panel( panel2, "3D Mode Options" );
  showcubes_chkbx = glui->add_checkbox_to_panel(mode3d_panel, "Cubes", &show_cubes, 0, redraw_func);
  showprojection_chkbx = glui->add_checkbox_to_panel(mode3d_panel, "Projection", &show_projection, 0, redraw_func);
  showcubes_chkbx->set_int_val(1);
  showprojection_chkbx->set_int_val(1);


  GLUI_Panel *mode_panel = glui->add_panel_to_panel( panel2, "Mode" );
  mode_chkbx1 = glui->add_checkbox_to_panel(mode_panel, "Single Window", &dummy, 0, mode_cb);
  mode_chkbx3 = glui->add_checkbox_to_panel(mode_panel, "3D", &dummy, 2, mode_cb);
  mode_chkbx4 = glui->add_checkbox_to_panel(mode_panel, "AS by region", &dummy, 3, mode_cb);
  mode_chkbx5 = glui->add_checkbox_to_panel(mode_panel, "Fish-eye", &dummy, 4, mode_cb);
  mode_chkbx1->set_int_val(1);
  mode_chkbx3->set_int_val(0);
  mode_chkbx4->set_int_val(0);
  mode_chkbx5->set_int_val(0);
  window_mode = 0;
*/



  /*** Start a new column in this panel ***/
  glui->add_column_to_panel(panel2, false); /* 'false' means don't draw bar */

  GLUI_Panel *dimension_panel = glui->add_panel_to_panel( panel2, "2D or 3D" );
  dimension_chkbx[0] = glui->add_checkbox_to_panel( dimension_panel, "2D", &dummy, 0, dimension_cb);
  dimension_chkbx[1] = glui->add_checkbox_to_panel( dimension_panel, "3D", &dummy, 1, dimension_cb);
  dimension_cb(0);


  /***** Control rollout for AS focus *****/

  OA.highlighted_AS_range = 500;
  OA.highlight_AS_click_mode = OA.highlight_AS_list_mode = OA.highlight_AS_country_mode = 0;
  GLUI_Panel *display_panel = glui->add_panel_to_panel( panel2, "Highlight AS" );
  glui->add_checkbox_to_panel( display_panel, "By clicking", &(OA.highlight_AS_click_mode), 0, redraw_func);
  glui->add_checkbox_to_panel( display_panel, "By list", &(OA.highlight_AS_list_mode), 0, redraw_func);
  ASFocus0 = 0;
  ASFocus0_spinner = glui->add_spinner_to_panel( display_panel, "AS number", GLUI_SPINNER_INT, &ASFocus0, 0, redraw_func);
  ASFocus0_spinner->set_int_limits(0,65535);
  ASFocus0_spinner->set_int_val(0);
  glui->add_button_to_panel(display_panel, "Add Highlight AS", 0, highlight_AS_cb);
  glui->add_button_to_panel(display_panel, "Remove Highlight AS", 1, highlight_AS_cb);

  glui->add_checkbox_to_panel( display_panel, "By country", &(OA.highlight_AS_country_mode), 0, redraw_func);
  glui->add_edittext_to_panel(display_panel, "Country code", GLUI_EDITTEXT_TEXT, OA.CN.cname, 0, country_cb);

  OA.highlight_IP_click_mode = 0;
  OA.highlighted_IP_prefix.P.IPAddress[0] = OA.highlighted_IP_prefix.P.IPAddress[1] = 
	  OA.highlighted_IP_prefix.P.IPAddress[2] = OA.highlighted_IP_prefix.P.IPAddress[3] = 255;
  OA.highlighted_IP_prefix.P.Mask = 0;
  OA.highlighted_IP_prefix.P.GenerateText();
  GLUI_Panel *ip_panel = glui->add_panel_to_panel( panel2, "Highlight IP Prefix" );
  glui->add_checkbox_to_panel( ip_panel, "Highlight", &(OA.highlight_IP_click_mode), 0, redraw_func);
  highlight_ip_text = glui->add_statictext_to_panel(ip_panel, OA.highlighted_IP_prefix.P.text);


  GLUI_Panel *aslines_panel = glui->add_panel_to_panel( panel2, "AS Lines" );
  aslines_spinner1  = glui->add_spinner_to_panel( aslines_panel, "P1",
				 GLUI_SPINNER_INT, &(OA.S.p1), 0, redraw_func);
  aslines_spinner1->set_int_limits( 0, 65536 );  
  aslines_spinner2  = glui->add_spinner_to_panel( aslines_panel, "P1",
				 GLUI_SPINNER_INT, &(OA.S.p2), 0, redraw_func);
  aslines_spinner2->set_int_limits( 0, 65536 );  
  aslines_spinner3  = glui->add_spinner_to_panel( aslines_panel, "P1",
				 GLUI_SPINNER_INT, &(OA.S.p3), 0, redraw_func);
  aslines_spinner3->set_int_limits( 0, 65536 ); 


	/******** BEGIN REAL-TIME GLUI **********************************/

	/*
	realtime_glui = GLUI_Master.create_glui( "Real Time Options", 0, controlx, controly ); 
	realtime_panel1 = realtime_glui->add_panel( "", GLUI_PANEL_NONE );

	realtime_startdate_spinner  = realtime_glui->add_spinner_to_panel( realtime_panel1, "Start Date",
				 GLUI_SPINNER_INT, &(C1.startdate));
	realtime_starttime_spinner  = realtime_glui->add_spinner_to_panel( realtime_panel1, "Start Time",
				 GLUI_SPINNER_INT, &(C1.starttime));
	realtime_enddate_spinner  = realtime_glui->add_spinner_to_panel( realtime_panel1, "End Date",
				 GLUI_SPINNER_INT, &(C1.enddate));
	realtime_endtime_spinner  = realtime_glui->add_spinner_to_panel( realtime_panel1, "End Time",
				 GLUI_SPINNER_INT, &(C1.endtime));
	realtime_startdate_spinner->set_int_val(C1.startdate);
	realtime_starttime_spinner->set_int_val(C1.starttime);
	realtime_enddate_spinner->set_int_val(C1.enddate);
	realtime_endtime_spinner->set_int_val(C1.endtime);

	GLUI_EditText *hostname_box = realtime_glui->add_edittext_to_panel(realtime_panel1, "Remote host", GLUI_EDITTEXT_TEXT, C1.hostname_buf);
	hostname_box->set_text(C1.hostname_buf);

	realtime_glui->add_button_to_panel( realtime_panel1, "Update", 0, realtime_commit_cb);	
	realtime_glui->hide();
*/

  // for per day animation
  GLUI_Panel *perday_panel1 = perday_glui->add_panel( "", GLUI_PANEL_NONE );
  GLUI_Panel *perday_panel2 = perday_glui->add_panel_to_panel ( perday_panel1, "", GLUI_PANEL_NONE );
  GLUI_Panel *animation_panel = perday_glui->add_panel_to_panel( perday_panel2, "Animation Options" );
  date_spinner  = perday_glui->add_spinner_to_panel( animation_panel, "Date",
				 GLUI_SPINNER_INT, &(OA.current_date), 0, date_spinner_cb);
  date_spinner->set_int_limits( OA.first_date, OA.last_date );
  perday_glui->add_button_to_panel(animation_panel, "Play", 0, playbutton_cb);
  perday_glui->add_button_to_panel(animation_panel, "Stop", 0, stopbutton_cb);
  perday_glui->add_button_to_panel(animation_panel, "Advance", 0, advancebutton_cb);
  perday_glui->add_button_to_panel(animation_panel, "Back", 0, backbutton_cb);
  delay_spinner = perday_glui->add_spinner_to_panel( animation_panel, "Delay (secs)", GLUI_SPINNER_FLOAT, &delay);
  delay = 0.1;
  delay_spinner->set_float_val(0.1);
  delay_spinner->set_float_limits(0.0,10.0);
  /*
  perday_glui->add_checkbox_to_panel( animation_panel, "Make movie", &make_movie, 0, redraw_func);
  perday_glui->add_button_to_panel(animation_panel, "Make frame", 0, makeframe_cb);
  */
  GLUI_Panel *range_panel = perday_glui->add_panel_to_panel( perday_panel2, "Date range" );
  begin_date_spinner  = perday_glui->add_spinner_to_panel( range_panel, "Begin Date",
				 GLUI_SPINNER_INT, &(OA.first_date), 0, rangebutton_cb);
  begin_date_spinner->set_int_limits( 0, 30000000 );
  begin_date_spinner->set_int_val(OA.first_date);
  end_date_spinner  = perday_glui->add_spinner_to_panel( range_panel, "End Date",
				 GLUI_SPINNER_INT, &(OA.last_date), 0, rangebutton_cb);
  end_date_spinner->set_int_limits( 0, 30000000 );
  end_date_spinner->set_int_val(OA.last_date);


  // for per update animation
  GLUI_Panel *perupdate_panel1 = perupdate_glui->add_panel( "", GLUI_PANEL_NONE );
  GLUI_Panel *perupdate_panel2 = perupdate_glui->add_panel_to_panel ( perupdate_panel1, "", GLUI_PANEL_NONE );
  GLUI_Panel *perupdate_animation_panel = perupdate_glui->add_panel_to_panel( perupdate_panel2, "Animation Options" );
  perupdate_date_spinner  = perupdate_glui->add_spinner_to_panel( perupdate_animation_panel, "Date",
				 GLUI_SPINNER_INT, &(OA.current_date), 0, date_spinner_cb);
  perupdate_date_spinner->set_int_limits( OA.first_date, OA.last_date );
  perupdate_time_spinner  = perupdate_glui->add_spinner_to_panel( perupdate_animation_panel, "Time",
				 GLUI_SPINNER_INT, &(OA.perupdate_time), 0, time_spinner_cb);
  perupdate_time_spinner->set_int_limits( 0, 1000000 );
  perupdate_window_spinner  = perupdate_glui->add_spinner_to_panel( perupdate_animation_panel, "Window",
				 GLUI_SPINNER_INT, &(OA.perupdate_window), 0, window_spinner_cb);
  perupdate_window_spinner->set_int_limits( 0, 1000000 );
  perupdate_incr_spinner  = perupdate_glui->add_spinner_to_panel( perupdate_animation_panel, "Increment",
				 GLUI_SPINNER_INT, &(OA.perupdate_incr), 0, incr_spinner_cb);
  perupdate_incr_spinner->set_int_limits( 0, 1000000 );
  OA.perupdate_window = OA.perupdate_incr = 1;
  perupdate_window_spinner->set_int_val(1);
  perupdate_incr_spinner->set_int_val(1);
  perupdate_chkbx[0] = perupdate_glui->add_checkbox_to_panel(perupdate_animation_panel, 
	  "entry", &dummy, 0, perupdate_chkbx_cb);
  perupdate_chkbx[1] = perupdate_glui->add_checkbox_to_panel(perupdate_animation_panel, 
	  "time", &dummy, 1, perupdate_chkbx_cb);
  perupdate_chkbx[0]->set_int_val(1);
  perupdate_chkbx[1]->set_int_val(0);
  OA.perupdate_incr_type = 0;
  perupdate_glui->add_button_to_panel(perupdate_animation_panel, "Play", 0, perupdate_playbutton_cb);
  perupdate_glui->add_button_to_panel(perupdate_animation_panel, "Stop", 0, perupdate_stopbutton_cb);
  perupdate_glui->add_button_to_panel(perupdate_animation_panel, "Advance", 0, perupdate_advancebutton_cb);
  perupdate_glui->add_button_to_panel(perupdate_animation_panel, "Back", 0, perupdate_backbutton_cb);
  perupdate_glui->hide();


	// for dynamics animation
  GLUI_Panel *dynamics_panel1 = dynamics_glui->add_panel( "", GLUI_PANEL_NONE );
  GLUI_Panel *dynamics_panel2 = dynamics_glui->add_panel_to_panel ( dynamics_panel1, "", GLUI_PANEL_NONE );
  GLUI_Panel *dynamics_display_panel = dynamics_glui->add_panel_to_panel ( dynamics_panel2, "Display" );
  
  DV.show_timeline = 1;
  dynamics_display_chkbx[0] = dynamics_glui->add_checkbox_to_panel( dynamics_display_panel, "Time Line", &(DV.show_timeline), 0, redraw_func);

  GLUI_Panel *dynamics_display_panel2 = dynamics_glui->add_panel_to_panel ( dynamics_display_panel, "Auxiliary" );

  dynamics_aux_chkbx[0] = dynamics_glui->add_checkbox_to_panel( dynamics_display_panel2, "Arcs", &dummy, 0, dynamics_aux_cb);
  dynamics_aux_chkbx[1] = dynamics_glui->add_checkbox_to_panel( dynamics_display_panel2, "Measures", &dummy, 1, dynamics_aux_cb);
  dynamics_aux_chkbx[2] = dynamics_glui->add_checkbox_to_panel( dynamics_display_panel2, "Network", &dummy, 2, dynamics_aux_cb);
  dynamics_aux_chkbx[3] = dynamics_glui->add_checkbox_to_panel( dynamics_display_panel2, "3D Network", &dummy, 3, dynamics_aux_cb);
  dynamics_aux_chkbx[4] = dynamics_glui->add_checkbox_to_panel( dynamics_display_panel2, "Comparison", &dummy, 4, dynamics_aux_cb);
  DV.aux_mode = 0;

  DV.show_events = 1;
  dynamics_display_chkbx[1] = dynamics_glui->add_checkbox_to_panel( dynamics_display_panel, "Signatures", &(DV.show_events), 0, redraw_func);

  dynamics_aux_cb(0);

  GLUI_Panel *dynamics_animation_panel = dynamics_glui->add_panel_to_panel ( dynamics_panel2, "Animation" );
  dynamics_date_spinner  = dynamics_glui->add_spinner_to_panel( dynamics_animation_panel, "Date",
				 GLUI_SPINNER_INT, &(DV.current_date), 0, dynamics_date_spinner_cb);
  dynamics_date_spinner->set_int_limits( DV.first_date, DV.last_date );
  dynamics_glui->add_button_to_panel(dynamics_animation_panel, "Play", 0, dynamics_playbutton_cb);
  dynamics_glui->add_button_to_panel(dynamics_animation_panel, "Stop", 0, dynamics_stopbutton_cb);
  dynamics_glui->add_button_to_panel(dynamics_animation_panel, "Advance", 0, dynamics_advancebutton_cb);
  dynamics_glui->add_button_to_panel(dynamics_animation_panel, "Back", 0, dynamics_backbutton_cb);

  dynamics_glui->hide();



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

}

