# include <dvo.h>

int dvo_catalog_load_mef (Catalog *catalog, int VERBOSE) {
  
  int Nitems, Nbytes, Nexpect, Naverage, Nmeasure, Nmissing, Nsecfilt;
  FILE *f;

  Header header;
  Matrix matrix;
  FTable ftable;

  f = catalog[0].f;
  ftable.header = &header;

  /* move pointer past header -- must be already read (load_catalog) */
  fseek (f, catalog[0].header.size, SEEK_SET);

  /* matrix should be empty */
  if (!gfits_fread_matrix (f, &matrix, &catalog[0].header)) {
    if (VERBOSE) fprintf (stderr, "can't read primary matrix");
    return (FALSE);
  }
  /* get the components from the header */
  if (!gfits_scan (&catalog[0].header, "NSTARS",   "%d", 1, &Naverage)) return (FALSE);
  if (!gfits_scan (&catalog[0].header, "NMEAS",    "%d", 1, &Nmeasure)) return (FALSE);
  if (!gfits_scan (&catalog[0].header, "NMISS",    "%d", 1, &Nmissing)) return (FALSE);
  if (!gfits_scan (&catalog[0].header, "NSECFILT", "%d", 1, &Nsecfilt)) Nsecfilt = 0;

  /**  Nsecfilt is unusual: it does not list the number of data items in the table
       instead, the number of items is Nsecfilt * Naverage.  **/
  catalog[0].Nsecfilt = Nsecfilt;

  /* validate table mode */

  /* read Average table header */
  if (!gfits_fread_header (f, &header)) {
    if (VERBOSE) fprintf (stderr, "can't read table average header");
    return (FALSE);
  }
  /* read Average table data (or skip) */
  if (catalog[0].catflags & LOAD_AVES) {
    if (!gfits_fread_ftable_data (f, &ftable)) {
      if (VERBOSE) fprintf (stderr, "can't read table average data");
      return (FALSE);
    }
    catalog[0].average = FtableToAverage (&ftable, &catalog[0].Naverage, &catalog[0].catformat);
    if (Naverage != catalog[0].Naverage) {
      fprintf (stderr, "Warning: mismatch between Naverage in PHU and Table headers (%d vs %d)\n", Naverage, catalog[0].Naverage);
    }
  } else {
    Nbytes = gfits_matrix_size (&header);
    fseek (f, Nbytes, SEEK_CUR);
  }
  gfits_free_header (&header);
  /** free the ftable or not? data is being used still..? **/

  /* read Measure table header */
  if (!gfits_fread_header (f, &header)) {
    if (VERBOSE) fprintf (stderr, "can't read table measure header");
    return (FALSE);
  }
  /* read Measure table data */
  if (catalog[0].catflags & LOAD_MEAS) {
    if (!gfits_fread_ftable_data (f, &ftable)) {
      if (VERBOSE) fprintf (stderr, "can't read table measure data");
      return (FALSE);
    }
    catalog[0].measure = FtableToMeasure (&ftable, &catalog[0].Nmeasure, &catalog[0].catformat);
    if (Nmeasure != catalog[0].Nmeasure) {
      fprintf (stderr, "Warning: mismatch between Nmeasure in PHU and Table headers (%d vs %d)\n", Nmeasure, catalog[0].Nmeasure);
    }
  } else {
    Nbytes = gfits_matrix_size (&header);
    fseek (f, Nbytes, SEEK_CUR);
  }

  /* read Missing table header */
  if (!gfits_fread_header (f, &header)) {
    if (VERBOSE) fprintf (stderr, "can't read table missing header");
    return (FALSE);
  }
  /* read Missing table data */
  if (catalog[0].catflags & LOAD_MISS) {
    if (!gfits_fread_ftable_data (f, &ftable)) {
      if (VERBOSE) fprintf (stderr, "can't read table missing data");
      return (FALSE);
    }
    /* no conversions currently defined */
    catalog[0].missing = gfits_table_get_Missing (&ftable, &catalog[0].Nmissing, NULL);
    if (Nmissing != catalog[0].Nmissing) {
      fprintf (stderr, "Warning: mismatch between Nmissing in PHU and Table headers (%d vs %d)\n", Nmissing, catalog[0].Nmissing);
    }
  } else {
    Nbytes = gfits_matrix_size (&header);
    fseek (f, Nbytes, SEEK_CUR);
  }

  // catalog[0].secfilt = gfits_table_get_SecFilt (&ftable, &Nitems, NULL);
  // catalog[0].Nsecfilt = Nitems / catalog[0].Naverage;

  /* read secfilt table header */
  if (!gfits_fread_header (f, &header)) {
    if (VERBOSE) fprintf (stderr, "can't read table secfilt header");
    return (FALSE);
  }
  /* read secfilt table data */
  if (catalog[0].catflags & LOAD_SECF) {
    if (!gfits_fread_ftable_data (f, &ftable)) {
      if (VERBOSE) fprintf (stderr, "can't read table secfilt data");
      return (FALSE);
    }
    Nexpect = catalog[0].Nsecfilt * catalog[0].Naverage;
    catalog[0].secfilt = FtableToSecFilt (&ftable, &Nitems, &catalog[0].catformat);
    if (Nexpect != Nitems) {
      fprintf (stderr, "Warning: mismatch between Nsecfilt items in PHU and Table headers (%d vs %d)\n", Nexpect, Nitems);
    }
  } else {
    /* no real need to skip the data array here... */
    Nbytes = gfits_matrix_size (&header);
    fseek (f, Nbytes, SEEK_CUR);
  }

  /* save the current number so we can do partial updates */
  catalog[0].Nave_disk  = catalog[0].Naverage;
  catalog[0].Nmeas_disk = catalog[0].Nmeasure;
  catalog[0].Nmiss_disk = catalog[0].Nmissing;

  return (TRUE);
}

