# include <dvo.h>

/* convert PS1_DEV_1 formats to internal formats */

Measure *Measure_PS1_DEV_1_ToInternal (Measure_PS1_DEV_1 *in, off_t Nvalues) {

  off_t i;
  Measure *out;

  ALLOCATE (out, Measure, Nvalues);

  for (i = 0; i < Nvalues; i++) {
    out[i].dR         = in[i].dR;
    out[i].dD         = in[i].dD;
    out[i].M          = in[i].M;
    out[i].Mcal       = in[i].Mcal;
    out[i].dM         = in[i].dM;
    out[i].dt         = in[i].dt;
    out[i].airmass    = in[i].airmass;
    out[i].az         = in[i].az;
    out[i].Xccd       = in[i].Xccd;
    out[i].Yccd       = in[i].Yccd;
    out[i].Sky        = in[i].Sky;
    out[i].dSky       = in[i].dSky;
    out[i].t          = in[i].t;
    out[i].averef     = in[i].averef;
    out[i].detID      = in[i].detID;
    out[i].imageID    = in[i].imageID;
    out[i].psfQual    = in[i].psfQual;
    out[i].psfChisq   = in[i].psfChisq;
    out[i].crNsigma   = in[i].crNsigma;
    out[i].extNsigma  = in[i].extNsigma;
    out[i].FWx 	      = in[i].FWx;
    out[i].FWy 	      = in[i].FWy;
    out[i].theta      = in[i].theta;
    out[i].photcode   = in[i].photcode;
    out[i].dXccd      = in[i].dXccd;
    out[i].dYccd      = in[i].dYccd;
    out[i].dbFlags    = in[i].dbFlags;
    out[i].photFlags  = in[i].photFlags;

    // changed or added for PS1_DEV_2
    out[i].Map        = in[i].Mgal;
    out[i].dMcal      = 0; 

    // changed or added for PS1_V1
    out[i].photFlags  = in[i].photFlags | (in[i].dophot << 16);
    out[i].t_msec     = 0;
    out[i].extID      = 0;
    out[i].objID      = 0;
    out[i].catID      = 0;
    out[i].Mxx 	      = 0.0;
    out[i].Mxy 	      = 0.0;
    out[i].Myy        = 0.0;
    out[i].posangle   = 0;
    out[i].pltscale   = 0;
    out[i].psfNdof    = 0;
    out[i].psfNpix    = 0;
  }
  return (out);
}

Measure_PS1_DEV_1 *MeasureInternalTo_PS1_DEV_1 (Measure *in, off_t Nvalues) {

  off_t i;
  Measure_PS1_DEV_1 *out;

  ALLOCATE (out, Measure_PS1_DEV_1, Nvalues);

  for (i = 0; i < Nvalues; i++) {
    out[i].dR         = in[i].dR;
    out[i].dD         = in[i].dD;
    out[i].M          = in[i].M;
    out[i].Mcal       = in[i].Mcal;
    out[i].dM         = in[i].dM;
    out[i].dt         = in[i].dt;
    out[i].airmass    = in[i].airmass;
    out[i].az         = in[i].az;
    out[i].Xccd       = in[i].Xccd;
    out[i].Yccd       = in[i].Yccd;
    out[i].Sky        = in[i].Sky;
    out[i].dSky       = in[i].dSky;
    out[i].t          = in[i].t;
    out[i].averef     = in[i].averef;
    out[i].detID      = in[i].detID;
    out[i].imageID    = in[i].imageID;
    out[i].psfQual    = in[i].psfQual;
    out[i].psfChisq   = in[i].psfChisq;
    out[i].crNsigma   = in[i].crNsigma;
    out[i].extNsigma  = in[i].extNsigma;
    out[i].FWx 	      = in[i].FWx;
    out[i].FWy 	      = in[i].FWy;
    out[i].theta      = in[i].theta;
    out[i].photcode   = in[i].photcode;
    out[i].dXccd      = in[i].dXccd;
    out[i].dYccd      = in[i].dYccd;
    out[i].dbFlags    = in[i].dbFlags;

    // changed or added for PS1_DEV_2
    out[i].Mgal       = in[i].Map;

    // changed or added for PS1_V1
    out[i].photFlags  = in[i].photFlags & 0x0000ffff;
    out[i].dophot     = in[i].photFlags >> 16;
  }
  return (out);
}

