# include "dvoshell.h"

void dbFreeFields (dbField *fields, int Nfields) {

  int i;

  if (fields == NULL) return;

  for (i = 0; i < Nfields; i++) {
    if (fields[i].name != NULL) free (fields[i].name);
    if (fields[i].photcode != NULL) {
      if (fields[i].photcode[0].type == PHOT_MAG) {
	free (fields[i].photcode);
      }
    }
  }
  free (fields);
}

void dbInitField (dbField *field) {
  field->name = NULL;
  field->extract = FALSE;
  field->table = 0;
  field->ID = 0;
  field->magMode = 0;
  field->photcode = NULL;
}

int GetMagMode (char *string) {

  if (!strcasecmp (string, "inst"))  return (MAG_INST);
  if (!strcasecmp (string, "cat"))   return (MAG_CAT);
  if (!strcasecmp (string, "sys"))   return (MAG_SYS);
  if (!strcasecmp (string, "rel"))   return (MAG_REL);
  if (!strcasecmp (string, "cal"))   return (MAG_CAL);
  if (!strcasecmp (string, "ave"))   return (MAG_AVE);
  if (!strcasecmp (string, "ref"))   return (MAG_REF);
  if (!strcasecmp (string, "err"))   return (MAG_ERR);
  if (!strcasecmp (string, "chisq")) return (MAG_CHISQ);
  if (!strcasecmp (string, "ncode")) return (MAG_NCODE);
  if (!strcasecmp (string, "nphot")) return (MAG_NPHOT);
  return (MAG_NONE);
}

PhotCode *ParsePhotcodeField (char *field, int *mode, int defMode) {

  int useDefault;
  char *tmpstring, *p;
  PhotCode *code;

  *mode = defMode;
  useDefault = TRUE;

  p = strchr (field, ':');
  if (p != NULL) {
    *mode = GetMagMode (p + 1);
    useDefault = FALSE;
    if (*mode == MAG_NONE) return (NULL);
    tmpstring = strncreate (field, p - field);
  } else {
    tmpstring = strcreate (field);
  }
  if (!strcasecmp (tmpstring, "MAG")) {
    ALLOCATE (code, PhotCode, 1);
    code[0].code = 0;
    strcpy (code[0].name, "MAG");
    code[0].type = PHOT_MAG;
    free (tmpstring);
    return (code);
  }
  code = GetPhotcodebyName (tmpstring);
  if (!code) {
      return NULL;
  }


  // enforce compatibility
  // XXX this is kind of poorly done
  if ((code[0].type == PHOT_REF) && (*mode != MAG_ERR)) {
    *mode = MAG_CAT;
  }
  if (code[0].type == PHOT_DEP) {
    if (useDefault) {
      *mode = MAG_REL;
    }
  } 
  free (tmpstring);
  return (code);
}

# define ESCAPE(F,M) { \
  field->ID = (F); \
  field->magMode = (M); \
  field->photcode = NULL; \
  return (TRUE); }

