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

/* the function in this file uses the old definition of Catalog,
   and is deprecated by the new locking scheme */

typedef struct {
  Average *average;
  Measure *measure; 
  Missing *missing; 
  SecFilt *secfilt;
  Header  header;
  int Naverage, Nmeasure, Nmissing, Nsecfilt;
  int *found;
  int *image;
  float *X, *Y;
} Catalog;

Measure *FixOldMeasure (OldMeasure *in, int Nvalues) {

  int i;
  Measure *out;

  ALLOCATE (out, Measure, Nvalues);

  for (i = 0; i < Nvalues; i++) {
    out[i].dR = in[i].dR;
    out[i].dD = in[i].dD;
    out[i].M  = in[i].M;
    out[i].dM = in[i].dM;
    out[i].Mcal = in[i].Mcal;
    out[i].dophot = in[i].dophot;
    out[i].source = in[i].source;
    out[i].t = in[i].t;

    out[i].dt = 0xffff;
    out[i].averef = in[i].average & 0x00ffffff;
    out[i].flags  = (in[i].average & 0xff000000) >> 24;
  }

  free (in);
  
  return (out);
}

Average *FixOldAverage (OldAverage *in, int Nvalues) {

  int i;
  Average *out;

  ALLOCATE (out, Average, Nvalues);

  for (i = 0; i < Nvalues; i++) {
    out[i].R       = in[i].R;      
    out[i].D       = in[i].D;      
    out[i].M       = in[i].M;      
    out[i].Xp      = in[i].Xp;     
    out[i].Xm      = in[i].Xm;     
    out[i].Nm      = in[i].Nm;     
    out[i].Nn      = in[i].Nn;     
    out[i].code    = in[i].code;   
    out[i].offset  = in[i].offset; 
    out[i].missing = in[i].missing;

    out[i].dM = 0xffff;
  }

  free (in);
  
  return (out);
}

SecFilt *FixOldSecFilt (OldSecFilt *in, int Nvalues) {

  int i;
  SecFilt *out;

  ALLOCATE (out, SecFilt, Nvalues);

  for (i = 0; i < Nvalues; i++) {
    out[i].M    = in[i].M;      
    out[i].Xm   = in[i].Xm;      

    out[i].dM   = 0xffff;
  }

  free (in);
  
  return (out);
}