// 'primary' is needed to conform with the API for Loneos and Elixir, but is not used
Average *Average_PS1_DEV_1_ToInternal (Average_PS1_DEV_1 *in, off_t Nvalues, SecFilt **primary) {

  off_t i;
  Average *out;

  ALLOCATE (out, Average, 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].dR       	 = in[i].dR;
    out[i].dD       	 = in[i].dD;
    out[i].uR       	 = in[i].uR;
    out[i].uD       	 = in[i].uD;
    out[i].duR      	 = in[i].duR;
    out[i].duD      	 = in[i].duD;
    out[i].P        	 = in[i].P;
    out[i].dP       	 = in[i].dP;
    out[i].objID 	 = in[i].objID;
    out[i].catID 	 = in[i].catID;

    // changed or added for PS1_DEV_2
    out[i].Nmeasure      = in[i].Nm;     
    out[i].Nmissing      = in[i].Nn;     
    out[i].measureOffset = in[i].offset; 
    out[i].missingOffset = in[i].missing;
    out[i].Nextend       = 0;
    out[i].extendOffset  = 0;

    // changed or added for PS1_V1
    out[i].flags    	 = in[i].code;   
    out[i].ChiSqAve    	 = NAN;
    out[i].ChiSqPM    	 = NAN;
    out[i].ChiSqPar    	 = NAN;
    out[i].Tmean    	 = 0;
    out[i].Trange   	 = 0;
    out[i].Npos       	 = 0.0;
    out[i].extID 	 = 0;
  }
  return (out);
}

// 'primary' is needed to conform with the API for Loneos and Elixir, but is not used
Average_PS1_DEV_1 *AverageInternalTo_PS1_DEV_1 (Average *in, off_t Nvalues, SecFilt *primary) {

  off_t i;
  Average_PS1_DEV_1 *out;

  ALLOCATE (out, Average_PS1_DEV_1, 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].dR       	 = in[i].dR;
    out[i].dD       	 = in[i].dD;
    out[i].uR       	 = in[i].uR;
    out[i].uD       	 = in[i].uD;
    out[i].duR      	 = in[i].duR;
    out[i].duD      	 = in[i].duD;
    out[i].P        	 = in[i].P;
    out[i].dP       	 = in[i].dP;
    out[i].objID    	 = in[i].objID;
    out[i].catID    	 = in[i].catID;

    // changed or added for PS1_DEV_2
    out[i].Nm       	 = in[i].Nmeasure;     
    out[i].Nn       	 = in[i].Nmissing;     
    out[i].offset   	 = in[i].measureOffset; 
    out[i].missing  	 = in[i].missingOffset;

    // changed or added for PS1_V1
    out[i].code          = in[i].flags;   
  }
  return (out);
}

SecFilt *SecFilt_PS1_DEV_1_ToInternal (SecFilt_PS1_DEV_1 *in, off_t Nvalues) {

  off_t i;
  SecFilt *out;

  ALLOCATE (out, SecFilt, Nvalues);

  for (i = 0; i < Nvalues; i++) {
    out[i].M     = in[i].M;      
    out[i].dM    = in[i].dM;      
    out[i].Xm    = in[i].Xm;     
    out[i].Ncode = in[i].Ncode;
    out[i].Nused = in[i].Nused;

    // changed or added for PS1_V1
    out[i].M_20  = 0;      
    out[i].M_80  = 0;      

    // changed or added for PS1_V2
    out[i].flags = 0;
 }
  return (out);
}

SecFilt_PS1_DEV_1 *SecFiltInternalTo_PS1_DEV_1 (SecFilt *in, off_t Nvalues) {

  off_t i;
  SecFilt_PS1_DEV_1 *out;

  ALLOCATE (out, SecFilt_PS1_DEV_1, Nvalues);

  for (i = 0; i < Nvalues; i++) {
    out[i].M     = in[i].M;      
    out[i].dM    = in[i].dM;      
    out[i].Xm    = in[i].Xm;     
    out[i].Ncode = in[i].Ncode;
    out[i].Nused = in[i].Nused;
  }
  return (out);
}

