# include <ohana.h>
# include <loneos.h>

main (argc, argv)
int argc;
char **argv;
{

  char filename[64], line[64];
  int Nitems, nitems, status;
  int i, Nmeas, Nmiss, Naverage, Nmeasure, Nmissing;
  FILE *f;
  Average *average;
  Measure *measure;
  Missing *missing;
  Header header;

  if (argc != 2) {
    fprintf (stderr, "USAGE: fixcpt (filename)\n");
    exit (1);
  }

  check_permissions (argv[1]);

  /* read catalog header */
  if (!fits_read_header (argv[1], &header)) {
    fprintf (stderr, "error loading file %s\n", argv[1]);
    exit (1);
  }

  f = fopen (argv[1], "r");
  if (f == (FILE *) NULL) {
    fprintf (stderr, "ERROR: can't open catalog file: %s\n", argv[1]);
    exit (1);
  }
  fseek (f, header.size, SEEK_SET); 

  /** find number of stars, measurements **/
  Nmissing = Naverage = Nmeasure = 0;
  fits_scan (&header, "NSTARS", "%d", 1, &Naverage);
  fits_scan (&header, "NMEAS", "%d", 1, &Nmeasure);
  fits_scan (&header, "NMISS", "%d", 1, &Nmissing);
  ALLOCATE (average, Average, MAX (Naverage, 1));
  ALLOCATE (measure, Measure, MAX (Nmeasure, 1));
  ALLOCATE (missing, Missing, MAX (Nmissing, 1));
  if (Naverage == 0) {
    fprintf (stderr, "no stars yet in catalog %s\n", argv[1]);
    fclose (f);
    exit (0);
  }

  /* read average values */
  Nitems = Naverage;
  nitems = Fread (average, sizeof(Average), Nitems, f, "average");
  if (nitems != Nitems) {
    fprintf (stderr, "ERROR: failed to read data from catalog file %s (1)\n", argv[1]);
    exit (1);
  }
  
  /* read measurements */
  Nitems = Nmeasure;
  nitems = Fread (measure, sizeof(Measure), Nitems, f, "measure");
  if (nitems != Nitems) {
    fprintf (stderr, "ERROR: failed to read data from catalog file %s (2)\n", argv[1]);
    exit (1);
  }
  
  /* read missing */
  Nitems = Nmissing;
  nitems = Fread (missing, sizeof(Missing), Nitems, f, "missing");
  if (nitems != Nitems) {
    fprintf (stderr, "ERROR: failed to read data from catalog file %s (3)\n", argv[1]);
    exit (1);
  }
  
  fprintf (stderr, "read %d stars from catalog file %s (%d measurements, %d missing)\n", 
	   Naverage, argv[1], Nmeasure, Nmissing);

  for (i = Nmeas = Nmiss = 0; i < Naverage; i++) {
    Nmeas += average[i].Nm; 
    Nmiss += average[i].Nn; 
  }
  if ((Nmeas != Nmeasure) || (Nmiss != Nmissing)) {
    fprintf (stderr, "ERROR: data in catalog %s is corrupt, sums don't check\n");
    fprintf (stderr, "ERROR: Nmeas: %d, %d\n", Nmeas, Nmeasure);
    fprintf (stderr, "ERROR: Nmiss: %d, %d\n", Nmiss, Nmissing);
    exit (1);
  }
  fclose (f);


  for (i = 0; i < Nmeasure; i++) {
    if (measure[i].t > 0) {
      fixtime (&measure[i].t);
    }
  }

  for (i = 0; i < Nmissing; i++) {
    if (missing[i].t > 0) {
      fixtime (&missing[i].t);
    }
  }

  /* write out file */
  /* save old file */
  sprintf (line, "mv %s %s.UT\0", argv[1], argv[1]);
  status = system (line);
  if (status) {
    fprintf (stderr, "ERROR: unable to create %s.UT, exiting\n", argv[1]);
    exit (1);
  }

  f = fopen (argv[1], "w");
  if (f == NULL) {
    fprintf (stderr, "ERROR: can't create new catalog file: %s\n", argv[1]);
    exit (1);
  }
  
  nitems = Fwrite (header.buffer, 1, header.size, f, "char");
  if (nitems != header.size) {
    fprintf (stderr, "ERROR: failed to write header\n");
    exit (1);
  }

  Nitems = Naverage;
  nitems = Fwrite (average, sizeof(Average), Nitems, f, "average");
  if (nitems != Nitems) {
    fprintf (stderr, "ERROR: failed to write catalog file aves %s\n", argv[1]);
    exit (1);
  }
  
  Nitems = Nmeasure;
  nitems = Fwrite (measure, sizeof(Measure), Nitems, f, "measure");
  if (nitems != Nitems) {
    fprintf (stderr, "ERROR: failed to write catalog file meas %s\n", argv[1]);
    exit (1);
  }

  Nitems = Nmissing;
  nitems = Fwrite (missing, sizeof(Missing), Nitems, f, "missing");
  if (nitems != Nitems) {
    fprintf (stderr, "ERROR: failed to write catalog file miss %s\n", argv[1]);
    exit (1);
  }

  fclose (f);

  exit (0);

}

  


