# include <dvo.h>

/* convert elixir-format measures to internal measures */
Measure *Measure_Elixir_ToInternal (Measure_Elixir *in, int Nvalues) {

  int i;
  Measure *out;

  ALLOCATE (out, Measure, Nvalues);

  for (i = 0; i < Nvalues; i++) {
    out[i].dR       = (in[i].dR      == NAN_S_SHORT) ? NAN : in[i].dR     * 0.01;
    out[i].dD       = (in[i].dD      == NAN_S_SHORT) ? NAN : in[i].dD     * 0.01;
    out[i].M        = (in[i].M       == NAN_S_SHORT) ? NAN : in[i].M      * 0.001;
    out[i].dM       = (in[i].dM      == NAN_U_CHAR)  ? NAN : in[i].dM     * 0.001;
    out[i].dt       = (in[i].dt      == NAN_S_SHORT) ? NAN : in[i].dt     * 0.001;
    out[i].Mcal     = (in[i].Mcal    == NAN_S_SHORT) ? NAN : in[i].Mcal   * 0.001;

    // 2008.02.26 : I've renamed Mgal to Map, and intend it to be used per aperture
    // magnitudes.  Most uses of Mgal in the past were actually aperture (isophotal) mags
    out[i].Map      = (in[i].Mgal    == NAN_S_SHORT) ? NAN : in[i].Mgal   * 0.001;
    out[i].airmass  = (in[i].airmass == NAN_S_SHORT) ? NAN : in[i].airmass* 0.001;
    out[i].FWx 	    = in[i].FWx;
    out[i].FWy 	    = in[i].fwy * in[i].FWx * 0.01;
    out[i].theta    = in[i].theta*(0x10000 / 0x100);
    out[i].dophot   = in[i].dophot;
    out[i].photcode = in[i].source;
    out[i].t        = in[i].t;
    out[i].averef   = in[i].averef;
    out[i].dbFlags  = in[i].flags;
    
    /* these can be determined if needed / desired */
    out[i].Xccd     = 0;
    out[i].Yccd     = 0;
    out[i].dXccd    = 0;
    out[i].dYccd    = 0;

    /* these do not have a corresponding value */
    out[i].az        = 0;
    out[i].stargal   = 0;
    out[i].Sky       = 0;
    out[i].dSky      = 0;
    out[i].qPSF      = 0;
    out[i].psfChisq  = 0;
    out[i].crNsigma  = 0;
    out[i].extNsigma = 0;
    out[i].photFlags = 0;

    /* XXX add these later */
    out[i].detID = 0;
    out[i].imageID = 0;
  }
  return (out);
}

/* convert internal measures to elixir-format measures */
Measure_Elixir *MeasureInternalTo_Elixir (Measure *in, int Nvalues) {

  int i;
  Measure_Elixir *out;

  ALLOCATE (out, Measure_Elixir, Nvalues);

  for (i = 0; i < Nvalues; i++) {
    out[i].dR       = isnan(in[i].dR     ) ? NAN_S_SHORT : in[i].dR      *  100.0;
    out[i].dD       = isnan(in[i].dD     ) ? NAN_S_SHORT : in[i].dD      *  100.0;
    out[i].M        = isnan(in[i].M      ) ? NAN_S_SHORT : in[i].M       * 1000.0;
    out[i].dM       = isnan(in[i].dM     ) ? NAN_U_CHAR  : in[i].dM      * 1000.0;
    out[i].dt       = isnan(in[i].dt     ) ? NAN_S_SHORT : in[i].dt      * 1000.0;
    out[i].Mcal     = isnan(in[i].Mcal   ) ? NAN_S_SHORT : in[i].Mcal    * 1000.0;
    out[i].Mgal     = isnan(in[i].Map    ) ? NAN_S_SHORT : in[i].Map     * 1000.0;
    out[i].airmass  = isnan(in[i].airmass) ? NAN_S_SHORT : in[i].airmass * 1000.0;

    if (out[i].M < 0) {
	fprintf (stderr, ".");
    }

    out[i].FWx 	   = in[i].FWx;
    out[i].fwy 	   = in[i].FWy * 100.0 / in[i].FWx;
    out[i].theta   = in[i].theta*(0x100/ 0x10000);
    out[i].dophot  = in[i].dophot;
    out[i].source  = in[i].photcode;
    out[i].t       = in[i].t;
    out[i].averef  = in[i].averef;
    out[i].flags   = in[i].dbFlags;
  }
  return (out);
}

