# include "relastro.h"

int bcatalog (Catalog *subcatalog, Catalog *catalog) {

  off_t i, j, offset;
  off_t NAVERAGE, NMEASURE, Naverage, Nmeasure, Nm;
  int Nsecfilt;

  // XXX in the future, use catalog[0].Nsecfilt only?  allow catalogs to have variable Nsecfilt?
  Nsecfilt = GetPhotcodeNsecfilt ();
  assert (catalog[0].Nsecfilt == Nsecfilt);

  /* we are moving only the subset of measurements from catalog[0] to subcatalog[0] */
  NAVERAGE = 50;
  NMEASURE = 1000;
  ALLOCATE (subcatalog[0].average, Average, NAVERAGE);
  ALLOCATE (subcatalog[0].secfilt, SecFilt, NAVERAGE*Nsecfilt);
  ALLOCATE (subcatalog[0].measure, Measure, NMEASURE);
  Nmeasure = Naverage = 0;

  /* exclude stars not in range or with too few measurements */
  for (i = 0; i < catalog[0].Naverage; i++) {
    if (catalog[0].average[i].Nmeasure <= SRC_MEAS_TOOFEW) {
      continue;
    }
    
    /* start with all stars good */
    subcatalog[0].average[Naverage] = catalog[0].average[i];
    subcatalog[0].average[Naverage].measureOffset = Nmeasure;
    for (j = 0; j < Nsecfilt; j++) {
      subcatalog[0].secfilt[Nsecfilt*Naverage+j] = catalog[0].secfilt[Nsecfilt*i+j];
    }

    if (RESET) {
      // XXX reset the ra,dec coords?
      // XXX define astrometry vs photometry average.dbFlags
      // XXX put photometry flags in secfilt (ie, per average mag?)
      subcatalog[0].average[Naverage].flags &= ~ID_STAR_FEW;
      subcatalog[0].average[Naverage].flags &= ~ID_STAR_POOR;
    }

    Nm = 0;
    for (j = 0; j < catalog[0].average[i].Nmeasure; j++) {

      offset = catalog[0].average[i].measureOffset + j;
      
      //filter objects based on user supplied criteria
      if (!MeasFilterTest(&catalog[0].measure[offset])) {
	catalog[0].measure[offset].dbFlags &= ~ID_MEAS_USED_CHIP;
	continue;
      }

      //filter out outliers
      if (FlagOutlier && (catalog[0].measure[offset].dbFlags & ID_MEAS_POOR_ASTROM)) {
	catalog[0].measure[offset].dbFlags &= ~ID_MEAS_USED_CHIP;
	continue;
      }
      catalog[0].measure[offset].dbFlags |= ID_MEAS_USED_CHIP;

      // re-assess on each run of relastro if a measurement should be used

      // NOCAL : this flag is used to mark measurements which must be ignored for this
      // analysis.  an example would be time ranges or photcodes which are ignored.  NOCAL
      // is internal only; it is not written out.

      // SKIP : this flag is used to mark measurements currently ignored, but may be
      // allowed before the analysis is complete.  for example, a star with measurements
      // only near the edge of images will have this flag set for most of the analysis,
      // but before the final average properties are calculated, these measurements may be
      // allowed.

      subcatalog[0].measure[Nmeasure].dbFlags &= ~ID_MEAS_SKIP_ASTROM;
      subcatalog[0].measure[Nmeasure].dbFlags &= ~ID_MEAS_NOCAL;
      subcatalog[0].measure[Nmeasure]          = catalog[0].measure[offset];
      subcatalog[0].measure[Nmeasure].averef   = Naverage;
      if (RESET) {
        subcatalog[0].measure[Nmeasure].dbFlags &= ~ID_MEAS_POOR_ASTROM;
        subcatalog[0].measure[Nmeasure].dbFlags &= ~ID_MEAS_AREA;
      }
     
      Nmeasure ++;
      Nm ++;
      if (Nmeasure == NMEASURE) {
        NMEASURE += 1000;
        REALLOCATE (subcatalog[0].measure, Measure, NMEASURE);
      }
    }
    subcatalog[0].average[Naverage].Nmeasure = Nm;
    Naverage ++;
    if (Naverage == NAVERAGE) {
      NAVERAGE += 50;
      REALLOCATE (subcatalog[0].average, Average, NAVERAGE);
      REALLOCATE (subcatalog[0].secfilt, SecFilt, NAVERAGE*Nsecfilt);
    }
  }
  REALLOCATE (subcatalog[0].average, Average, MAX (Naverage, 1));
  REALLOCATE (subcatalog[0].measure, Measure, MAX (Nmeasure, 1));
  REALLOCATE (subcatalog[0].secfilt, SecFilt, Nsecfilt*MAX (Naverage, 1));
  subcatalog[0].Naverage = Naverage;
  subcatalog[0].Nmeasure = Nmeasure;
  subcatalog[0].Nsecfilt = catalog[0].Nsecfilt;
  subcatalog[0].Nsecf_mem = Naverage * Nsecfilt;
  assert (Nsecfilt == catalog[0].Nsecfilt);

  if (VERBOSE) {
    fprintf (stderr, "%lld: using %lld stars (%lld measures) for catalog\n", (long long) i, (long long) subcatalog[0].Naverage, (long long) subcatalog[0].Nmeasure);
   }
  return (TRUE);
}