check_permissions (char *basefile) {
  
  FILE *f;
  char *c, dir[256], filename[256];
  struct stat filestat;
  uid_t fuid, uid;
  gid_t fgid, gid;
  int status;

  uid = getuid();
  gid = getgid();

  /* check permission to write to directory */
  sprintf (filename, "%s\0", basefile);
  c = strrchr (filename, '/');
  if (c == (char *) NULL) {
    strcpy (dir, ".");
  } else {
    *c = 0;
    strcpy (dir, filename);
  }
  status = stat (dir, &filestat);
  if (status == -1) {
    fprintf (stderr, "ERROR: can't write to %s\n", dir);
    exit (1);
  } 
  if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRWXU)) ||
      ((gid == filestat.st_gid) && (filestat.st_mode & S_IRWXG)) || 
      (filestat.st_mode & S_IRWXO)) {
  } else {
    fprintf (stderr, "ERROR: can't write to %s\n", dir);
    exit (1);
  }
  
  /* check permission to write to file */
  sprintf (filename, "%s\0", basefile);
  status = stat (filename, &filestat);
  if (status == 0) { /* file exists, are permissions OK? */
    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
    } else {
      fprintf (stderr, "ERROR: can't write to %s\n", filename);
      exit (1);
    }
  }
  
  /* check permission to write to backup file */
  sprintf (filename, "%s.UT\0", basefile);
  status = stat (filename, &filestat);
  if (status == 0) { /* file exists, we should exit! */
    fprintf (stderr, "ERROR: %s already exists, already fixed times\n", filename);
    exit (1);
  }
  
}


fixtime (unsigned int *T) {

  struct tm now, *gmt;
  unsigned int t, Nsec;
  double jd;

  t = *T;

  gmt   = gmtime (&t);
  now = gmt[0];

  /* fix problems with DST dates */
  if (((now.tm_mon == 3) && (now.tm_mday >  5)) || 
      ((now.tm_mon >  3) && (now.tm_mon  <  9)) || 
      ((now.tm_mon == 9) && (now.tm_mday < 26))) {
    now.tm_hour += 1;
  }

  /* now subtract one month to get original month */
  
  now.tm_mon -= 1;
  /* fix year error */
  if (now.tm_mon == -1) {
    now.tm_mon = 11;
    now.tm_year -= 1;
  }

  /* special days:
     980331 -> 98 04 01 --> 98 02 31
     980131 -> 98 02 03 --> 98 00 31 
     */

  if ((now.tm_mon == 4) && (now.tm_mday == 1)) {
    now.tm_mon = 2;
    now.tm_mday = 31;
  }

  if ((now.tm_mon == 2) && (now.tm_mday == 3)) {
    now.tm_mon = 0;
    now.tm_mday = 31;
  }

  /* we now have year,mon-1,mday,hour,min,sec all correct.
     now convert to JD and from there to seconds. */

  jd = now.tm_mday - 32075 + (int)(1461*(1900 + now.tm_year + 4800 + (int)(((now.tm_mon+1)-14)/12))/4)
    + (int)(367*((now.tm_mon+1) - 2 - (int)(((now.tm_mon+1) - 14)/12)*12)/12)
    - (int)(3*(int)((1900 + now.tm_year + 4900 + (int)(((now.tm_mon+1) - 14)/12))/100)/4) - 0.5;
  
  Nsec = (jd - 2440587.5)*86400 + 3600.0*now.tm_hour + now.tm_min*60.0 + now.tm_sec;
  *T = Nsec;

  /*
  fprintf (stderr, "%d -> %02d/%02d/%02d %02d:%02d:%02d -> %d\n",
	   t, 
	   now.tm_year, now.tm_mon+1, now.tm_mday, 
	   now.tm_hour, now.tm_min, now.tm_sec, Nsec);
	   */
}
