# include <dvo.h>

/* The Ftable-TYPE conversion functions determine the format of table based on EXTNAME in header.
   they convert the table to the internal format, and set 'format'.  

   The TYPE-Ftable conversions functions create output tables in the format requested
   by the 'format' function parameter.
*/

/** this file might be more readable if I use macros for the repetative
    constructions below **/

/*** Average / FTable conversion functions ***/

Average *FtableToAverage (FTable *ftable, int *Naverage, int *format, SecFilt **primary) {

  Average *average;
  char extname[80];

  /* in the Elixir and Loneos cases, we are supplied with an average magnitude in Average
     in these cases, save these values in primary; otherwise set primary to NULL */
  *primary = NULL;

  /* convert to the internal format */
  if (!gfits_scan (ftable[0].header, "EXTNAME", "%s", 1, extname)) {
    fprintf (stderr, "EXTNAME missing for average table\n");
    return (FALSE);
  }
  if (!strcmp (extname, "DVO_AVERAGE")) {
    average = gfits_table_get_Average (ftable, Naverage, NULL);
    *format = DVO_FORMAT_INTERNAL;
    return (average);
  }
  if (!strcmp (extname, "DVO_AVERAGE_ELIXIR")) {
    AverageElixir *tmpAverage;
    tmpAverage = gfits_table_get_AverageElixir (ftable, Naverage, NULL);
    average = AverageElixirToInternal (tmpAverage, *Naverage, primary);
    free (tmpAverage);
    *format = DVO_FORMAT_ELIXIR;
    return (average);
  }
  if (!strcmp (extname, "DVO_AVERAGE_LONEOS")) {
    AverageLoneos *tmpAverage;
    tmpAverage = gfits_table_get_AverageLoneos (ftable, Naverage, NULL);
    average = AverageLoneosToInternal (tmpAverage, *Naverage, primary);
    free (tmpAverage);
    *format = DVO_FORMAT_LONEOS;
    return (average);
  }
  if (!strcmp (extname, "DVO_AVERAGE_PANSTARRS_DEV_0")) {
    AveragePanstarrs_DEV_0 *tmpAverage;
    tmpAverage = gfits_table_get_AveragePanstarrs_DEV_0 (ftable, Naverage, NULL);
    average = AveragePanstarrs_DEV_0_ToInternal (tmpAverage, *Naverage);
    free (tmpAverage);
    *format = DVO_FORMAT_PANSTARRS_DEV_0;
    return (average);
  }
/* disable the new and minimally-used versions for now.  
   put them back in after dev work is further along
   OR replace with other output formats */
# if 0
  if (!strcmp (extname, "DVO_AVERAGE_PANSTARRS")) {
    AveragePanstarrs *tmpAverage;
    tmpAverage = gfits_table_get_AveragePanstarrs (ftable, Naverage, NULL);
    average = AveragePanstarrsToInternal (tmpAverage, *Naverage);
    free (tmpAverage);
    *format = DVO_FORMAT_PANSTARRS;
    return (average);
  }
  if (!strcmp (extname, "DVO_AVERAGE_PMTEST")) {
    AveragePMtest *tmpAverage;
    tmpAverage = gfits_table_get_AveragePMtest (ftable, Naverage, NULL);
    average = AveragePMtestToInternal (tmpAverage, *Naverage);
    free (tmpAverage);
    *format = DVO_FORMAT_PMTEST;
    return (average);
  }
# endif

  fprintf (stderr, "table format unknown: %s\n", extname);

  *Naverage = 0;
  return (NULL);
}

