
#include "glut.h"
#include "glui.h"

#include "structures.h"

extern ASList AL1;

int ASChange::minAS = 1000;
int ASChange::maxAS = 0;


extern int begin_date;
extern int show_date;

float datetofloat(int d, int d2) {
	int n = 0;
	int n2 = 0;
	// day
	n += (d%100) - (begin_date%100);
	// month
	n += 31 * ((d%10000)/100 - (begin_date%10000)/100);
	// year
	n += 365 * (d/10000 - begin_date/10000);
	// day
	n2 += (d2%100) - (begin_date%100);
	// month
	n2 += 31 * ((d2%10000)/100 - (begin_date%10000)/100);
	// year
	n2 += 365 * (d2/10000 - begin_date/10000);
	return (float)n/(float)n2;
}


int date_off(int d1,int off) {

	int d2, sign, day, month, year;

	// convert the off to day, month and year

	sign = 0;
	if (off<0) {
		off = -off;
		sign = 1;
	}
	year = 0;
	while (off>365) {
		year++;
		off -= 365;
	}
	month = 0;
	while (off>31) {
		month++;
		off -= 31;
	}
	day = off;

	// convert the d1 to day, month and year

	if (sign==0) {
		day = day + (d1 % 100);
		month = month + ((d1 % 10000) / 100)%100;
		year = year + (d1 / 10000);
		while (day>31) {
			month++;
			day-=31;
		}
		while (month>12) {
			year++;
			month-=12;
		}
	} else {
		day = day - (d1 % 100);
		month = month - ((d1 % 10000) / 100)%100;
		year = year - (d1 / 10000);
		while (day<0) {
			month--;
			day+=31;
		}
		while (month<0) {
			year--;
			month+=12;
		}
	} 

	d2 = day + (month*100) + (year*10000);

	return d2;

}


int datediff(int d1, int d2) {

	int day, month, year;

	day = d1%100 - d2%100;
	month = ((d1%10000 - d2%10000) / 100) % 100;
	year = d1 / 10000 - d2 / 10000;

	return (day + month*12 + year*365);


}


// read one line of the input file
int ASChange::ReadInput(FILE *fptr) {

  char buffer[128];
  char nextchar;
  int counter;
  int i;

  // read the type

  counter = 0;
  nextchar = (char)getc(fptr);
  if (feof(fptr)) return 1;
  while (nextchar!=':') {
    buffer[counter] = nextchar;
    nextchar = (char)getc(fptr);
    if (feof(fptr)) return 1;
    counter++;
  }

/*

  if ((buffer[0]=='C') && (buffer[1]=='S') && (buffer[2]=='S')) {
	  printf("CSS read\n");
  }

*/


  if ((buffer[0]=='O') && (buffer[1]=='S')) {
	type = OS;
  } else if ((buffer[0]=='O') && (buffer[1]=='M')) {
	type = OM;
  } else if (buffer[0]=='B') {
    type = BSS;
  } else if (buffer[0]=='H') {
    type = HSS;
  } else if ((buffer[0]=='C') && (buffer[1]=='S') && (buffer[2]=='M')) {
    type = CSM;
  } else if ((buffer[0]=='C') && (buffer[1]=='M') && (buffer[2]=='S')) {
    type = CMS;
  } else if ((buffer[0]=='C') && (buffer[1]=='M') && (buffer[2]=='M')) {
    type = CMM;
  } else if ((buffer[0]=='C') && (buffer[1]=='S') && (buffer[2]=='S')) {
	type = CSS;
  }


  // read the each byte of the IP address

  for (i=0;i<4;i++) {  
    counter = 0;
    nextchar = (char)getc(fptr);
    if (feof(fptr)) return 1;
    while ((nextchar!='.')&&(nextchar!='/')) {
      buffer[counter] = nextchar;
      nextchar = (char)getc(fptr);
      if (feof(fptr)) return 1;
      counter++;
    }
    buffer[counter] = '\0';
    IPAddress[i] = (unsigned char)atoi(buffer);
  }

  // read the mask

  counter = 0;
  nextchar = (char)getc(fptr);
  if (feof(fptr)) return 1;
  while ((nextchar!=' ')&&(nextchar!='*')&&(nextchar!='\t')) {
    buffer[counter] = nextchar;
    nextchar = (char)getc(fptr);
    if (feof(fptr)) return 1;
    counter++;
  }
  buffer[counter] = '\0';
  Mask = atoi(buffer);

  // read the Autonomous System numbers

  if (nextchar=='*') nextchar = (char)getc(fptr);

  nextchar = (char)getc(fptr);

  if (nextchar == '(') {
	  while (nextchar != ')') nextchar = (char)getc(fptr);
	  nextchar = (char)getc(fptr);
  }

  counter = 0;
  nextchar = (char)getc(fptr);
  if (feof(fptr)) return 1;
  while ((nextchar!=' ')&&(nextchar!='*')&&(nextchar!='\t')&&(nextchar!=',')) {
    buffer[counter] = nextchar;
    nextchar = (char)getc(fptr);
    if (feof(fptr)) return 1;
    counter++;
  }
  buffer[counter] = '\0';
  AS = atoi(buffer);

  AL1.NumIPChange[AS]++;

  // read and ignore rest of the line

  fgets(buffer,128,fptr);

  if (feof(fptr)) { 
    return 1;
  } else {
    return 0;
  }

}

