# include "dvoshell.h"

/* time concepts */
static time_t TimeReference;
static int TimeFormat;

void dbExtractMeasuresInit () {
  GetTimeFormat (&TimeReference, &TimeFormat);
}

/* return measure.field based on the selection */
double dbExtractMeasures (Average *average, SecFilt *secfilt, Measure *measure, dbField *field) {

  int Nsec;
  double value;
  double ra, dec, x, y;

  Image *image;
  Coords *mosaic;

  value = NAN;

  switch (field->ID) {
    case MEAS_MAG: /* magnitudes are already determined above */
      // we return the magnitude for this measure if:
      if (field->photcode->type == PHOT_MAG) goto valid_photcode;
      if ((field->photcode->type == PHOT_REF) && (measure[0].photcode == field->photcode->code)) goto valid_photcode;
      if ((field->photcode->type == PHOT_DEP) && (measure[0].photcode == field->photcode->code)) goto valid_photcode;
      if ((field->photcode->type == PHOT_SEC) && (GetPhotcodeEquivCodebyCode (measure[0].photcode) == field->photcode->code)) goto valid_photcode;
      break;

  valid_photcode:
      switch (field->magMode) {
	case MAG_INST:
	  value = PhotInst (measure);  
	  break;
	case MAG_CAT:
	  value = PhotCat  (measure); 
	  break;
	case MAG_SYS:
	  value = PhotSys  (measure, average, secfilt); 
	  break;
	case MAG_REL:
	  value = PhotRel  (measure, average, secfilt); 
	  break;
	case MAG_CAL:
	  value = PhotCal  (measure, average, secfilt, measure, GetPhotcodeEquivbyCode (measure[0].photcode)); 
	  break;
	case MAG_AVE:
	  value = PhotAve  (GetPhotcodeEquivbyCode (measure[0].photcode), average, secfilt); 
	  break;
	case MAG_REF:
	  value = PhotRef  (GetPhotcodeEquivbyCode (measure[0].photcode), average, secfilt, measure); 
	  break;
	case MAG_ERR:
	  value = PhotdM  (GetPhotcodeEquivbyCode (measure[0].photcode), average, secfilt); 
	  break;
	case MAG_CHISQ:
	  value = PhotXm  (GetPhotcodeEquivbyCode (measure[0].photcode), average, secfilt); 
	  break;
	case MAG_NCODE:
	  Nsec = GetPhotcodeNsec (GetPhotcodeEquivCodebyCode (measure[0].photcode));
	  if (Nsec == -1) break;
	  value = secfilt[Nsec].Ncode;
	  break;
	case MAG_NPHOT:
	  Nsec = GetPhotcodeNsec (GetPhotcodeEquivCodebyCode (measure[0].photcode));
	  if (Nsec == -1) break;
	  value = secfilt[Nsec].Nused;
	  break;
      }
      break;
    case MEAS_RA: /* OK */
      value = average[0].R - measure[0].dR / 3600.0;
      break;
    case MEAS_DEC: /* OK */
      value = average[0].D - measure[0].dD / 3600.0;
      break;
    case MEAS_RA_AVE: /* OK */
      value = average[0].R;
      break;
    case MEAS_DEC_AVE: /* OK */
      value = average[0].D;
      break;
    case MEAS_RA_AVE_ERR: /* OK */
      value = average[0].dR;
      break;
    case MEAS_DEC_AVE_ERR: /* OK */
      value = average[0].dD;
      break;
    case MEAS_U_RA: /* OK */
      value = average[0].uR;
      break;
    case MEAS_U_DEC: /* OK */
      value = average[0].uD;
      break;
    case MEAS_U_RA_ERR: /* OK */
      value = average[0].duR;
      break;
    case MEAS_U_DEC_ERR: /* OK */
      value = average[0].duD;
      break;
    case MEAS_PAR: /* OK */
      value = average[0].R;
      break;
    case MEAS_PAR_ERR: /* OK */
      value = average[0].D;
      break;
    case MEAS_XP: /* OK */
      value = average[0].Xp;
      break;
    case MEAS_NMEAS: /* OK */
      value = average[0].Nm;
      break;
    case MEAS_NMISS: /* OK */
      value = average[0].Nn;
      break;
    case MEAS_OBJFLAGS: /* OK */
      value = average[0].code;
      break;
    // note that these represent the ra displacement relative to the average, not 
    // the error.
    case MEAS_RA_OFFSET: /* OK */
      value = measure[0].dR;
      break;
    case MEAS_DEC_OFFSET: /* OK */
      value = measure[0].dD;
      break;
    case MEAS_RA_OFFSET_ERR: /* OK */
      value = NAN;
      break;
    case MEAS_DEC_OFFSET_ERR: /* OK */
      value = NAN;
      break;
    case MEAS_AIRMASS: /* OK */
      value = measure[0].airmass;
      break;
    case MEAS_AZ: /* OK */
      value = measure[0].az;
      break;
    case MEAS_EXPTIME: /* OK */
      value = pow (10.0, measure[0].dt * 0.4);
      break;
    case MEAS_PHOTCODE: /* OK */
      value = measure[0].photcode;
      break;
    case MEAS_TIME: /* OK */
      value = TimeValue (measure[0].t, TimeReference, TimeFormat);
      break;
    case MEAS_FWHM: /* OK */
      value = 0.01*(measure[0].FWx + measure[0].FWy);
      break;
    case MEAS_FWHM_MAJ: /* OK */
      value = 0.01*measure[0].FWx;
      break;
    case MEAS_FWHM_MIN: /* OK */
      value = 0.01*measure[0].FWy;
      break;
    case MEAS_THETA: /* OK */
      value = measure[0].theta;
      break;
    case MEAS_DOPHOT: /* OK */
      value = measure[0].dophot;
      break;
    case MEAS_DB_FLAGS: /* ? */
      value = measure[0].dbFlags;
      break;
    case MEAS_PHOT_FLAGS: /* ? */
      value = measure[0].photFlags;
      break;
    case MEAS_XCCD: /* OK */
/* I need to perform this conversion for ELIXIR and LONEOS formats on load */      
# if 0
      value = measure[0].Xccd;
# else
      ra  = average[0].R - measure[0].dR / 3600.0;
      dec = average[0].D - measure[0].dD / 3600.0;
      image = MatchImage (measure[0].t, measure[0].photcode);
      if (image == NULL) break;
      RD_to_XY (&x, &y, ra, dec, &image[0].coords);
      value = x;
# endif
      break;
    case MEAS_YCCD: /* OK */
/* I need to perform this conversion for ELIXIR and LONEOS formats on load */      
# if 0
      value = measure[0].Yccd;
# else
      ra  = average[0].R - measure[0].dR / 3600.0;
      dec = average[0].D - measure[0].dD / 3600.0;
      image = MatchImage (measure[0].t, measure[0].photcode);
      if (image == NULL) break;
      RD_to_XY (&x, &y, ra, dec, &image[0].coords);
      value = y;
# endif
      break;
    case MEAS_XMOSAIC: /* OK */
      ra  = average[0].R - measure[0].dR / 3600.0;
      dec = average[0].D - measure[0].dD / 3600.0;
      mosaic = MatchMosaic (measure[0].t, measure[0].photcode);
      if (mosaic == NULL) break;
      RD_to_XY (&x, &y, ra, dec, mosaic);
      value = x;
      break;
    case MEAS_YMOSAIC: /* OK */
      ra  = average[0].R - measure[0].dR / 3600.0;
      dec = average[0].D - measure[0].dD / 3600.0;
      mosaic = MatchMosaic (measure[0].t, measure[0].photcode);
      if (mosaic == NULL) break;
      RD_to_XY (&x, &y, ra, dec, mosaic);
      value = y;
      break;

    case MEAS_SKY: /* OK */
      value = measure[0].Sky;
      break;
    case MEAS_dSKY: /* OK */
      value = measure[0].dSky;
      break;
    case MEAS_DET_ID: /* OK */
      value = measure[0].detID;
      break;
    case MEAS_OBJ_ID: /* OK */
      value = measure[0].averef;
      break;
    case MEAS_IMAGE_ID: /* OK */
      value = measure[0].imageID;
      break;
    case MEAS_PSF_QF: /* OK */
      value = measure[0].qPSF;
      break;
    case MEAS_PSF_PROB: /* OK */
      value = measure[0].psfProb;
      break;
    case MEAS_CR_NSIGMA: /* OK */
      value = measure[0].crNsigma;
      break;
    case MEAS_EXT_NSIGMA: /* OK */
      value = measure[0].extNsigma;
      break;
    case MEAS_STARGAL: /* OK */
      value = measure[0].stargal;
      break;
  }
  return (value);
}

/** the mosaic entries do not use the registered mosaic found 
    by MatchImage (via FindMosaicForImage).  Rather, they use
    a coordinate frame saved by SetImageSelection 
**/