int AverageToFtable (FTable *ftable, Average *average, int Naverage, int format, SecFilt *primary) {


  /* convert from the internal format */
  switch (format) {
    case DVO_FORMAT_INTERNAL: {
      gfits_table_set_Average (ftable, average, Naverage);
      break; }
    case DVO_FORMAT_ELIXIR: {
      AverageElixir *tmpAverage;
      tmpAverage = AverageInternalToElixir (average, Naverage, primary);
      gfits_table_set_AverageElixir (ftable, tmpAverage, Naverage);
      free (tmpAverage);
      break; }
    case DVO_FORMAT_LONEOS: {
      AverageLoneos *tmpAverage ;
      tmpAverage  = AverageInternalToLoneos (average, Naverage, primary);
      gfits_table_set_AverageLoneos (ftable, tmpAverage, Naverage);
      free (tmpAverage );
      break; }
    case DVO_FORMAT_PANSTARRS_DEV_0: {
      AveragePanstarrs_DEV_0 *tmpAverage;
      tmpAverage = AverageInternalToPanstarrs_DEV_0 (average, Naverage);
      gfits_table_set_AveragePanstarrs_DEV_0 (ftable, tmpAverage, Naverage);
      free (tmpAverage);
      break; }
# if 0
    case DVO_FORMAT_PANSTARRS: {
      AveragePanstarrs *tmpAverage;
      tmpAverage = AverageInternalToPanstarrs (average, Naverage);
      gfits_table_set_AveragePanstarrs (ftable, tmpAverage, Naverage);
      free (tmpAverage);
      break; }
    case DVO_FORMAT_PMTEST: {
      AveragePMtest *tmpAverage;
      tmpAverage = AverageInternalToPMtest (average, Naverage);
      gfits_table_set_AveragePMtest (ftable, tmpAverage, Naverage);
      free (tmpAverage);
      break; }
# endif
    default:
      fprintf (stderr, "table format unknown (average)\n");
      return (FALSE);
  }
  return (TRUE);
}

/*** Measure / FTable conversion functions ***/

Measure *FtableToMeasure (FTable *ftable, int *Nmeasure, int *format) {

  Measure *measure;
  char extname[80];

  /* convert to the internal format */
  if (!gfits_scan (ftable[0].header, "EXTNAME", "%s", 1, extname)) {
    fprintf (stderr, "EXTNAME missing for measure table\n");
    return (FALSE);
  }
  if (!strcmp (extname, "DVO_MEASURE")) {
    measure = gfits_table_get_Measure (ftable, Nmeasure, NULL);
    *format = DVO_FORMAT_INTERNAL;
    return (measure);
  }
  if (!strcmp (extname, "DVO_MEASURE_ELIXIR")) {
    MeasureElixir *tmpMeasure;
    tmpMeasure = gfits_table_get_MeasureElixir (ftable, Nmeasure, NULL);
    measure = MeasureElixirToInternal (tmpMeasure, *Nmeasure);
    free (tmpMeasure);
    *format = DVO_FORMAT_ELIXIR;
    return (measure);
  }
  if (!strcmp (extname, "DVO_MEASURE_LONEOS")) {
    MeasureLoneos *tmpMeasure;
    tmpMeasure = gfits_table_get_MeasureLoneos (ftable, Nmeasure, NULL);
    measure = MeasureLoneosToInternal (tmpMeasure, *Nmeasure);
    free (tmpMeasure);
    *format = DVO_FORMAT_LONEOS;
    return (measure);
  }
  if (!strcmp (extname, "DVO_MEASURE_PANSTARRS_DEV_0")) {
    MeasurePanstarrs_DEV_0 *tmpMeasure;
    tmpMeasure = gfits_table_get_MeasurePanstarrs_DEV_0 (ftable, Nmeasure, NULL);
    measure = MeasurePanstarrs_DEV_0_ToInternal (tmpMeasure, *Nmeasure);
    free (tmpMeasure);
    *format = DVO_FORMAT_PANSTARRS_DEV_0;
    return (measure);
  }
# if 0
  if (!strcmp (extname, "DVO_MEASURE_PANSTARRS") || !strcmp (extname, "DVO_MEASURE_PMTEST")) {
    MeasurePanstarrs *tmpMeasure;
    tmpMeasure = gfits_table_get_MeasurePanstarrs (ftable, Nmeasure, NULL);
    measure = MeasurePanstarrsToInternal (tmpMeasure, *Nmeasure);
    free (tmpMeasure);
    *format = DVO_FORMAT_PANSTARRS;
    return (measure);
  }
# endif

  fprintf (stderr, "table format unknown: %s\n", extname);

  *Nmeasure = 0;
  return (NULL);
}