void ASChange::Print() {

  printf("AS Change %d %d %d %d Mask %d\n", IPAddress[0], 
	 IPAddress[1], IPAddress[2],
	 IPAddress[3], Mask);

}

void ASChange::MatrixPos(int &x, int &y) {

  int xupper, xlower, yupper, ylower;
  int i, n;

  xupper = yupper = 511;
  xlower = ylower = 0;

  for (i=0;i<4;i++) {
    n = (IPAddress[0] >> ((3-i)*2)) & 3;
    if (n&1) { 
      xlower += (1+xupper-xlower)/2;
    } else {
      xupper = xlower + (1+xupper-xlower)/2 - 1;
    }
    if (n&2) {
      ylower += (1+yupper-ylower)/2;
    } else {
      yupper = ylower + (1+yupper-ylower)/2 - 1;
    }
  } 

  for (i=0;i<4;i++) {
    n = (IPAddress[1] >> ((3-i)*2)) & 3;
    if (n&1) { 
      xlower += (1+xupper-xlower)/2;
    } else {
      xupper = xlower + (1+xupper-xlower)/2 - 1;
    }
    if (n&2) {
      ylower += (1+yupper-ylower)/2;
    } else {
      yupper = ylower + (1+yupper-ylower)/2 - 1;
    }
  } 

  n = (IPAddress[2] >> 6) & 3;
  if (n&1) {
    x = xupper;
  } else {
    x = xlower;
  }
  if (n&2) {
    y = yupper;
  } else {
    y = ylower;
  }

}


void ASChange::PutInMatrix(DisplayMatrix *m) {
	int x,y;
	MatrixPos(x,y);
	m->n[x][y] = m->n[x][y] + 1;
}

void ASChange::DetailMatrixPos(int bit, int &xlower, int &xupper, int &ylower, int &yupper, int xdim, int ydim) {

  int i, n;
  int ind, b;

  xupper = xdim;
  yupper = ydim;
  xlower = ylower = 0;

  //printf("draw detail mask ip %d %d %d %d mask %d\n",(int)IPAddress[0],(int)IPAddress[1],(int)IPAddress[2],(int)IPAddress[3],Mask);

  while (bit<Mask) {
	  // find out which of 4 parts of IP address to examine
	  ind = bit/8;
	  // find out which bit in this part we want to examine
	  b = 7 - bit%8;
	  // update the x and y ranges
	  if (!(b%2)) { // if b is an odd bit, change x range
		  if ( ( IPAddress[ind] >> b ) & 1 ) {
			  xlower += (1+xupper-xlower)/2;
		  } else {
			  xupper = xlower + (1+xupper-xlower)/2 - 1;
		  }
	  } else { // if b is an even bit, change y range
		  if ( ( IPAddress[ind] >> b ) & 1 ) {
			  ylower += (1+yupper-ylower)/2;
		  } else {
			  yupper = ylower + (1+yupper-ylower)/2 - 1;
		  }
	  }
	bit++;
  }

}


void ASChange::DrawInDetailMatrix(int bit, int xdim, int ydim) {
	int xlower,xupper,ylower,yupper;
	float fdate;
	DetailMatrixPos(bit,xlower,xupper,ylower,yupper,xdim,ydim);
	fdate = datetofloat(cdate,show_date);
	if (type==OS) {
		glColor3f(1.0,0.0,1.0);
	} else if (type==CMS) {
		glColor3f(1.0,1.0,0.0);
	} else if (type==CSM) {
		glColor3f(0.0,1.0,1.0);
	} else if (type==CMM) {
		glColor3f(1.0,0.0,0.0);
	} else if (type==HSS) {
		glColor3f(0.0,0.0,1.0*fdate);
	} else if (type==BSS) {
		glColor3f(0.0,1.0*fdate,0.0);
	} else if (type==OM) {
		glColor3f(1.0,1.0,0.0);
	} else if (type==CSS) {
		glColor3f(0.2,0.8,0.5);
	}


	glBegin(GL_QUADS);
		glVertex3f(xlower,ylower,fdate);
		glVertex3f(xlower,yupper,fdate);
		glVertex3f(xupper,yupper,fdate);
		glVertex3f(xupper,ylower,fdate);
	glEnd();
}



ASChange &ASChange::operator=(const ASChange &rhs) {
	int i;
	type = rhs.type;
	from = rhs.from;
	to = rhs.to;
	for (i=0;i<4;i++) {
		IPAddress[i] = rhs.IPAddress[i];
	}
	Mask = rhs.Mask;
	AS = rhs.AS;
	cdate = rhs.cdate;
	return *this;
}