/* convert elixir-format averages to internal averages */
Average *Average_Elixir_ToInternal (Average_Elixir *in, int Nvalues, SecFilt **primary) {

  int i;
  Average *out;

  ALLOCATE (out, Average, Nvalues);
  ALLOCATE (*primary, SecFilt, Nvalues);

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

    /* these don't exist in Elixir */
    out[i].dR      = 0;
    out[i].dD      = 0;
    out[i].uR      = 0;
    out[i].uD      = 0;
    out[i].duR     = 0;
    out[i].duD     = 0;
    out[i].P       = 0;
    out[i].dP      = 0;

    /* XXX add these later */
    out[i].objID   = 0;
    out[i].catID   = 0;

    primary[0][i].M     = (in[i].M  == NAN_S_SHORT) ? NAN : in[i].M  * 0.001;      
    primary[0][i].dM    = (in[i].dM == NAN_S_SHORT) ? NAN : in[i].dM * 0.001;      
    primary[0][i].Xm    = in[i].Xm;     
    primary[0][i].Ncode = 0;     
    primary[0][i].Nused = 0;
  }
  return (out);
}

/* convert internal averages to elixir-format averages */
Average_Elixir *AverageInternalTo_Elixir (Average *in, int Nvalues, SecFilt *primary) {

  int i;
  Average_Elixir *out;

  ALLOCATE (out, Average_Elixir, Nvalues);

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

    out[i].M       = isnan(primary[i].M)  ? NAN_S_SHORT : primary[i].M   * 1000.0;
    out[i].dM      = isnan(primary[i].dM) ? NAN_S_SHORT : primary[i].dM  * 1000.0;
    out[i].Xm      = primary[i].Xm;     
  }
  return (out);
}

/* convert elixir-format secfilts to internal secfilts */
SecFilt *SecFilt_Elixir_ToInternal (SecFilt_Elixir *in, int Nvalues) {

  int i;
  SecFilt *out;

  ALLOCATE (out, SecFilt, Nvalues);

  for (i = 0; i < Nvalues; i++) {
    out[i].M     = (in[i].M  == NAN_S_SHORT) ? NAN : in[i].M   * 0.001;
    out[i].dM    = (in[i].dM == NAN_S_SHORT) ? NAN : in[i].dM  * 0.001;
    out[i].Xm    = in[i].Xm;     
    out[i].Ncode = 0;
    out[i].Nused = 0;
  }
  return (out);
}

/* convert internal secfilts to elixir-format secfilts */
SecFilt_Elixir *SecFiltInternalTo_Elixir (SecFilt *in, int Nvalues) {

  int i;
  SecFilt_Elixir *out;

  ALLOCATE (out, SecFilt_Elixir, Nvalues);

  for (i = 0; i < Nvalues; i++) {
    out[i].M     = isnan(in[i].M)  ? NAN_S_SHORT : in[i].M   * 1000.0;
    out[i].dM    = isnan(in[i].dM) ? NAN_S_SHORT : in[i].dM  * 1000.0;
    out[i].Xm    = in[i].Xm;     
  }
  return (out);
}