int MeasureToFtable (FTable *ftable, Measure *measure, int Nmeasure, int format) {


  /* convert from the internal format */
  switch (format) {
    case DVO_FORMAT_INTERNAL: {
      gfits_table_set_Measure (ftable, measure, Nmeasure);
      break; }
    case DVO_FORMAT_ELIXIR: {
      MeasureElixir *tmpMeasure;
      tmpMeasure = MeasureInternalToElixir (measure, Nmeasure);
      gfits_table_set_MeasureElixir (ftable, tmpMeasure, Nmeasure);
      free (tmpMeasure);
      break; }
    case DVO_FORMAT_LONEOS: {
      MeasureLoneos *tmpMeasure;
      tmpMeasure = MeasureInternalToLoneos (measure, Nmeasure);
      gfits_table_set_MeasureLoneos (ftable, tmpMeasure, Nmeasure);
      free (tmpMeasure);
      break; }
    case DVO_FORMAT_PANSTARRS_DEV_0: {
      MeasurePanstarrs_DEV_0 *tmpMeasure;
      tmpMeasure = MeasureInternalToPanstarrs_DEV_0 (measure, Nmeasure);
      gfits_table_set_MeasurePanstarrs_DEV_0 (ftable, tmpMeasure, Nmeasure);
      free (tmpMeasure);
      break; }
# if 0
    case DVO_FORMAT_PANSTARRS: {
      MeasurePanstarrs *tmpMeasure;
      tmpMeasure = MeasureInternalToPanstarrs (measure, Nmeasure);
      gfits_table_set_MeasurePanstarrs (ftable, tmpMeasure, Nmeasure);
      free (tmpMeasure);
      break; }
# endif
    default:
      fprintf (stderr, "table format unknown (measure)\n");
      return (FALSE);
  }
  return (TRUE);
}

/*** SecFilt / FTable conversion functions ***/

SecFilt *FtableToSecFilt (FTable *ftable, int *Nsecfilt, int *format) {

  SecFilt *secfilt;
  char extname[80];

  /* convert to the internal format */
  if (!gfits_scan (ftable[0].header, "EXTNAME", "%s", 1, extname)) {
    fprintf (stderr, "EXTNAME missing for secfilt table\n");
    return (FALSE);
  }
  if (!strcmp (extname, "DVO_SECFILT")) {
    secfilt = gfits_table_get_SecFilt (ftable, Nsecfilt, NULL);
    *format = DVO_FORMAT_INTERNAL;
    return (secfilt);
  }
  if (!strcmp (extname, "DVO_SECFILT_ELIXIR")) {
    SecFiltElixir *tmpSecFilt;
    tmpSecFilt = gfits_table_get_SecFiltElixir (ftable, Nsecfilt, NULL);
    secfilt = SecFiltElixirToInternal (tmpSecFilt, *Nsecfilt);
    free (tmpSecFilt);
    *format = DVO_FORMAT_ELIXIR;
    return (secfilt);
  }
  if (!strcmp (extname, "DVO_SECFILT_LONEOS")) {
    SecFiltLoneos *tmpSecFilt;
    tmpSecFilt = gfits_table_get_SecFiltLoneos (ftable, Nsecfilt, NULL);
    secfilt = SecFiltLoneosToInternal (tmpSecFilt, *Nsecfilt);
    free (tmpSecFilt);
    *format = DVO_FORMAT_LONEOS;
    return (secfilt);
  }
  if (!strcmp (extname, "DVO_SECFILT_PANSTARRS_DEV_0")) {
    SecFiltPanstarrs_DEV_0 *tmpSecFilt;
    tmpSecFilt = gfits_table_get_SecFiltPanstarrs_DEV_0 (ftable, Nsecfilt, NULL);
    secfilt = SecFiltPanstarrs_DEV_0_ToInternal (tmpSecFilt, *Nsecfilt);
    free (tmpSecFilt);
    *format = DVO_FORMAT_PANSTARRS_DEV_0;
    return (secfilt);
  }
# if 0
  if (!strcmp (extname, "DVO_SECFILT_PANSTARRS") || !strcmp (extname, "DVO_SECFILT_PMTEST")) {
    SecFiltPanstarrs *tmpSecFilt;
    tmpSecFilt = gfits_table_get_SecFiltPanstarrs (ftable, Nsecfilt, NULL);
    secfilt = SecFiltPanstarrsToInternal (tmpSecFilt, *Nsecfilt);
    free (tmpSecFilt);
    *format = DVO_FORMAT_PANSTARRS;
    return (secfilt);
  }
# endif

  fprintf (stderr, "table format unknown: %s\n", extname);

  *Nsecfilt = 0;
  return (NULL);
}

