# include "relphot.h"

# define MARKTIME(MSG,...) { \
  float dtime; \
  gettimeofday (&stop, (void *) NULL); \
  dtime = DTIME (stop, start); \
  fprintf (stderr, MSG, __VA_ARGS__); }

// This function generates a subset of the images based on selections.  Input db has already
// been loaded with the raw fits table data
SkyList *load_images (FITS_DB *db, char *regionName, SkyRegion *region) {

  Image     *image, *subset;
  off_t      Nimage, Nsubset, Nchar;
  off_t     *LineNumber;
  struct timeval start, stop;
  char *inSubset;

  SkyTable *sky = NULL;
  SkyList *skylist = NULL;

  gettimeofday (&start, (void *) NULL);

  // load the current sky table (layout of all SkyRegions) 
  sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, TRUE, SKY_DEPTH, VERBOSE);
  SkyTableSetFilenames (sky, CATDIR, "cpt");
  
  // convert database table to internal structure (binary to Image)
  // 'image' points to the same memory as db->ftable->buffer
  image = gfits_table_get_Image (&db[0].ftable, &Nimage, &db[0].swapped);
  if (!image) {
      fprintf (stderr, "ERROR: failed to read images\n");
      exit (2);
  }
  MARKTIME("read image table: %f sec\n", dtime);

  // allocate and init an array to identify the images included in the subset
  ALLOCATE (inSubset, char, Nimage);
  memset (inSubset, 0, Nimage);

  // determine the populated SkyRegions overlapping the requested area

  // if the user selects a specific catalog, do that one; 
  // otherwise limit to the selection region
  if (regionName) {
    Nchar = strlen(regionName);
    if (!strcmp (&regionName[Nchar-4], ".cpt")) regionName[Nchar-4] = 0;
    skylist = SkyListByName (sky, regionName);

    // select the images which overlap the selected sky regions
    // 'subset' points to a new copy of the data (different from 'image')
    subset = select_images (skylist, image, Nimage, inSubset, &LineNumber, &Nsubset, NULL);
    MARKTIME("selected %d overlapping images: %f sec\n", (int) Nsubset, dtime);
  } else {
    if (region[0].Rmin > region[0].Rmax) {
      SkyRegion subregion;
      subregion = *region;
      subregion.Rmin = 0.0; subregion.Rmax = region[0].Rmax;
      skylist = SkyListByPatch (sky, -1, &subregion);

      // select the images which overlap the selected sky regions
      // 'subset' points to a new copy of the data (different from 'image')
      subset = select_images (skylist, image, Nimage, inSubset, &LineNumber, &Nsubset, &subregion);
      MARKTIME("selected %d overlapping images: %f sec\n", (int) Nsubset, dtime);

      Image *subsetExtra;
      off_t NsubsetExtra;
      off_t *LineNumberExtra, i;

      subregion.Rmin = region[0].Rmin; subregion.Rmax = 360.0; 
      SkyList *extraList = SkyListByPatch (sky, -1, &subregion);

      subsetExtra = select_images (extraList, image, Nimage, inSubset, &LineNumberExtra, &NsubsetExtra, &subregion);
      MARKTIME("selected %d overlapping images: %f sec\n", (int) Nsubset, dtime);

      REALLOCATE (subset, Image, MAX (Nsubset + NsubsetExtra, 1));
      REALLOCATE (LineNumber, off_t, MAX (Nsubset + NsubsetExtra, 1));
      
      for (i = 0; i < NsubsetExtra; i++) {
	subset[i+Nsubset] = subsetExtra[i];
	LineNumber[i+Nsubset] = LineNumberExtra[i];
      }
      Nsubset += NsubsetExtra;
      MARKTIME("selected %d overlapping images: %f sec\n", (int) NsubsetExtra, dtime);
    } else {
      skylist = SkyListByPatch (sky, -1, region);

      // select the images which overlap the selected sky regions
      // 'subset' points to a new copy of the data (different from 'image')
      subset = select_images (skylist, image, Nimage, inSubset, &LineNumber, &Nsubset, region);
      MARKTIME("selected %d overlapping images: %f sec\n", (int) Nsubset, dtime);
    }
  } 

# if (1)
  FILE *ftest = fopen ("skydump.dat", "w");
  int i;
  for (i = 0; i < skylist[0].Nregions; i++) {
    fprintf (ftest, "%s : %f %f : %f %f\n", skylist[0].regions[i][0].name, skylist[0].regions[i][0].Rmin, skylist[0].regions[i][0].Rmax, skylist[0].regions[i][0].Dmin, skylist[0].regions[i][0].Dmax);
  }
  fclose (ftest);
# endif

  // match chips to mosaics (if applicable)
  initMosaics (subset, Nsubset, image, inSubset, Nimage);
  MARKTIME("init mosaics: %f sec\n", dtime);
  
  // save the subset of images in the static reference in ImageOps, set up indexes
  initImages (subset, LineNumber, Nsubset);
  MARKTIME("init images: %f sec\n", dtime);

  return (skylist);
}

int reload_images (FITS_DB *db) {

  Image     *image;
  off_t     Nimage, Nx, i, *LineNumber;
  VTable    *vtable;

  image = getimages (&Nimage, &LineNumber);

  gfits_vtable_from_ftable (&db[0].ftable, &db[0].vtable, LineNumber, Nimage);
  vtable = &db[0].vtable;

  gfits_scan (vtable[0].header, "NAXIS1", OFF_T_FMT, 1,  &Nx);
  for (i = 0; i < Nimage; i++) {
    memcpy (vtable[0].buffer[i], &image[i], Nx);
  }
  return (TRUE);
}