Image *Image_PS1_DEV_1_ToInternal (Image_PS1_DEV_1 *in, off_t Nvalues) {

  off_t 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, 63); // out[128], in[64]
    out[i].name[63] = 0; // force termination

    out[i].tzero    	    = in[i].tzero;
    out[i].nstar    	    = in[i].nstar;
    out[i].secz	    	    = in[i].secz;
    out[i].NX	    	    = in[i].NX;
    out[i].NY	    	    = in[i].NY;
    out[i].apmifit  	    = in[i].apmifit;
    out[i].dapmifit 	    = in[i].dapmifit;
    out[i].Mcal	    	    = in[i].Mcal;
    out[i].dMcal    	    = in[i].dMcal;
    out[i].Xm	    	    = in[i].Xm;
    out[i].photcode   	    = in[i].photcode;
    out[i].exptime  	    = in[i].exptime;
    out[i].sidtime  	    = in[i].sidtime;
    out[i].latitude  	    = in[i].latitude;
    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].ccdnum	    = in[i].ccdnum;
    out[i].imageID	    = in[i].imageID;

    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;

    // changed or added for PS1_DEV_2
    out[i].externID	    = 0;
    out[i].sourceID	    = 0;

    // changed or added for PS1_V1
    out[i].flags	    = in[i].code;
    out[i].parentID	    = 0;

    // changed or added for PS1_V2
    out[i].RAo  	    = NAN;
    out[i].DECo  	    = NAN;
    out[i].Radius  	    = NAN;
  }
  return (out);
}

/* convert internal images to panstarrs-format images */
Image_PS1_DEV_1 *ImageInternalTo_PS1_DEV_1 (Image *in, off_t Nvalues) {

  off_t i;
  Image_PS1_DEV_1 *out;

  ALLOCATE (out, Image_PS1_DEV_1, Nvalues);

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

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

    out[i].tzero    	    = in[i].tzero;
    out[i].nstar    	    = in[i].nstar;
    out[i].secz	    	    = in[i].secz;
    out[i].NX	    	    = in[i].NX;
    out[i].NY	    	    = in[i].NY;
    out[i].apmifit  	    = in[i].apmifit;
    out[i].dapmifit 	    = in[i].dapmifit;
    out[i].Mcal	    	    = in[i].Mcal;
    out[i].dMcal    	    = in[i].dMcal;
    out[i].Xm	    	    = in[i].Xm;
    out[i].photcode   	    = in[i].photcode;
    out[i].exptime  	    = in[i].exptime;
    out[i].sidtime  	    = in[i].sidtime;
    out[i].latitude  	    = in[i].latitude;
    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].ccdnum	    = in[i].ccdnum;
    out[i].imageID	    = in[i].imageID;

    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;

    // changed or added for PS1_V1
    out[i].code		    = in[i].flags;
  }
  return (out);
}

PhotCode *PhotCode_PS1_DEV_1_To_Internal (PhotCode_PS1_DEV_1 *in, off_t Nvalues) {

  off_t 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));            

    out[i].astromErrMagScale = in[i].astromErrMagScale;
    out[i].photomErrSys      = in[i].photomErrSys;

    // changed or added for PS1_DEV_2
    out[i].astromErrSys      = 0.0;
    out[i].astromErrScale    = 0.0;

    // changed or added for PS1_V1 (also PS1_DEV_3, deprecated)
    out[i].photomPoorMask      = 0;
    out[i].photomBadMask       = 0;
    out[i].astromPoorMask      = 0;
    out[i].astromBadMask       = 0;
  }
  return (out);
}

PhotCode_PS1_DEV_1 *PhotCode_Internal_To_PS1_DEV_1 (PhotCode *in, off_t Nvalues) {

  off_t i;
  PhotCode_PS1_DEV_1 *out;

  ALLOCATE (out, PhotCode_PS1_DEV_1, 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));            

    out[i].astromErrMagScale = out[i].astromErrMagScale;
    out[i].photomErrSys      = out[i].photomErrSys;
  }
  return (out);
}