int ParseMeasureField (dbField *field, char *fieldName) {

  int mode;
  PhotCode *code;

  field->table = DVO_TABLE_MEASURE;
  field->name  = strcreate (fieldName);

  if (!strcasecmp (fieldName, "RA"))       ESCAPE (MEAS_RA,   	     	MAG_NONE);
  if (!strcasecmp (fieldName, "DEC"))      ESCAPE (MEAS_DEC,  	     	MAG_NONE);
  if (!strcasecmp (fieldName, "RA:AVE"))   ESCAPE (MEAS_RA_AVE,      	MAG_NONE);
  if (!strcasecmp (fieldName, "DEC:AVE"))  ESCAPE (MEAS_DEC_AVE,     	MAG_NONE);
  if (!strcasecmp (fieldName, "RA:ERR"))   ESCAPE (MEAS_RA_AVE_ERR,  	MAG_NONE);
  if (!strcasecmp (fieldName, "DEC:ERR"))  ESCAPE (MEAS_DEC_AVE_ERR, 	MAG_NONE);
  if (!strcasecmp (fieldName, "uRA"))      ESCAPE (MEAS_U_RA,        	MAG_NONE);
  if (!strcasecmp (fieldName, "uDEC"))     ESCAPE (MEAS_U_DEC,       	MAG_NONE);
  if (!strcasecmp (fieldName, "duRA"))     ESCAPE (MEAS_U_RA_ERR,    	MAG_NONE);
  if (!strcasecmp (fieldName, "duDEC"))    ESCAPE (MEAS_U_DEC_ERR,   	MAG_NONE);
  if (!strcasecmp (fieldName, "PAR"))      ESCAPE (MEAS_PAR,         	MAG_NONE);
  if (!strcasecmp (fieldName, "dPAR"))     ESCAPE (MEAS_PAR_ERR,       	MAG_NONE);
  if (!strcasecmp (fieldName, "dR"))       ESCAPE (MEAS_RA_OFFSET,   	MAG_NONE);
  if (!strcasecmp (fieldName, "dD"))       ESCAPE (MEAS_DEC_OFFSET,  	MAG_NONE);
  if (!strcasecmp (fieldName, "dR:ERR"))   ESCAPE (MEAS_RA_OFFSET_ERR,  MAG_NONE);
  if (!strcasecmp (fieldName, "dD:ERR"))   ESCAPE (MEAS_DEC_OFFSET_ERR, MAG_NONE);
  if (!strcasecmp (fieldName, "xp"))       ESCAPE (MEAS_XP,          	MAG_NONE);
  if (!strcasecmp (fieldName, "nmeas"))    ESCAPE (MEAS_NMEAS,       	MAG_NONE);
  if (!strcasecmp (fieldName, "nmiss"))    ESCAPE (MEAS_NMISS,       	MAG_NONE);
  if (!strcasecmp (fieldName, "objflags")) ESCAPE (MEAS_OBJFLAGS,     	MAG_NONE);
  if (!strcasecmp (fieldName, "AIRMASS"))  ESCAPE (MEAS_AIRMASS,     	MAG_NONE);
  if (!strcasecmp (fieldName, "ALT"))      ESCAPE (MEAS_ALT,     	MAG_NONE);
  if (!strcasecmp (fieldName, "AZ"))       ESCAPE (MEAS_AZ,     	MAG_NONE);
  if (!strcasecmp (fieldName, "EXPTIME"))  ESCAPE (MEAS_EXPTIME,     	MAG_NONE);
  if (!strcasecmp (fieldName, "PHOTCODE")) ESCAPE (MEAS_PHOTCODE,    	MAG_NONE);
  if (!strcasecmp (fieldName, "TIME"))     ESCAPE (MEAS_TIME,        	MAG_NONE);
  if (!strcasecmp (fieldName, "FWHM"))     ESCAPE (MEAS_FWHM,        	MAG_NONE);
  if (!strcasecmp (fieldName, "FWHM_MAJ")) ESCAPE (MEAS_FWHM_MAJ,    	MAG_NONE);
  if (!strcasecmp (fieldName, "FWHM_MIN")) ESCAPE (MEAS_FWHM_MIN,    	MAG_NONE);
  if (!strcasecmp (fieldName, "THETA"))    ESCAPE (MEAS_THETA,       	MAG_NONE);
  if (!strcasecmp (fieldName, "FLAGS"))    ESCAPE (MEAS_FLAGS,       	MAG_NONE);
  if (!strcasecmp (fieldName, "XCCD"))     ESCAPE (MEAS_XCCD, 	     	MAG_NONE);
  if (!strcasecmp (fieldName, "YCCD"))     ESCAPE (MEAS_YCCD, 	     	MAG_NONE);
  if (!strcasecmp (fieldName, "XMOSAIC"))  ESCAPE (MEAS_XMOSAIC,     	MAG_NONE);
  if (!strcasecmp (fieldName, "YMOSAIC"))  ESCAPE (MEAS_YMOSAIC,     	MAG_NONE);
  if (!strcasecmp (fieldName, "XCHIP"))    ESCAPE (MEAS_XCCD, 	     	MAG_NONE);
  if (!strcasecmp (fieldName, "YCHIP"))    ESCAPE (MEAS_YCCD, 	     	MAG_NONE);
  if (!strcasecmp (fieldName, "XFPA"))     ESCAPE (MEAS_XMOSAIC,     	MAG_NONE);
  if (!strcasecmp (fieldName, "YFPA"))     ESCAPE (MEAS_YMOSAIC,     	MAG_NONE);
  if (!strcasecmp (fieldName, "DETID"))    ESCAPE (MEAS_DETID,     	MAG_NONE);
  if (!strcasecmp (fieldName, "OBJID"))    ESCAPE (MEAS_OBJID,     	MAG_NONE);
  if (!strcasecmp (fieldName, "IMAGEID"))  ESCAPE (MEAS_IMAGEID,     	MAG_NONE);
  if (!strcasecmp (fieldName, "stargal"))  ESCAPE (MEAS_IMAGEID,     	MAG_NONE);
  if (!strcasecmp (fieldName, "psfqf"))    ESCAPE (MEAS_IMAGEID,     	MAG_NONE);
  if (!strcasecmp (fieldName, "sky"))      ESCAPE (MEAS_IMAGEID,     	MAG_NONE);
  if (!strcasecmp (fieldName, "sky_err"))  ESCAPE (MEAS_IMAGEID,     	MAG_NONE);

  // for words that don't parse, try a photcode

  // check for code:mode in photcode name 
  code = ParsePhotcodeField (fieldName, &mode, MAG_REL);
  if (code == NULL) return (FALSE);

  field->ID = MEAS_MAG;
  field->magMode = mode;
  field->photcode = code;
  return (TRUE);
}
  