load_catalog (char *filename, Catalog *catalog, char mode, char VERBOSE) {
  
  int Nitems, nitems;
  int i, Nmeas, Nmiss, size, ssize;
  int NewMeasure, NewAverage, NewSecFilt;
  FILE *f;
  OldMeasure *tmpmeasure;
  OldAverage *tmpaverage;
  OldSecFilt *tmpsecfilt;
  struct stat filestatus;

  /* possible exit status: 
     0 - serious failure
     1 - success
     2 - file non-existent */

  /* read catalog header */
  if (!fits_read_header (filename, &catalog[0].header)) {
    if (VERBOSE) fprintf (stderr, "catalog file does not exist: %s\n", filename);
    return (2);
  }

  f = fopen (filename, "r");
  if (f == (FILE *) NULL) {
    if (VERBOSE) fprintf (stderr, "ERROR: can't read data from catalog file: %s\n", filename);
    return (FALSE);
  }
  fseek (f, catalog[0].header.size, SEEK_SET); 

  catalog[0].Naverage = catalog[0].Nmeasure = catalog[0].Nmissing = catalog[0].Nsecfilt = 0;
  if (!fits_scan (&catalog[0].header, "NSTARS",   "%d", 1, &catalog[0].Naverage)) return (FALSE);
  if (!fits_scan (&catalog[0].header, "NMEAS",    "%d", 1, &catalog[0].Nmeasure)) return (FALSE);
  if (!fits_scan (&catalog[0].header, "NMISS",    "%d", 1, &catalog[0].Nmissing)) return (FALSE);
  if (!fits_scan (&catalog[0].header, "NSECFILT", "%d", 1, &catalog[0].Nsecfilt)) catalog[0].Nsecfilt = 0;
  if (!fits_scan (&catalog[0].header, "NEWMEAS",  "%t", 1, &NewMeasure)) NewMeasure = FALSE;
  if (!fits_scan (&catalog[0].header, "NEWAVES",  "%t", 1, &NewAverage)) NewAverage = FALSE;
  if (!fits_scan (&catalog[0].header, "NEWSECF",  "%t", 1, &NewSecFilt)) NewSecFilt = FALSE;

  /* predicted file size */

  size = 0;
  ssize = NewAverage ? sizeof (Average) : sizeof (OldAverage);
  size += ssize * catalog[0].Naverage;

  ssize = NewMeasure ? sizeof (Measure) : sizeof (OldMeasure);
  size += ssize * catalog[0].Nmeasure;

  ssize = sizeof (Missing);
  size += ssize * catalog[0].Nmissing;

  ssize = NewSecFilt ? sizeof (SecFilt) : sizeof (OldSecFilt);
  size += ssize * catalog[0].Nsecfilt * catalog[0].Naverage;

  size += catalog[0].header.size;

  /* check that file size makes sense */
  if (stat (filename, &filestatus) == -1) {
    fprintf (stderr, "ERROR: failed to get status of star catalog\n");
    exit (1);
  }
  if (size != filestatus.st_size) {
    fprintf (stderr, "ERROR: star catalog has inconsistent size\n");
    exit (1);
  } 

  if (catalog[0].Naverage == 0) {
    if (VERBOSE) fprintf (stderr, "no stars yet in catalog %s\n", filename);
    fclose (f);
    return (TRUE);
  }

  if (mode & LOAD_AVES) {
    /* read average values */
    if (NewAverage) {
      ALLOCATE (catalog[0].average, Average, MAX (catalog[0].Naverage, 1));
      Nitems = catalog[0].Naverage;
      nitems = Fread (catalog[0].average, sizeof(Average), Nitems, f, "average");
    } else {
      ALLOCATE (tmpaverage, Average, MAX (catalog[0].Naverage, 1));
      Nitems = catalog[0].Naverage;
      nitems = Fread (tmpaverage, sizeof(OldAverage), Nitems, f, "oldaverage");
      catalog[0].average = FixOldAverage (tmpaverage, Nitems);
    }
    if (nitems != Nitems) {
      fprintf (stderr, "ERROR: failed to read averages from catalog file %s\n", filename);
      fclose (f);
      return (FALSE);
    }
  } else {
    /* skip over averages */
    fseek (f, catalog[0].Naverage * sizeof(Average), SEEK_CUR); 
  }    
  
  if (mode & LOAD_MEAS) {
    /* read measurements */
    if (NewMeasure) {
      ALLOCATE (catalog[0].measure, Measure, MAX (catalog[0].Nmeasure, 1));
      Nitems = catalog[0].Nmeasure;
      nitems = Fread (catalog[0].measure, sizeof(Measure), Nitems, f, "measure");
    } else {
      ALLOCATE (tmpmeasure, OldMeasure, MAX (catalog[0].Nmeasure, 1));
      Nitems = catalog[0].Nmeasure;
      nitems = Fread (tmpmeasure, sizeof(OldMeasure), Nitems, f, "oldmeasure");
      catalog[0].measure = FixOldMeasure (tmpmeasure, Nitems);
    }
    if (nitems != Nitems) {
      fprintf (stderr, "ERROR: failed to read measures from catalog file %s\n", filename);
      fclose (f);
      return (FALSE);
    }
  } else {
    /* skip over measures */
    fseek (f, catalog[0].Nmeasure * sizeof(Measure), SEEK_CUR); 
  } 

  if (mode & LOAD_MISS) {
    /* read missing */
    ALLOCATE (catalog[0].missing, Missing, MAX (catalog[0].Nmissing, 1));
    Nitems = catalog[0].Nmissing;
    nitems = Fread (catalog[0].missing, sizeof(Missing), Nitems, f, "missing");
    if (nitems != Nitems) {
      fprintf (stderr, "ERROR: failed to read missing from catalog file %s\n", filename);
      fclose (f);
      return (FALSE);
    }
  } else {
    /* skip over missings */
    fseek (f, catalog[0].Nmissing * sizeof(Missing), SEEK_CUR); 
  }
  
  if (mode & LOAD_SECF) {
    /* read missing */
    if (NewSecFilt) {
      Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
      ALLOCATE (catalog[0].secfilt, SecFilt, MAX (Nitems, 1));
      nitems = Fread (catalog[0].secfilt, sizeof(SecFilt), Nitems, f, "secfilt");
    } else {
      Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
      ALLOCATE (tmpsecfilt, OldSecFilt, MAX (Nitems, 1));
      nitems = Fread (tmpsecfilt, sizeof(OldSecFilt), Nitems, f, "oldsecfilt");
      catalog[0].secfilt = FixOldSecFilt (tmpsecfilt, Nitems);
    } 
    if (nitems != Nitems) {
      fprintf (stderr, "ERROR: failed to read secondary filters from catalog file %s\n", filename);
      fclose (f);
      return (FALSE);
    }
  } else {
    /* skip over secfilts */
    fseek (f, catalog[0].Naverage * catalog[0].Nsecfilt * sizeof(SecFilt), SEEK_CUR); 
  }

  fclose (f);
  
  if (VERBOSE) fprintf (stderr, "read %d stars from catalog file %s (%d measurements, %d missing, %d secondary filters)\n", 
	   catalog[0].Naverage, filename, catalog[0].Nmeasure, catalog[0].Nmissing, catalog[0].Nsecfilt);

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