int SecFiltToFtable (FTable *ftable, SecFilt *secfilt, int Nsecfilt, int format) {

  /* convert from the internal format */
  switch (format) {
    case DVO_FORMAT_INTERNAL: {
      gfits_table_set_SecFilt (ftable, secfilt, Nsecfilt);
      break; }
    case DVO_FORMAT_ELIXIR: {
      SecFiltElixir *tmpSecFilt;
      tmpSecFilt = SecFiltInternalToElixir (secfilt, Nsecfilt);
      gfits_table_set_SecFiltElixir (ftable, tmpSecFilt, Nsecfilt);
      free (tmpSecFilt);
      break; }
    case DVO_FORMAT_LONEOS: {
      SecFiltLoneos *tmpSecFilt;
      tmpSecFilt = SecFiltInternalToLoneos (secfilt, Nsecfilt);
      gfits_table_set_SecFiltLoneos (ftable, tmpSecFilt, Nsecfilt);
      free (tmpSecFilt);
      break; }
    case DVO_FORMAT_PANSTARRS_DEV_0: {
      SecFiltPanstarrs_DEV_0 *tmpSecFilt;
      tmpSecFilt = SecFiltInternalToPanstarrs_DEV_0 (secfilt, Nsecfilt);
      gfits_table_set_SecFiltPanstarrs_DEV_0 (ftable, tmpSecFilt, Nsecfilt);
      free (tmpSecFilt);
      break; }
# if 0
    case DVO_FORMAT_PANSTARRS: {
      SecFiltPanstarrs *tmpSecFilt;
      tmpSecFilt = SecFiltInternalToPanstarrs (secfilt, Nsecfilt);
      gfits_table_set_SecFiltPanstarrs (ftable, tmpSecFilt, Nsecfilt);
      free (tmpSecFilt);
      break; }
# endif
    default:
      fprintf (stderr, "table format unknown (secfilt)\n");
      return (FALSE);
  }
  return (TRUE);
}

/*** Image Conversions ***/

