# include "dvoshell.h"

int mextract (int argc, char **argv) {
  
  int i, j, k, m, n, N, N1, Npts, NPTS, last, Nfields, Nreturn, Ncstack, Nstack;
  int param, mode, Nsecfilt;
  char *RegionName, *RegionList, *p;
  double *M1;
  char **cstack, name[1024];
  float *values;

  Catalog catalog;
  SkyList *skylist;
  PhotCode *code;
  Vector **vec;

  dbField *fields;
  dbStack *stack;

  /* defaults */
  skylist = NULL;
  RegionName = NULL;
  RegionList = NULL;
  code = NULL;
  mode = MAG_REL;
  dvo_catalog_init (&catalog, TRUE);

  /* load photcode information */
  if (!InitPhotcodes ()) goto escape;
  Nsecfilt = GetPhotcodeNsecfilt ();
  
  // init locally static variables (time refs)
  dbExtractMeasuresInit();

  // remove skyregion options
  // XXX this needs to explicitly handle -qregion and -skyregion
  if (!SetRegionSelection (&argc, argv, &RegionName, &RegionList)) goto escape;

  // command-line is of the form: avextract field,field, field [where (field op value)...]

  // parse the fields to be extracted and returned
  fields = dbCmdlineFields (argc, argv, DVO_TABLE_MEASURE, &last, &Nfields);
  if (fields == NULL) return (FALSE);

  // parse the remainder of the line as a boolean math expression
  cstack = isolate_elements (argc-last, &argv[last], &Ncstack);
  
  // construct the db Boolean math stack (frees cstack)
  stack = dbRPN (Ncstack, cstack, &Nstack);

  Nreturn = Nfields; 
  dbCheckStack (stack, Nstack, DVO_TABLE_MEASURE, &fields, &Nfields);
  // XXX handle errors

  /* load region corresponding to selection above */
  if ((skylist = SelectRegions (RegionName, RegionList)) == NULL) goto escape;

  // XXX is this still needed?
  // if (!SetImageSelection (param, ((RegionName == NULL) && (RegionList == NULL)))) goto escape;

  /* create storage vector */
  ALLOCATE (values, float, Nfields);
  ALLOCATE (vec, Vector *, Nreturn);
  for (i = 0; i < Nreturn; i++) {
    if (ISNUM(fields[i].name[0])) {
      sprintf (name, "v_%s", fields[i].name);
    } else {
      sprintf (name, "%s", fields[i].name);
    }
    if ((vec[i] = SelectVector (name, ANYVECTOR, TRUE)) == NULL) goto escape;
  }

  Npts = 0;
  NPTS = 1;

  // XXX need to add interrupt test to this loop
  for (i = 0; i < skylist[0].Nregions; i++) {
    /* lock, load, unlock catalog */
    catalog.filename = skylist[0].filename[i];
    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
    catalog.Nsecfilt = Nsecfilt;

    // an error exit status here is a significant error
    if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
      exit (2);
    }
    dvo_catalog_unlock (&catalog);

    /* XXX need to call dvo_catalog_chipcoords here passing the loaded images */

    for (j = 0; j < catalog.Naverage; j++) {
      m = catalog.average[j].offset;
      for (k = 0; k < catalog.average[j].Nm; k++, m++) {

	// extract the relevant values for this measurement
	for (n = 0; n < Nfields; n++) {
	  values[n] = dbExtractMeasures (&catalog.average[j], &catalog.secfilt[j*Nsecfilt], &catalog.measure[m], &fields[n]);
	}
	
	// test the conditional statement
	if (!dbBooleanCond (stack, Nstack, values)) continue;
	for (n = 0; n < Nreturn; n++) {
	  vec[n][0].elements[Npts] = values[n];
	}
	Npts++;
	if (Npts >= NPTS) {
	  NPTS += 2000;
	  for (n = 0; n < Nreturn; n++) {
	    REALLOCATE (vec[n][0].elements, float, NPTS);
	  }
	}
      }
    }
    dvo_catalog_free (&catalog);
  }
  for (n = 0; n < Nreturn; n++) {
    vec[n][0].Nelements = Npts;
    REALLOCATE (vec[n][0].elements, float, MAX(1,Npts));
  }

  // XXX free fields and stack 

  FreeImageSelection ();
  SkyListFree (skylist, ((RegionName != NULL) || (RegionList != NULL)));
  if (RegionName != NULL) free (RegionName);
  if (RegionList != NULL) free (RegionList);
  return (TRUE);

usage:
  gprint (GP_ERR, "USAGE: mextract (value) [options]\n");
  gprint (GP_ERR, "  value: measure.parameter or photcode\n");
  return (FALSE);

escape:
  FreeImageSelection ();
  SkyListFree (skylist, ((RegionName != NULL) || (RegionList != NULL)));
  dvo_catalog_free (&catalog);
  if (RegionName != NULL) free (RegionName);
  if (RegionList != NULL) free (RegionList);
  return (FALSE);
}
