# include "dvo.h"

/*** note : this file is derived from the autocode version, but is modified because
     the format does not match with structure byte boundaries ***/

/* if we are not correctly including the ohana headers, this will fail */
# ifndef BYTE_SWAP
# ifndef NOT_BYTE_SWAP
# error "neither BYTE_SWAP not NOT_BYTE_SWAP is set"
# endif
# endif

# define FT_SIZE 224
CMF_PS1_DV3 *gfits_table_get_CMF_PS1_DV3 (FTable *ftable, off_t *Ndata, char *swapped) {

  off_t i, nitems;
  unsigned char *byte, *inbyte, *otbyte, tmp;
  CMF_PS1_DV3 *output;

  /* provide initial values to avoid compiler warnings for non-BYTE_SWAP arch */
  i = tmp = 0;
  byte = NULL;

  // this function is a special case : it must have Nx = FT_SIZE
  if (ftable[0].header[0].Naxis[0] != FT_SIZE) { 
    fprintf (stderr, "ERROR: wrong format for CMF_PS1_DV3: "OFF_T_FMT" vs %d\n",  ftable[0].header[0].Naxis[0], FT_SIZE);
    return (NULL);
  }

  *Ndata = ftable[0].header[0].Naxis[1];
  nitems = ftable[0].header[0].Naxis[1];

  if ((swapped == NULL) || (*swapped == FALSE)) {

    // the byte table below is generated by libautocode/def/cmf-ps1-dv3.d.
    // the table dv3.d matches the input FITS table layout.  
    // the byte order in that file follows the list below.
# ifdef BYTE_SWAP
      // we need to do the byte swap before applying the table scaling:
      byte = (unsigned char *) ftable[0].buffer;
      for (i = 0; i < nitems; i++, byte += FT_SIZE) {
        /** BYTE SWAP **/
        SWAP_WORD (0); // IPP_IDET
        SWAP_WORD (4); // X_PSF
        SWAP_WORD (8); // Y_PSF
        SWAP_WORD (12); // X_PSF_SIG
        SWAP_WORD (16); // Y_PSF_SIG
        SWAP_WORD (20); // POSANGLE
        SWAP_WORD (24); // PLTSCALE
        SWAP_WORD (28); // PSF_INST_MAG
        SWAP_WORD (32); // PSF_INST_MAG_SIG
        SWAP_WORD (36); // PSF_INST_FLUX
        SWAP_WORD (40); // PSF_INST_FLUX_SIG
        SWAP_WORD (44); // AP_MAG
        SWAP_WORD (48); // AP_MAG_RAW
        SWAP_WORD (52); // AP_MAG_RADIUS
        SWAP_WORD (56); // AP_FLUX
        SWAP_WORD (60); // AP_FLUX_SIG
        SWAP_WORD (64); // PEAK_FLUX_AS_MAG
        SWAP_WORD (68); // CAL_PSF_MAG
        SWAP_WORD (72); // CAL_PSF_MAG_SIG
        SWAP_DBLE (76); // RA_PSF
        SWAP_DBLE (84); // DEC_PSF
        SWAP_WORD (92); // SKY
        SWAP_WORD (96); // SKY_SIGMA
        SWAP_WORD (100); // PSF_CHISQ
        SWAP_WORD (104); // CR_NSIGMA
        SWAP_WORD (108); // EXT_NSIGMA
        SWAP_WORD (112); // PSF_MAJOR
        SWAP_WORD (116); // PSF_MINOR
        SWAP_WORD (120); // PSF_THETA
        SWAP_WORD (124); // PSF_QF
        SWAP_WORD (128); // PSF_QF_PERFECT
        SWAP_WORD (132); // PSF_NDOF
        SWAP_WORD (136); // PSF_NPIX
        SWAP_WORD (140); // MOMENTS_XX
        SWAP_WORD (144); // MOMENTS_XY
        SWAP_WORD (148); // MOMENTS_YY
        SWAP_WORD (152); // MOMENTS_R1
        SWAP_WORD (156); // MOMENTS_RH
        SWAP_WORD (160); // KRON_FLUX
        SWAP_WORD (164); // KRON_FLUX_ERR
        SWAP_WORD (168); // KRON_FLUX_INNER
        SWAP_WORD (172); // KRON_FLUX_OUTER
        SWAP_WORD (176); // DIFF_NPOS
        SWAP_WORD (180); // DIFF_FRATIO
        SWAP_WORD (184); // DIFF_NRATIO_BAD
        SWAP_WORD (188); // DIFF_NRATIO_MASK
        SWAP_WORD (192); // DIFF_NRATIO_ALL
        SWAP_WORD (196); // DIFF_R_P
        SWAP_WORD (200); // DIFF_SN_P
        SWAP_WORD (204); // DIFF_R_M
        SWAP_WORD (208); // DIFF_SN_M
        SWAP_WORD (212); // FLAGS
        SWAP_WORD (216); // FLAGS2
        SWAP_BYTE (220); // N_FRAMES
        SWAP_BYTE (222); // PADDING
      }
# endif  

      gfits_table_scale_data (ftable);
      if (swapped != NULL) *swapped = TRUE;
  }

  byte = (unsigned char *) ftable[0].buffer;

  // allocate a new output data buffer
  ALLOCATE (output, CMF_PS1_DV3, nitems);
  inbyte = (unsigned char *) byte;
  otbyte = (unsigned char *) output;

  // the data in the input table does not line up with the output structure: copy carefully.
  int ST_SIZE = sizeof(CMF_PS1_DV3);
  for (i = 0; i < nitems; i++, inbyte += FT_SIZE, otbyte += ST_SIZE) {
    memcpy (&otbyte[  0], &inbyte[  0],  76); // IPP_IDET to CAL_PSF_MAG_SIG
    memcpy (&otbyte[ 80], &inbyte[ 76], 148); // RA_PSF to PADDING
  }

  free (ftable[0].buffer);
  ftable[0].buffer = (char *) output;

  return (output);
} 