int FtableToImage (FTable *ftable, Header *theader, int *format) {

  int Nimage;
  char extname[80];

  /* extname may be set from outside if the source is RAW not MEF */
  if (*format == DVO_FORMAT_ELIXIR) {		  // special case for ELIXIR
    ImageElixir *tmpimage;
    tmpimage = gfits_table_get_ImageElixir (ftable, &Nimage, NULL);
    ftable[0].buffer = (char *) ImageElixirToInternal (tmpimage, Nimage);
    free (tmpimage);
    goto set_header;
  }

  /* convert to the internal format */
  if (!gfits_scan (ftable[0].header, "EXTNAME", "%s", 1, extname)) {
    fprintf (stderr, "EXTNAME missing for image table\n");
    return (FALSE);
  }
  if (!strcmp (extname, "DVO_IMAGE")) {
    Image *image;
    image = gfits_table_get_Image (ftable, &Nimage, NULL);
    *format = DVO_FORMAT_INTERNAL;
    return (TRUE);
  }
  if (!strcmp (extname, "DVO_IMAGE_ELIXIR")) {
    ImageElixir *tmpimage;
    *format = DVO_FORMAT_ELIXIR;
    tmpimage = gfits_table_get_ImageElixir (ftable, &Nimage, NULL);
    ftable[0].buffer = (char *) ImageElixirToInternal (tmpimage, Nimage);
    free (tmpimage);
    goto set_header;
  }
  if (!strcmp (extname, "DVO_IMAGE_LONEOS")) {
    ImageLoneos *tmpimage;
    *format = DVO_FORMAT_LONEOS;
    tmpimage = gfits_table_get_ImageLoneos (ftable, &Nimage, NULL);
    ftable[0].buffer = (char *) ImageLoneosToInternal (tmpimage, Nimage);
    free (tmpimage);
    goto set_header;
  }
  if (!strcmp (extname, "DVO_IMAGE_PANSTARRS_DEV_0")) {
    ImagePanstarrs_DEV_0 *tmpimage;
    *format = DVO_FORMAT_PANSTARRS_DEV_0;
    tmpimage = gfits_table_get_ImagePanstarrs_DEV_0 (ftable, &Nimage, NULL);
    ftable[0].buffer = (char *) ImagePanstarrs_DEV_0_ToInternal (tmpimage, Nimage);
    free (tmpimage);
    goto set_header;
  }
# if 0
  if (!strcmp (extname, "DVO_IMAGE_PANSTARRS") || !strcmp (extname, "DVO_IMAGE_PMTEST")) {
    ImagePanstarrs *tmpimage;
    *format = DVO_FORMAT_PANSTARRS;
    tmpimage = gfits_table_get_ImagePanstarrs (ftable, &Nimage, NULL);
    ftable[0].buffer = (char *) ImagePanstarrsToInternal (tmpimage, Nimage);
    free (tmpimage);
    goto set_header;
  }
# endif
  fprintf (stderr, "table format unknown: %s\n", extname);
  return (FALSE);

set_header:
  gfits_free_header (theader);
  gfits_table_mkheader_Image (theader);
  gfits_modify (theader, "NAXIS2", "%d", 1, Nimage);
  theader[0].Naxis[1] = Nimage;
  ftable[0].size = gfits_matrix_size (theader);
  return (TRUE);
}

int ImageToFtable (FTable *ftable, Header *theader, int format) {

  int Nimage;

  Nimage = theader[0].Naxis[1];

  /* convert from the internal format */
  switch (format) {
    case DVO_FORMAT_INTERNAL: {
      gfits_convert_Image ((Image *) ftable[0].buffer, sizeof(Image), Nimage);
      break; }
    case DVO_FORMAT_ELIXIR: {
      ImageElixir *tmpImage;
      tmpImage = ImageInternalToElixir ((Image *) ftable[0].buffer, Nimage);
      free (ftable[0].buffer);
      gfits_table_set_ImageElixir (ftable, tmpImage, Nimage);
      free (tmpImage);
      break; }
    case DVO_FORMAT_LONEOS: {
      ImageLoneos *tmpImage;
      tmpImage = ImageInternalToLoneos ((Image *) ftable[0].buffer, Nimage);
      free (ftable[0].buffer);
      gfits_table_set_ImageLoneos (ftable, tmpImage, Nimage);
      free (tmpImage);
      break; }
    case DVO_FORMAT_PANSTARRS_DEV_0: {
      ImagePanstarrs_DEV_0 *tmpImage;
      tmpImage = ImageInternalToPanstarrs_DEV_0 ((Image *) ftable[0].buffer, Nimage);
      free (ftable[0].buffer);
      gfits_table_set_ImagePanstarrs_DEV_0 (ftable, tmpImage, Nimage);
      free (tmpImage);
      break; }
# if 0
    case DVO_FORMAT_PANSTARRS: {
      ImagePanstarrs *tmpImage;
      tmpImage = ImageInternalToPanstarrs ((Image *) ftable[0].buffer, Nimage);
      free (ftable[0].buffer);
      gfits_table_set_ImagePanstarrs (ftable, tmpImage, Nimage);
      free (tmpImage);
      break; }
# endif
    default:
      fprintf (stderr, "table format unknown (image ftable)\n");
      return (FALSE);
  }
  return (TRUE);
}

