#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <signal.h>

FILE *log_file;
FILE *nist_output;
double average_interval, start_time, current_time, last_time;

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

 struct timespec req;
 struct timespec rem;

 struct timeval start_tv;
 struct timeval current_tv;
 struct timeval last_tv;
 struct timezone tz;

 int n;
 char sys_call[100]; 
 char nist_file[10];
 char scan_it[300];
 int n_drops;
 long nanos;

 void interrupt_handler();
  signal(SIGINT, interrupt_handler); /* signal 2, INT */

 if(argc != 5) {
   fprintf(stderr,"%s src dst time log_file\n", argv[0]);
   fprintf(stderr,"where:  src - source host\n");
   fprintf(stderr,"dst - destination host\n");
   fprintf(stderr,"time - time in milliseconds\n");
   fprintf(stderr,"log_file - file to log to\n");
   fprintf(stderr,"Every time ms will call nistnet and log statistics\n");
   fprintf(stderr,"for src dst connection par\n");
   exit(-1);
  }

  log_file = fopen (argv[4],"w");
   
  if(log_file == NULL) {
    fprintf(stderr, "Error opening the log file for writing\n");
    exit(-1);
  }

  // check that the time isn't too long
  nanos = 1000000 * atoi(argv[3]);

  if (nanos >= 1000000000) {
    fprintf(stderr, "That's too long of a time...\n");
    fprintf(stderr, "Time must be less than 1000000 ms \n");
    exit(-1);
  }

  // set up the string for use in system
  sprintf(sys_call, 
          "/usr/local/bin/cnistnet -s %s %s > cnistnet_out", 
          argv[1], argv[2]);

  sprintf(nist_file, "cnistnet_out");

  // check to make sure that nist net has this entry
  // and that we can read it's output
  system(sys_call);
  nist_output = fopen (nist_file, "r");

  if(nist_output == NULL) {
    fprintf(stderr, "Can't open the nistnet output file\n");
    exit(-1);
  }

  for (n=0; n < 18; n++) {
    fscanf(nist_output, "%s", scan_it);
  }
  if(fscanf(nist_output, "%s", scan_it) == -1) {
    fprintf(stderr, "Bad host pair\n");
    exit(-1);
  }
  fclose(nist_output);

  // prep the log file
  system(sys_call);
  nist_output = fopen (nist_file, "r");

  if(nist_output == NULL) {
    fprintf(stderr, "Can't open the nistnet output file\n");
    exit(-1);
  }
  for (n=0; n < 5; n++) {
    fscanf(nist_output, "%s", scan_it);
    fprintf(log_file, "%s ", scan_it); 
  } 
  fprintf(log_file, "\n");
  fprintf(log_file, "time_ms\ttime_s\t");
  for (n=6; n < 12; n++) {
    fscanf(nist_output, "%s", scan_it);
    fprintf(log_file, "%s\t", scan_it);
  }
  fscanf(nist_output, "%s", scan_it);
  fprintf(log_file, "%s_", scan_it);
  fscanf(nist_output, "%s", scan_it);
  fprintf(log_file, "%s\t", scan_it);

  for (n=13; n < 16; n++) {
    fscanf(nist_output, "%s", scan_it);
    fprintf(log_file, "%s\t", scan_it);
  }
  fscanf(nist_output, "%s", scan_it);
  fprintf(log_file, "%s_", scan_it);
  fscanf(nist_output, "%s", scan_it);
  fprintf(log_file, "%s\t", scan_it);

  fprintf(log_file, "abstime");

  fprintf(log_file, "\n");

  fclose(nist_output);

  // set up the time structures
  req.tv_sec = (time_t) 0;
  req.tv_nsec = nanos;
  //  printf("Granulatiry set to: %s ms or %d ns\n", argv[3], req.tv_nsec);
  printf("Gathering statistics\n");


  system(sys_call);
  nist_output = fopen (nist_file, "r");

  for (n=0; n < 18; n++) {
    fscanf(nist_output, "%s", scan_it);
  }

  gettimeofday(&start_tv, NULL);
  start_time = (double)start_tv.tv_sec +
               ((double)start_tv.tv_usec)/1000000.0;
  last_time = start_time;
  
  fprintf(log_file, "%.2f\t%.2f\t", 0.0,0.0);
  for (n=0; n < 11; n++) {
    fscanf(nist_output, "%s", scan_it);
    fprintf(log_file, "%s\t", scan_it);
  }
  fprintf(log_file, "%d\t", start_tv.tv_sec);
  fprintf(log_file, "\n");
  sprintf(scan_it,"%d",-1);
  fclose(nist_output);
  n = nanosleep(&req, NULL);
  if(n != 0) printf ("nanosleep: %d signal sentwhilesleeping\n",n);

  while (1==1) {  
    system(sys_call);
    nist_output = fopen (nist_file, "r");

    for (n=0; n < 18; n++) {
      fscanf(nist_output, "%s", scan_it);
    }
    
    // Check to see if something is messed up
    if(strcmp(scan_it, "-1") != 0) {

      gettimeofday(&current_tv, NULL);
      current_time = (double)current_tv.tv_sec +
                     ((double)current_tv.tv_usec)/1000000.0;
      //printf("Interval: %f\n", current_time - last_time);
      average_interval = (average_interval + (current_time-last_time))/2;

      last_time = current_time;  

      fprintf(log_file, "%.2f\t%.2f\t", (current_time-start_time)*1000, 
                                         current_time-start_time);
      for (n=0; n < 11; n++) {
        fscanf(nist_output, "%s", scan_it);
        fprintf(log_file, "%s\t", scan_it);
      }
      fprintf(log_file, "%d\t", current_tv.tv_sec);
      fprintf(log_file, "\n");
      sprintf(scan_it,"%d",-1);
      fclose(nist_output);
      n = nanosleep(&req, NULL);
      if(n != 0) printf ("nanosleep: %d signal sentwhilesleeping\n",n);
    } else {
      fclose(nist_output);
      interrupt_handler();
    }
  }

  fclose(log_file);
}

void interrupt_handler() {
  printf("Average interval: %f\n", average_interval);
  printf("Closing log file and exiting...\n");
  fclose(log_file);
  system("rm -rf /tmp/cnistnet_out");
  exit(1);
}