// data organization (input vs output)
//              FITS                       struct
// WORD  0      IPP_IDET              0    IPP_IDET                   
// WORD  4      X_PSF                 4    X_PSF                           
// WORD  8      Y_PSF                 8    Y_PSF                           
// WORD  12     X_PSF_SIG             12   X_PSF_SIG               
// WORD  16     Y_PSF_SIG             16   Y_PSF_SIG               
// WORD  20     POSANGLE              20   POSANGLE                
// WORD  24     PLTSCALE              24   PLTSCALE                
// WORD  28     PSF_INST_MAG          28   PSF_INST_MAG            
// WORD  32     PSF_INST_MAG_SIG      32   PSF_INST_MAG_SIG        
// WORD  36     PSF_INST_FLUX         36   PSF_INST_FLUX                   
// WORD  40     PSF_INST_FLUX_SIG     40   PSF_INST_FLUX_SIG       
// WORD  44     AP_MAG                44   AP_MAG                          
// WORD  48     AP_MAG_RAW            48   AP_MAG_RAW              
// WORD  52     AP_MAG_RADIUS         52   AP_MAG_RADIUS                   
// WORD  56     AP_FLUX               56   AP_FLUX                         
// WORD  60     AP_FLUX_SIG           60   AP_FLUX_SIG             
// WORD  64     PEAK_FLUX_AS_MAG      64   PEAK_FLUX_AS_MAG        
// WORD  68     CAL_PSF_MAG           68   CAL_PSF_MAG             
// WORD  72     CAL_PSF_MAG_SIG       72   CAL_PSF_MAG_SIG                 
// DBLE  76     RA_PSF                80   RA_PSF                          
// DBLE  84     DEC_PSF               88   DEC_PSF                         
// WORD  92     SKY                   96   SKY                     
// WORD  96     SKY_SIGMA             100  SKY_SIGMA               
// WORD  100    PSF_CHISQ             104  PSF_CHISQ               
// WORD  104    CR_NSIGMA             108  CR_NSIGMA               
// WORD  108    EXT_NSIGMA            112  EXT_NSIGMA              
// WORD  112    PSF_MAJOR             116  PSF_MAJOR               
// WORD  116    PSF_MINOR             120  PSF_MINOR               
// WORD  120    PSF_THETA             124  PSF_THETA               
// WORD  124    PSF_QF                128  PSF_QF                          
// WORD  128    PSF_QF_PERFECT        132  PSF_QF_PERFECT                  
// WORD  132    PSF_NDOF              136  PSF_NDOF                
// WORD  136    PSF_NPIX              140  PSF_NPIX                
// WORD  140    MOMENTS_XX            144  MOMENTS_XX              
// WORD  144    MOMENTS_XY            148  MOMENTS_XY              
// WORD  148    MOMENTS_YY            152  MOMENTS_YY              
// WORD  152    MOMENTS_R1            156  MOMENTS_R1              
// WORD  156    MOMENTS_RH            160  MOMENTS_RH              
// WORD  160    KRON_FLUX             164  KRON_FLUX               
// WORD  164    KRON_FLUX_ERR         168  KRON_FLUX_ERR                   
// WORD  168    KRON_FLUX_INNER       172  KRON_FLUX_INNER                 
// WORD  172    KRON_FLUX_OUTER       176  KRON_FLUX_OUTER                 
// WORD  176    DIFF_NPOS             180  DIFF_NPOS               
// WORD  180    DIFF_FRATIO           184  DIFF_FRATIO             
// WORD  184    DIFF_NRATIO_BAD       188  DIFF_NRATIO_BAD                 
// WORD  188    DIFF_NRATIO_MASK      192  DIFF_NRATIO_MASK        
// WORD  192    DIFF_NRATIO_ALL       196  DIFF_NRATIO_ALL                 
// WORD  196    DIFF_R_P              200  DIFF_R_P                
// WORD  200    DIFF_SN_P             204  DIFF_SN_P               
// WORD  204    DIFF_R_M              208  DIFF_R_M                
// WORD  208    DIFF_SN_M             212  DIFF_SN_M               
// WORD  212    FLAGS                 216  FLAGS                           
// WORD  216    FLAGS2                220  FLAGS2                          
// BYTE  220    N_FRAMES              224  N_FRAMES                
// BYTE  222    PADDING               226  PADDING                         