int ImageToVtable (VTable *vtable, Header *theader, int format) {

  int i, Nrow, Nimage;

  Nrow = vtable[0].Nrow;

  /* convert from the internal format */
  switch (format) {
    case DVO_FORMAT_INTERNAL: {
      for (i = 0; i < Nrow; i++) {
	gfits_convert_Image ((Image *) vtable[0].buffer[i], sizeof(Image), 1);
      }
      return (TRUE); }
    case DVO_FORMAT_ELIXIR: {
      ImageElixir *tmpImage;
      /* convert table rows from internal to external format */
      for (i = 0; i < Nrow; i++) {
	tmpImage = ImageInternalToElixir ((Image *) vtable[0].buffer[i], 1);
	gfits_convert_ImageElixir (tmpImage, sizeof(ImageElixir), 1);
	free (vtable[0].buffer[i]);
	vtable[0].buffer[i] = (char *) tmpImage;
      }

      /* convert header from old format to new format */
      gfits_scan (theader, "NAXIS2", "%d", 1, &Nimage);

      gfits_free_header (theader);
      gfits_table_mkheader_ImageElixir (theader);

      gfits_modify (theader, "NAXIS2", "%d", 1, Nimage);
      theader[0].Naxis[1] = Nimage;
      vtable[0].size = gfits_matrix_size (theader);
      return (TRUE); }
    case DVO_FORMAT_LONEOS: {
      ImageLoneos *tmpImage;
      /* convert table rows from internal to external format */
      for (i = 0; i < Nrow; i++) {
	tmpImage = ImageInternalToLoneos ((Image *) vtable[0].buffer[i], 1);
	gfits_convert_ImageLoneos (tmpImage, sizeof(ImageLoneos), 1);
	free (vtable[0].buffer[i]);
	vtable[0].buffer[i] = (char *) tmpImage;
      }

      /* convert header from old format to new format */
      gfits_scan (theader, "NAXIS2", "%d", 1, &Nimage);

      gfits_free_header (theader);
      gfits_table_mkheader_ImageLoneos (theader);

      gfits_modify (theader, "NAXIS2", "%d", 1, Nimage);
      theader[0].Naxis[1] = Nimage;
      vtable[0].size = gfits_matrix_size (theader);
      return (TRUE); }
    case DVO_FORMAT_PANSTARRS_DEV_0: {
      ImagePanstarrs_DEV_0 *tmpImage;
      /* convert table rows from internal to external format */
      for (i = 0; i < Nrow; i++) {
	tmpImage = ImageInternalToPanstarrs_DEV_0 ((Image *) vtable[0].buffer[i], 1);
	gfits_convert_ImagePanstarrs_DEV_0 (tmpImage, sizeof(ImagePanstarrs_DEV_0), 1);
	free (vtable[0].buffer[i]);
	vtable[0].buffer[i] = (char *) tmpImage;
      }
      /* convert header from old format to new format */
      gfits_scan (theader, "NAXIS2", "%d", 1, &Nimage);
      gfits_free_header (theader);
      gfits_table_mkheader_ImagePanstarrs_DEV_0 (theader);
      gfits_modify (theader, "NAXIS2", "%d", 1, Nimage);
      theader[0].Naxis[1] = Nimage;
      vtable[0].size = gfits_matrix_size (theader);
      return (TRUE); }
# if 0
    case DVO_FORMAT_PANSTARRS: {
      ImagePanstarrs *tmpImage;
      /* convert table rows from internal to external format */
      for (i = 0; i < Nrow; i++) {
	tmpImage = ImageInternalToPanstarrs ((Image *) vtable[0].buffer[i], 1);
	gfits_convert_ImagePanstarrs (tmpImage, sizeof(ImagePanstarrs), 1);
	free (vtable[0].buffer[i]);
	vtable[0].buffer[i] = (char *) tmpImage;
      }
      /* convert header from old format to new format */
      gfits_scan (theader, "NAXIS2", "%d", 1, &Nimage);
      gfits_free_header (theader);
      gfits_table_mkheader_ImagePanstarrs (theader);
      gfits_modify (theader, "NAXIS2", "%d", 1, Nimage);
      theader[0].Naxis[1] = Nimage;
      vtable[0].size = gfits_matrix_size (theader);
      return (TRUE); }
# endif
    default:
      break;
  }
  fprintf (stderr, "table format unknown (image vtable)\n");
  return (FALSE);
}

