# include "dvoshell.h"

int avextract (int argc, char **argv) {
  
  int i, j, n, m, Npts, NPTS, last, Nfields, Nreturn, Ncstack, Nstack;
  int Nsecfilt, mode;
  char *RegionName, *RegionList, *p;
  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_AVE;
  dvo_catalog_init (&catalog, TRUE);

  /* load photcode information */
  if (!InitPhotcodes ()) goto escape;
  Nsecfilt = GetPhotcodeNsecfilt ();

  // 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_AVERAGE, &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_AVERAGE, &fields, &Nfields);
  // XXX handle errors

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

  /* create output storage vectors */
  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 = 0;

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

    for (j = 0; j < catalog.Naverage; j++) {
      m = catalog.average[j].offset;
      // extract the relevant values
      // XXX for measure values, this could be optimized for one loop over measures...
      for (n = 0; n < Nfields; n++) {
	values[n] = dbExtractAverages (&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 

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

usage:
  gprint (GP_ERR, "USAGE: avextract (value) [options]\n");
  gprint (GP_ERR, "  value: average.parameter or photcode\n");

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