int ParseAverageField (dbField *field, char *fieldName) {

  int mode;
  PhotCode *code;

  field->table = DVO_TABLE_AVERAGE;
  field->name  = strcreate (fieldName);

  if (!strcasecmp (fieldName, "RA"))    ESCAPE (AVE_RA,        MAG_NONE);
  if (!strcasecmp (fieldName, "DEC"))   ESCAPE (AVE_DEC,       MAG_NONE);
  if (!strcasecmp (fieldName, "dRA"))   ESCAPE (AVE_RA_ERR,    MAG_NONE);
  if (!strcasecmp (fieldName, "dDEC"))  ESCAPE (AVE_DEC_ERR,   MAG_NONE);
  if (!strcasecmp (fieldName, "uRA"))   ESCAPE (AVE_U_RA,      MAG_NONE);
  if (!strcasecmp (fieldName, "uDEC"))  ESCAPE (AVE_U_DEC,     MAG_NONE);
  if (!strcasecmp (fieldName, "duRA"))  ESCAPE (AVE_U_RA_ERR,  MAG_NONE);
  if (!strcasecmp (fieldName, "duDEC")) ESCAPE (AVE_U_DEC_ERR, MAG_NONE);
  if (!strcasecmp (fieldName, "PAR"))   ESCAPE (AVE_PAR,       MAG_NONE);
  if (!strcasecmp (fieldName, "dPAR"))  ESCAPE (AVE_PAR_ERR,   MAG_NONE);
  if (!strcasecmp (fieldName, "Xp"))    ESCAPE (AVE_Xp,        MAG_NONE);
  if (!strcasecmp (fieldName, "NMEAS")) ESCAPE (AVE_NMEAS,     MAG_NONE);
  if (!strcasecmp (fieldName, "NMISS")) ESCAPE (AVE_NMISS,     MAG_NONE);
  if (!strcasecmp (fieldName, "FLAG"))  ESCAPE (AVE_FLAG,      MAG_NONE);
  if (!strcasecmp (fieldName, "TYPE"))  ESCAPE (AVE_TYPE,      MAG_NONE);
  if (!strcasecmp (fieldName, "OBJID")) ESCAPE (AVE_OBJID,     MAG_NONE);

  // for words that don't parse, try a photcode

  // check for code:mode in photcode name 
  code = ParsePhotcodeField (fieldName, &mode, MAG_AVE);
  if (code == NULL) return (FALSE);
  if (code[0].type == PHOT_MAG) {
    gprint (GP_ERR, "'mag' is ambiguous for avextract\n");
    free (code);
    return (FALSE);
  }

  field->ID = AVE_MAG;
  field->magMode = mode;
  field->photcode = code;
  return (TRUE);
}
