
#ifndef SIGNATURE_H
#define SIGNATURE_H

#define MAX_N_EVENTS 256
#define SHORTLONG 1200

class SignatureEvent {

public:

	
	int sy, sm, sd, sh, smin;
	int ey, em, ed, eh, emin;

	int Flag;
	int spath, epath;
	int npaths;
	float maxT;

	SignatureEvent() : Flag(0) , npaths(0) { };

	void AddAnn(int p) {
		epath = p;
		if (npaths==0) spath = p;
		npaths++;
	};
	
	void SettleStartEnd(Graph *gptr) {

		sy = gptr->paths[spath]->year;
		sm = gptr->paths[spath]->month;
		sd = gptr->paths[spath]->day;
		sh = gptr->paths[spath]->hour;
		smin = gptr->paths[spath]->min;
		ey = gptr->paths[epath]->year;
		em = gptr->paths[epath]->month;
		ed = gptr->paths[epath]->day;
		eh = gptr->paths[epath]->hour;
		emin = gptr->paths[epath]->min;

	};


};


class Signature {

public:

	SignatureEvent EArray[MAX_N_EVENTS];

	float startx, starty, xsize, ysize;

	int nevents;
	float thres;

	int thres_screen_start;
	int thres_screen_end;
	int thres_screen_current;

	Signature() : nevents(0) , thres_screen_start(600), thres_screen_end(700) { };

	void SetThreshold(int y) {

		if (y < thres_screen_start) y = thres_screen_start;
		if (y > thres_screen_end) y = thres_screen_end;

		thres = (float)(y - thres_screen_start)/(float)(thres_screen_end - thres_screen_start);
		thres = thres * 3.0;

		thres_screen_current = y;

	};

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

	void Display() {

		int j;
		char buf[32];

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluOrtho2D(0.0,xsize,0.0,ysize);
				// 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);

		glColor3f(1.0,0.0,0.0);
		glLineWidth(3);
		glBegin(GL_LINES);
		glVertex3f(800.0,thres_screen_start,0.9);
		glVertex3f(800.0,thres_screen_end,0.9);
		glEnd();
		glBegin(GL_LINES);
		glVertex3f(790.0,thres_screen_current,0.9);
		glVertex3f(810.0,thres_screen_current,0.9);
		glEnd();

		sprintf(buf,"%f",thres);
		glColor3f(1.0,0.0,0.0);
		for (j=0;j<strlen(buf);j++) {
			glRasterPos3f(820.0+8.0*(float)j,thres_screen_current,0.9);
			glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10,buf[j]);
		}


	};


	int attrssame(Path *p1, Path *p2) {
		int i;
		int r;
		r = 1; // assume same
		for (i=0;i<5;i++) {
			if (strcmp(p1->attributes[i],p2->attributes[i])!=0) {
				r = 0;
			}
		}
		return r;
	};


	void OutputEvents(char *fname) {
		FILE *fptr;
		int i,j;
		char flagstring[32];
		fptr = fopen(fname,"wt");
		fprintf(fptr,"%d\n", nevents);
		for (i=0;i<nevents; i++) {
			for (j=0;j<9;j++) {
				if ((EArray[i].Flag & (1 << j)) != 0) {
					flagstring[j] = '1';
				} else {
					flagstring[j] = '0';
				}
			}
			flagstring[9] = '\0';
			fprintf(fptr,"%d %d %d %d %d %d %d %d %d %d %s %d %d %f\n",
				EArray[i].sy, EArray[i].sm, EArray[i].sd, EArray[i].sh, EArray[i].smin,
				EArray[i].ey, EArray[i].em, EArray[i].ed, EArray[i].eh, EArray[i].emin,  
				flagstring, EArray[i].spath, EArray[i].npaths, EArray[i].maxT);
		}
		fclose(fptr);

	};

	void GenerateTempEvents(Graph *gptr) {

		int i,j;

		if (nevents > 0) nevents = 0;
		for (i=1; i<gptr->num_sigan; i++) {
			EArray[nevents].Flag = 0;
			EArray[nevents].spath = gptr->sigans[i].start;
			EArray[nevents].epath = gptr->sigans[i].end;
			EArray[nevents].npaths = gptr->sigans[i].end - gptr->sigans[i].start + 1;
			EArray[nevents].maxT = 0.0;
			for (j=gptr->sigans[i].start; j<gptr->sigans[i].end; j++) {
				if (gptr->paths[j]->T > EArray[nevents].maxT) {
					EArray[nevents].maxT = gptr->paths[j]->T;
				}
			}
			for (j=0;j<10;j++) {
				if (gptr->sigans[i].flags[j] > (unsigned char)0) {
					EArray[nevents].Flag = EArray[nevents].Flag | (1 << (j-1));
				}
			}
			nevents++;
		}
		
		for (i=0; i<nevents;i++) {
			// for each event, finalize start and end times
			EArray[i].SettleStartEnd(gptr);
		}
	};


	void GenerateOnlyEvents(Graph *gptr) {

		int i,j;

		if (nevents > 0) nevents = 0;
		for (i=1; i<gptr->num_siggroups; i++) {
			EArray[nevents].Flag = 0;
			EArray[nevents].spath = gptr->siggroups[i].start;
			EArray[nevents].epath = gptr->siggroups[i].end;
			EArray[nevents].npaths = gptr->siggroups[i].end - gptr->siggroups[i].start + 1;
			EArray[nevents].maxT = 0.0;
			for (j=gptr->siggroups[i].start; j<gptr->siggroups[i].end; j++) {
				if (gptr->paths[j]->T > EArray[nevents].maxT) {
					EArray[nevents].maxT = gptr->paths[j]->T;
				}
			}
			for (j=0;j<10;j++) {
				if (gptr->siggroups[i].flags[j] > (unsigned char)0) {
					EArray[nevents].Flag = EArray[nevents].Flag | (1 << (j-1));
				}
			}
			nevents++;
		}
		
		for (i=0; i<nevents;i++) {
			// for each event, finalize start and end times
			EArray[i].SettleStartEnd(gptr);
		}
	};

	void GenerateSigAnEvents(Graph *gptr) {

		int i,j;

		gptr->num_siggroups = 0;

		for (i=1; i<gptr->npaths; i++) {
			if (gptr->paths[i]->T > thres) {
				gptr->CreateSignatureGroup(i);
			}
		}

		GenerateOnlyEvents(gptr);

	};


	void GenerateKeEvents(Graph *gptr) {

		int i, j;
		int currentlyactive;
		int type_array[6]; // 6 classes
		if (nevents > 0) nevents = 0;
		currentlyactive = 0;
		for (i=1; i<gptr->npaths; i++) {
			for (j=0;j<6;j++) type_array[j] = 0; // clear type array
			if (gptr->paths[i]->T > thres) {
				if (!currentlyactive) {
					nevents++;
					EArray[nevents-1].Flag = 0;
					EArray[nevents-1].npaths = 0;
					EArray[nevents-1].maxT = 0.0;
					currentlyactive = 1;
				}	
				EArray[nevents-1].AddAnn(i);
				if (gptr->paths[i]->T > EArray[nevents-1].maxT) {
					EArray[nevents-1].maxT = gptr->paths[i]->T;
				}
				if (gptr->paths[i]->sig > 0) {
					EArray[nevents-1].Flag = EArray[nevents-1].Flag | (1 << gptr->paths[i]->sig);
				}
			} else {
				if (currentlyactive) currentlyactive = 0;
			}
		}

		for (i=0; i<nevents;i++) {
			// for each event, finalize start and end times
			EArray[i].SettleStartEnd(gptr);
		}

	};



};

#endif

