# include "relphot.h"

/* This function is essentially identical to relphot_images, except:

 * load the subset images saved by the master node
 * distinguish detections we own (touch our images) and those we don't
 * distinguish objects we own (in region) and those we don't
 * update the unowned detections for owned objects from neighbor regions
 * update the unowned objects for owned detections 
 */

int dumpObjects (char *filename, Catalog *catalog, int Ncatalog);

int relphot_parallel_images () {

  int i, Ncatalog;
  Catalog *catalog = NULL;

  INITTIME;

  client_logger_init (CATDIR);

  // load the RegionTable (UserRegion should not be used at this level)
  RegionHostTable *regionHosts = RegionHostTableLoad (CATDIR, REGION_FILE);
  int myHost = regionHosts->index[REGION_HOST_ID];
  RegionHostFindNeighbors (regionHosts, myHost);
  client_logger_message ("started parallel images on %s\n", regionHosts->hosts[myHost].hostname);

  // load the subset images belonging to this host
  off_t Nimage;
  Image *image = ImageTableLoad (IMAGE_TABLE, &Nimage);
  if (!image) {
    fprintf (stderr, "ERROR loading image %s\n", IMAGE_TABLE);
    exit (2);
  }

  // once we have read this table, we should remove it for repeat runs
  // unlink (IMAGE_TABLE); // XXX a bit risky, add some protection?

  // XXX need to deal with mosaic vs image...
  makeMosaics (image, Nimage);

  initImages (image, NULL, Nimage);

  // load the flat correction table (if defined)
  char flatcorrfile[256];
  sprintf (flatcorrfile, "%s/flatcorr.fits", CATDIR);
  FlatCorrectionTable *flatcorr = FlatCorrectionLoad (flatcorrfile, VERBOSE);

  SkyTable *sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, TRUE, SKY_DEPTH, VERBOSE);
  SkyTableSetFilenames (sky, CATDIR, "cpt");

  // UserPatch.Rmin,Rmax may have range from a few degrees < 0.0 to few degrees > 360.0.
  // the following function correctly chooses the sky regions on the 0,360 boundary
  SkyList *skylist = SkyListByBounds (sky, -1, UserPatch.Rmin, UserPatch.Rmax, UserPatch.Dmin, UserPatch.Dmax);

  /* load catalog data from region files (hostID is 0 since we are not a client */
  catalog = load_catalogs (skylist, &Ncatalog, 0, NULL);
  MARKTIME("-- load catalog data: %f sec\n", dtime);
  client_logger_message ("loaded catalog data\n");

  // NOTE: if I let all hosts load blindly, I saturate the data clients with too many
  // relphot_client requests.  I need to have the master mediate this.  the master
  // will not launch the next remote job until this one says it is done
  char *syncfile = make_filename (CATDIR, regionHosts->hosts[myHost].hostname, REGION_HOST_ID, "loadcat.sync");
  update_sync_file (syncfile, 1);
  
  // generate tables go from catID,objID -> catSeq,objSeq
  indexCatalogs (catalog, Ncatalog);
  client_logger_message ("indexed Catalogs\n");

  /* match measurements with images, mosaics */
  initImageBins  (catalog, Ncatalog, TRUE);
  MARKTIME("-- make image bins: %f sec\n", dtime);

  initMosaicBins (catalog, Ncatalog, TRUE);
  initMrel (catalog, Ncatalog);

  findImages (catalog, Ncatalog, TRUE);
  MARKTIME("-- set up image indexes: %f sec\n", dtime);

  findMosaics (catalog, Ncatalog, TRUE);  /* also sets Grid values */
  MARKTIME("-- set up mosaic indexes: %f sec\n", dtime);

  client_logger_message ("done setting up indexes\n");

  // dumpObjects ("test.obj.dat", catalog, Ncatalog);
  markObjects (catalog, Ncatalog);

  SAVEPLOT = FALSE;

  setExclusions (catalog, Ncatalog, TRUE);

  global_stats (catalog, Ncatalog, flatcorr);

  if (PLOTSTUFF) {
    plot_star_coords (catalog, Ncatalog);
    // plot_mosaic_fields (catalog);
  }

  // XXX : add this in the loop at various points
  // if (PLOTSTUFF) plot_scatter (catalog, Ncatalog, flatcorr); 

  /* determine fit values */
  client_logger_message ("starting the loops : %d \n", NLOOP);
  for (i = 0; i < NLOOP; i++) {

    // set the mean stellar mags given the measurements and the image calibrations
    setMrel  (catalog, Ncatalog, flatcorr);

    // share mean mags for objects at the boundary (number of unowned meas > 0)
    share_mean_mags (catalog, Ncatalog, regionHosts, i);
    client_logger_message ("shared mean mag data : loop %d \n", i);

    // load mean mags from other region hosts
    slurp_mean_mags (catalog, Ncatalog, regionHosts, i);
    client_logger_message ("slurped mean mag data : loop %d \n", i);

    // set the image (Mcal) and mosaic (Mmos) zero point offsets given the mean mags and measurements
    setMcal  (catalog, FALSE, flatcorr);
    setMmos  (catalog, FALSE, flatcorr);
    MARKTIME("-- set Mrel, Mcal, Mmos, Mgrid : %f sec\n", dtime);
    
    // share image mags for images with non-zero unowned detections
    share_image_mags (regionHosts, i);
    client_logger_message ("shared image data : loop %d \n", i);

    slurp_image_mags (regionHosts, i);
    client_logger_message ("slurped image data : loop %d \n", i);

    if ((i > 8) && (i % 8 == 2)) clean_measures (catalog, Ncatalog, FALSE, flatcorr); 
    if ((i > 8) && (i % 8 == 3)) clean_stars (catalog, Ncatalog);
    if ((i > 8) && (i % 8 == 5)) clean_mosaics ();
    if ((i > 8) && (i % 8 == 5)) clean_images ();

    if (i % 3 == 2) global_stats (catalog, Ncatalog, flatcorr);
    MARKTIME("-- finished loop %d: %f sec\n", i, dtime);
  }
  client_logger_message ("done with loops\n");

  // this is a checkpoint to make sure all hosts have finished the loop above
  char *loopsyncfile = make_filename (CATDIR, regionHosts->hosts[myHost].hostname, REGION_HOST_ID, "loop.sync");
  update_sync_file (loopsyncfile, 0);
  free (loopsyncfile);

  for (i = 0; i < regionHosts->Nhosts; i++) {
    if (regionHosts->hosts[i].hostID == REGION_HOST_ID) continue;
    char *loopsync = make_filename (CATDIR, regionHosts->hosts[i].hostname, regionHosts->hosts[i].hostID, "loop.sync");
    check_sync_file (loopsync, 0);
    free (loopsync);
  }    
  client_logger_message ("all hosts are done the loops\n");

  /* set Mcal & Mmos for bad images */
  setMcal  (catalog, TRUE, flatcorr);
  setMmos  (catalog, TRUE, flatcorr);
  MARKTIME("-- finalize Mcal values: %f sec\n", dtime);

  setMcalFinal (); // copy per-mosaic calibrations to the images

  share_image_mags (regionHosts, -1);
  client_logger_message ("done with parallel images\n");

  exit (0);
}