/* convert elixir-format images to internal images */
Image *Image_Elixir_ToInternal (Image_Elixir *in, int Nvalues) {

  int i;
  Image *out;

  ALLOCATE (out, Image, Nvalues);

  for (i = 0; i < Nvalues; i++) {
    memcpy (&out[i].coords, &in[i].coords, sizeof(Coords));

    strncpy (out[i].name, in[i].name, 31); // in[32], out[128]
    out[i].name[31] = 0; // force termination

    out[i].tzero    	    = in[i].tzero;
    out[i].nstar    	    = in[i].nstar;
    out[i].NX	    	    = in[i].NX;
    out[i].NY	    	    = in[i].NY;
    out[i].secz    	    = (in[i].secz     == NAN_S_SHORT) ? NAN : in[i].secz     * 0.001;
    out[i].apmifit  	    = (in[i].apmifit  == NAN_S_SHORT) ? NAN : in[i].apmifit  * 0.001;
    out[i].dapmifit  	    = (in[i].dapmifit == NAN_S_SHORT) ? NAN : in[i].dapmifit * 0.001;
    out[i].Mcal   	    = (in[i].Mcal     == NAN_S_SHORT) ? NAN : in[i].Mcal     * 0.001;
    out[i].dMcal   	    = (in[i].dMcal    == NAN_S_SHORT) ? NAN : in[i].dMcal    * 0.001;
    out[i].Xm	    	    = in[i].Xm;
    out[i].photcode   	    = in[i].source;
    out[i].exptime  	    = in[i].exptime;
    out[i].detection_limit  = in[i].detection_limit;
    out[i].saturation_limit = in[i].saturation_limit;
    out[i].cerror	    = in[i].cerror;
    out[i].fwhm_x	    = in[i].fwhm_x;
    out[i].fwhm_y	    = in[i].fwhm_y;
    out[i].trate	    = in[i].trate;
    out[i].code		    = in[i].code;
    out[i].ccdnum	    = in[i].ccdnum;

    out[i].order	    = in[i].order;
    out[i].Mx		    = in[i].Mx;
    out[i].My		    = in[i].My;
    out[i].Mxx		    = in[i].Mxx;
    out[i].Mxy		    = in[i].Mxy;
    out[i].Myy		    = in[i].Myy;
    out[i].Mxxx		    = in[i].Mxxx;
    out[i].Mxxy		    = in[i].Mxxy;
    out[i].Mxyy		    = in[i].Mxyy;
    out[i].Myyy		    = in[i].Myyy;
    out[i].Mxxxx	    = in[i].Mxxxx;
    out[i].Mxxxy	    = in[i].Mxxxy;
    out[i].Mxxyy	    = in[i].Mxxyy;
    out[i].Mxyyy	    = in[i].Mxyyy;
    out[i].Myyyy	    = in[i].Myyyy;

    /* XXX add these later */
    out[i].imageID = 0;

    // not available in ELIXIR
    out[i].sidtime  	    = NAN;
    out[i].latitude  	    = NAN;
  }
  return (out);
}