/* save_catalog_mef writes a complete new file from scratch */

int dvo_catalog_save_mef (Catalog *catalog, char VERBOSE) {

  int Nitems;
  FILE *f;
  Matrix matrix;
  Header header;
  FTable ftable;

  if (catalog[0].Naverage == 0) {
    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
    return (TRUE);
  }

  /* make sure header is consistent with data */
  gfits_modify (&catalog[0].header, "NSTARS",   "%d", 1, catalog[0].Naverage);
  gfits_modify (&catalog[0].header, "NMEAS",    "%d", 1, catalog[0].Nmeasure);
  gfits_modify (&catalog[0].header, "NMISS",    "%d", 1, catalog[0].Nmissing);
  gfits_modify (&catalog[0].header, "NSECFILT", "%d", 1, catalog[0].Nsecfilt);
  gfits_modify (&catalog[0].header, "EXTEND",   "%t", 1, TRUE);

  f = catalog[0].f;
  /* rewind file pointers and truncate */
  fseek (f, 0, SEEK_SET);
  ftruncate (fileno (catalog[0].f), 0);
  ftable.header = &header;

  /* write table PHU header */
  if (!gfits_fwrite_header  (catalog[0].f, &catalog[0].header)) {
    fprintf (stderr, "can't write primary header");
    return (FALSE);
  }

  /* this is probably a NOP, do I have to keep it in? */
  gfits_create_matrix (&catalog[0].header, &matrix);
  if (!gfits_fwrite_matrix  (catalog[0].f, &matrix)) {
    fprintf (stderr, "can't write primary matrix");
    return (FALSE);
  }
  gfits_free_matrix (&matrix);

  /* write out Average table (convert to FITS table format) */
  AverageToFtable (&ftable, catalog[0].average, catalog[0].Naverage, catalog[0].catformat);
  if (!gfits_fwrite_Theader (catalog[0].f, &header)) {
    fprintf (stderr, "can't write table header");
    return (FALSE);
  }
  if (!gfits_fwrite_table (catalog[0].f, &ftable)) {
    fprintf (stderr, "can't write table data");
    return (FALSE);
  }
  gfits_free_table (&ftable);
  gfits_free_header (&header);

  /* write out Measure table (convert to FITS table format) */
  MeasureToFtable (&ftable, catalog[0].measure, catalog[0].Nmeasure, catalog[0].catformat);
  if (!gfits_fwrite_Theader (catalog[0].f, &header)) {
    fprintf (stderr, "can't write table header");
    return (FALSE);
  }
  if (!gfits_fwrite_table (catalog[0].f, &ftable)) {
    fprintf (stderr, "can't write table data");
    return (FALSE);
  }
  gfits_free_table (&ftable);
  gfits_free_header (&header);

  /* write out Missing table (convert to FITS table format) */
  gfits_table_set_Missing (&ftable, catalog[0].missing, catalog[0].Nmissing);
  if (!gfits_fwrite_Theader (catalog[0].f, &header)) {
    fprintf (stderr, "can't write table header");
    return (FALSE);
  }
  if (!gfits_fwrite_table (catalog[0].f, &ftable)) {
    fprintf (stderr, "can't write table data");
    return (FALSE);
  }
  gfits_free_table (&ftable);
  gfits_free_header (&header);

  /* write out SecFilt table (convert to FITS table format) */
  Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
  SecFiltToFtable (&ftable, catalog[0].secfilt, Nitems, catalog[0].catformat);
  if (!gfits_fwrite_Theader (catalog[0].f, &header)) {
    fprintf (stderr, "can't write table header");
    return (FALSE);
  }
  if (!gfits_fwrite_table (catalog[0].f, &ftable)) {
    fprintf (stderr, "can't write table data");
    return (FALSE);
  }
  gfits_free_table (&ftable);
  gfits_free_header (&header);

  return (TRUE);
}

/*
   catalog data is:
   header (bitpix == 8)
   matrix (empty)
   average header
   average table
   measure header
   measure table
   missing header
   missing table
   secfilt header
   secfilt table
*/
   
