# 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) {

  Average *average;
  char extname[80];

  /* 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);
    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);
    free (tmpAverage);
    *format = DVO_FORMAT_LONEOS;
    return (average);
  }
  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);
  }

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

  *Naverage = 0;
  return (NULL);
}

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

  AverageElixir *tmpAverageElixir;
  AverageLoneos *tmpAverageLoneos ;
  AveragePanstarrs *tmpAveragePanstarrs;
  AveragePMtest *tmpAveragePMtest;

  /* convert from the internal format */
  switch (format) {
    case DVO_FORMAT_INTERNAL:
      gfits_table_set_Average (ftable, average, Naverage);
      break;
    case DVO_FORMAT_ELIXIR:
      tmpAverageElixir = AverageInternalToElixir (average, Naverage);
      gfits_table_set_AverageElixir (ftable, tmpAverageElixir, Naverage);
      free (tmpAverageElixir);
      break;
    case DVO_FORMAT_LONEOS:
      tmpAverageLoneos  = AverageInternalToLoneos (average, Naverage);
      gfits_table_set_AverageLoneos (ftable, tmpAverageLoneos , Naverage);
      free (tmpAverageLoneos );
      break;
    case DVO_FORMAT_PANSTARRS:
      tmpAveragePanstarrs = AverageInternalToPanstarrs (average, Naverage);
      gfits_table_set_AveragePanstarrs (ftable, tmpAveragePanstarrs, Naverage);
      free (tmpAveragePanstarrs);
      break;
    case DVO_FORMAT_PMTEST:
      tmpAveragePMtest = AverageInternalToPMtest (average, Naverage);
      gfits_table_set_AveragePMtest (ftable, tmpAveragePMtest, Naverage);
      free (tmpAveragePMtest);
      break;
    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") || !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);
  }

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

  *Nmeasure = 0;
  return (NULL);
}

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

  MeasureElixir *tmpMeasureElixir;
  MeasureLoneos *tmpMeasureLoneos;
  MeasurePanstarrs *tmpMeasurePanstarrs;

  /* convert from the internal format */
  switch (format) {
    case DVO_FORMAT_INTERNAL:
      gfits_table_set_Measure (ftable, measure, Nmeasure);
      break;
    case DVO_FORMAT_ELIXIR:
      tmpMeasureElixir = MeasureInternalToElixir (measure, Nmeasure);
      gfits_table_set_MeasureElixir (ftable, tmpMeasureElixir, Nmeasure);
      free (tmpMeasureElixir);
      break;
    case DVO_FORMAT_LONEOS:
      tmpMeasureLoneos = MeasureInternalToLoneos (measure, Nmeasure);
      gfits_table_set_MeasureLoneos (ftable, tmpMeasureLoneos, Nmeasure);
      free (tmpMeasureLoneos);
      break;
    case DVO_FORMAT_PANSTARRS:
    case DVO_FORMAT_PMTEST:
      tmpMeasurePanstarrs = MeasureInternalToPanstarrs (measure, Nmeasure);
      gfits_table_set_MeasurePanstarrs (ftable, tmpMeasurePanstarrs, Nmeasure);
      free (tmpMeasurePanstarrs);
      break;
    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") || !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);
  }

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

  *Nsecfilt = 0;
  return (NULL);
}

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

  SecFiltElixir *tmpSecFiltElixir;
  SecFiltLoneos *tmpSecFiltLoneos;
  SecFiltPanstarrs *tmpSecFiltPanstarrs;

  /* convert from the internal format */
  switch (format) {
    case DVO_FORMAT_INTERNAL:
      gfits_table_set_SecFilt (ftable, secfilt, Nsecfilt);
      break;
    case DVO_FORMAT_ELIXIR:
      tmpSecFiltElixir = SecFiltInternalToElixir (secfilt, Nsecfilt);
      gfits_table_set_SecFiltElixir (ftable, tmpSecFiltElixir, Nsecfilt);
      free (tmpSecFiltElixir);
      break;
    case DVO_FORMAT_LONEOS:
      tmpSecFiltLoneos = SecFiltInternalToLoneos (secfilt, Nsecfilt);
      gfits_table_set_SecFiltLoneos (ftable, tmpSecFiltLoneos, Nsecfilt);
      free (tmpSecFiltLoneos);
      break;
    case DVO_FORMAT_PANSTARRS:
    case DVO_FORMAT_PMTEST:
      tmpSecFiltPanstarrs = SecFiltInternalToPanstarrs (secfilt, Nsecfilt);
      gfits_table_set_SecFiltPanstarrs (ftable, tmpSecFiltPanstarrs, Nsecfilt);
      free (tmpSecFiltPanstarrs);
      break;
    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) {
    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") || !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;
  }
  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;
  ImageElixir *tmpImageElixir;
  ImageLoneos *tmpImageLoneos;
  ImagePanstarrs *tmpImagePanstarrs;

  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:
      tmpImageElixir = ImageInternalToElixir ((Image *) ftable[0].buffer, Nimage);
      free (ftable[0].buffer);
      gfits_table_set_ImageElixir (ftable, tmpImageElixir, Nimage);
      free (tmpImageElixir);
      break;
    case DVO_FORMAT_LONEOS:
      tmpImageLoneos = ImageInternalToLoneos ((Image *) ftable[0].buffer, Nimage);
      free (ftable[0].buffer);
      gfits_table_set_ImageLoneos (ftable, tmpImageLoneos, Nimage);
      free (tmpImageLoneos);
      break;
    case DVO_FORMAT_PANSTARRS:
    case DVO_FORMAT_PMTEST:
      tmpImagePanstarrs = ImageInternalToPanstarrs ((Image *) ftable[0].buffer, Nimage);
      free (ftable[0].buffer);
      gfits_table_set_ImagePanstarrs (ftable, tmpImagePanstarrs, Nimage);
      free (tmpImagePanstarrs);
      break;
    default:
      fprintf (stderr, "table format unknown (image ftable)\n");
      return (FALSE);
  }
  return (TRUE);
}

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

  ImageElixir *tmpImageElixir;
  ImageLoneos *tmpImageLoneos;
  ImagePanstarrs *tmpImagePanstarrs;
  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:
      /* convert table rows from internal to external format */
      for (i = 0; i < Nrow; i++) {
	tmpImageElixir = ImageInternalToElixir ((Image *) vtable[0].buffer[i], 1);
	gfits_convert_ImageElixir (tmpImageElixir, sizeof(ImageElixir), 1);
	free (vtable[0].buffer[i]);
	vtable[0].buffer[i] = (char *) tmpImageElixir;
      }

      /* 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:
      /* convert table rows from internal to external format */
      for (i = 0; i < Nrow; i++) {
	tmpImageLoneos = ImageInternalToLoneos ((Image *) vtable[0].buffer[i], 1);
	gfits_convert_ImageLoneos (tmpImageLoneos, sizeof(ImageLoneos), 1);
	free (vtable[0].buffer[i]);
	vtable[0].buffer[i] = (char *) tmpImageLoneos;
      }

      /* 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:
    case DVO_FORMAT_PMTEST:
      /* convert table rows from internal to external format */
      for (i = 0; i < Nrow; i++) {
	tmpImagePanstarrs = ImageInternalToPanstarrs ((Image *) vtable[0].buffer[i], 1);
	gfits_convert_ImagePanstarrs (tmpImagePanstarrs, sizeof(ImagePanstarrs), 1);
	free (vtable[0].buffer[i]);
	vtable[0].buffer[i] = (char *) tmpImagePanstarrs;
      }

      /* 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);
    default:
      break;
  }
  fprintf (stderr, "table format unknown (image vtable)\n");
  return (FALSE);
}