/* convert internal images to elixir-format images */
Image_Elixir *ImageInternalTo_Elixir (Image *in, int Nvalues) {

  int i;
  Image_Elixir *out;

  ALLOCATE (out, Image_Elixir, Nvalues);

  for (i = 0; i < Nvalues; i++) {
    memcpy (&out[i].coords, &in[i].coords, sizeof(Coords));

    strncpy (out[i].name, in[i].name, 31); // out[32], in[128]
    out[i].name[31] = 0; // force termination

    out[i].tzero    	    = in[i].tzero;
    out[i].nstar    	    = in[i].nstar;
    out[i].NX	    	    = in[i].NX;
    out[i].NY	    	    = in[i].NY;
    out[i].secz    	    = isnan(in[i].secz    ) ? NAN_S_SHORT : in[i].secz     * 1000.0;
    out[i].apmifit    	    = isnan(in[i].apmifit ) ? NAN_S_SHORT : in[i].apmifit  * 1000.0;
    out[i].dapmifit    	    = isnan(in[i].dapmifit) ? NAN_S_SHORT : in[i].dapmifit * 1000.0;
    out[i].Mcal    	    = isnan(in[i].Mcal    ) ? NAN_S_SHORT : in[i].Mcal     * 1000.0;
    out[i].dMcal    	    = isnan(in[i].dMcal   ) ? NAN_S_SHORT : in[i].dMcal    * 1000.0;
    out[i].Xm	    	    = in[i].Xm;
    out[i].source   	    = in[i].photcode;
    out[i].exptime  	    = in[i].exptime;
    out[i].detection_limit  = in[i].detection_limit;
    out[i].saturation_limit = in[i].saturation_limit;
    out[i].cerror	    = in[i].cerror;
    out[i].fwhm_x	    = in[i].fwhm_x;
    out[i].fwhm_y	    = in[i].fwhm_y;
    out[i].trate	    = in[i].trate;
    out[i].code		    = in[i].code;
    out[i].ccdnum	    = in[i].ccdnum;

    out[i].order	    = in[i].order;
    out[i].Mx		    = in[i].Mx;
    out[i].My		    = in[i].My;
    out[i].Mxx		    = in[i].Mxx;
    out[i].Mxy		    = in[i].Mxy;
    out[i].Myy		    = in[i].Myy;
    out[i].Mxxx		    = in[i].Mxxx;
    out[i].Mxxy		    = in[i].Mxxy;
    out[i].Mxyy		    = in[i].Mxyy;
    out[i].Myyy		    = in[i].Myyy;
    out[i].Mxxxx	    = in[i].Mxxxx;
    out[i].Mxxxy	    = in[i].Mxxxy;
    out[i].Mxxyy	    = in[i].Mxxyy;
    out[i].Mxyyy	    = in[i].Mxyyy;
    out[i].Myyyy	    = in[i].Myyyy;
  }
  return (out);
}

PhotCode_Elixir *PhotCode_Internal_To_Elixir (PhotCode *in, int Nvalues) {

  int i;
  PhotCode_Elixir *out;

  ALLOCATE (out, PhotCode_Elixir, Nvalues);

  for (i = 0; i < Nvalues; i++) {
    strncpy (out[i].name, in[i].name, 31); // out[32], in[32]
    out[i].name[31] = 0; // force termination

    out[i].code  = in[i].code;         
    out[i].type  = in[i].type;         
    out[i].C  	 = in[i].C;            
    out[i].dC 	 = in[i].dC;           
    out[i].dX 	 = in[i].dX;           
    out[i].K  	 = in[i].K;            
    out[i].c1 	 = in[i].c1;           
    out[i].c2 	 = in[i].c2;           
    out[i].equiv = in[i].equiv;        
    out[i].Nc    = in[i].Nc;           
    memcpy (out[i].X, in[i].X, 4*sizeof(float));            
  }
  return (out);
}

PhotCode *PhotCode_Elixir_To_Internal (PhotCode_Elixir *in, int Nvalues) {

  int i;
  PhotCode *out;

  ALLOCATE (out, PhotCode, Nvalues);

  for (i = 0; i < Nvalues; i++) {
    strncpy (out[i].name, in[i].name, 31); // out[32], in[32]
    out[i].name[31] = 0; // force termination

    out[i].code  = in[i].code;         
    out[i].type  = in[i].type;         
    out[i].C  	 = in[i].C;            
    out[i].dC 	 = in[i].dC;           
    out[i].dX 	 = in[i].dX;           
    out[i].K  	 = in[i].K;            
    out[i].c1 	 = in[i].c1;           
    out[i].c2 	 = in[i].c2;           
    out[i].equiv = in[i].equiv;        
    out[i].Nc    = in[i].Nc;           
    memcpy (out[i].X, in[i].X, 4*sizeof(float));            

    // not defined in Elixir:
    out[i].astromErrSys      = 0.0;
    out[i].astromErrScale    = 0.0;
    out[i].astromErrMagScale = 0.0;
    out[i].photomErrSys      = 0.0;

    out[i].photomPoorMask      = 0;
    out[i].photomBadMask       = 0;
    out[i].astromPoorMask      = 0;
    out[i].astromBadMask       = 0;
  }
  return (out);
}
