# include "relastro.h"

/* This function is essentially identical to relastro_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 relastro_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);
  }

  // assign image->parent and image->coords.mosaic 
  BuildChipMatch (image, Nimage);

  char mapfile[DVO_MAX_PATH];
  snprintf (mapfile, DVO_MAX_PATH, "%s/AstroMap.%d.fits", CATDIR, REGION_HOST_ID);
  AstromOffsetTable *table = AstromOffsetMapLoad (mapfile, VERBOSE);

  // assign images.coords.offsetMap -> table->map[i]
  if (table) {
    AstromOffsetTableMatchChips (image, Nimage, table);
  } else {
    table = AstromOffsetTableInit ();
  }
  put_astrom_table (table);
  client_logger_message ("loaded images on %s\n", regionHosts->hosts[myHost].hostname);

  // 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...
  initMosaics (image, Nimage);

  initImages (image, NULL, Nimage);

  SkyTable *sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, TRUE, SKY_DEPTH, VERBOSE);
  SkyTableSetFilenames (sky, CATDIR, "cpt");
  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 */
  char *syncfile = make_filename (CATDIR, regionHosts->hosts[myHost].hostname, REGION_HOST_ID, "loadcat.sync");
  catalog = load_catalogs (skylist, &Ncatalog, TRUE, 0, NULL, syncfile);
  MARKTIME("-- load catalog data, host %d: %f sec\n", REGION_HOST_ID, dtime);
  free (syncfile);
  
  client_logger_message ("loaded catalog data %s\n", regionHosts->hosts[myHost].hostname);

  // find ICRF QSOs for reference downstream (only if USE_ICRF_CORRECT)
  select_catalog_ICRF (catalog, Ncatalog);

  if (photcodesReset) {
    photcodesKeep  = photcodesReset;
    NphotcodesKeep = NphotcodesReset;
  }

  // generate tables go from catID,objID -> catSeq,objSeq
  indexCatalogs (catalog, Ncatalog);

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

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

  // set test points based on the starmap
  createStarMap (catalog, Ncatalog);

  client_logger_message ("set up image indexes on %s\n", regionHosts->hosts[myHost].hostname);

  markObjects (catalog, Ncatalog);

  SAVEPLOT = FALSE;

  client_logger_message ("starting the loops: %s\n", regionHosts->hosts[myHost].hostname);

  /* major modes */
  switch (FIT_TARGET) {
    case TARGET_SIMPLE:
      for (i = 0; i < NLOOP; i++) {
	UpdateObjects (catalog, Ncatalog, i);
	share_mean_pos (catalog, Ncatalog, regionHosts, i);
	slurp_mean_pos (catalog, Ncatalog, regionHosts, i);
	UpdateSimple (catalog, Ncatalog);
	share_image_pos (regionHosts, i);
	slurp_image_pos (catalog, Ncatalog, regionHosts, i);
      }
      break;

    case TARGET_CHIPS:
      if (RESET_IMAGES) {
	UpdateMeasures (catalog, Ncatalog);
	MARKTIME("reset measures, host %d: %f sec\n", REGION_HOST_ID, dtime);
	client_logger_message ("reset measures: %s\n", regionHosts->hosts[myHost].hostname);
      }
      for (i = 0; i < NLOOP; i++) {
	UpdateObjects (catalog, Ncatalog, (i > 0));
	MARKTIME("update objects loop %d, host %d: %f sec\n", i, REGION_HOST_ID, dtime);
	client_logger_message ("update objects loop %d: %s\n", i, regionHosts->hosts[myHost].hostname);
	if ((i > 1) || !USE_GALAXY_MODEL) {
	  // if GALAXY_MODEL is selected, we want to delay the frame correction until we have 
	  // applied the galaxy model a couple of times.
	  FrameCorrectionParallelSlave (catalog, Ncatalog, regionHosts, i); 
	  MARKTIME("frame correction loop %d, host %d: %f sec\n", i, REGION_HOST_ID, dtime);
	  client_logger_message ("frame correction loop %d: %s\n", i, regionHosts->hosts[myHost].hostname);
	}
	share_mean_pos (catalog, Ncatalog, regionHosts, i);
	slurp_mean_pos (catalog, Ncatalog, regionHosts, i);
	client_logger_message ("slurp mags loop %d: %s\n", i, regionHosts->hosts[myHost].hostname);

	UpdateChips (catalog, Ncatalog);
	MARKTIME("update chips loop %d, host %d: %f sec\n", i, REGION_HOST_ID, dtime);
	client_logger_message ("update chips loop %d: %s\n", i, regionHosts->hosts[myHost].hostname);

	share_image_pos (regionHosts, i);
	slurp_image_pos (catalog, Ncatalog, regionHosts, i);
	client_logger_message ("slurp image pos loop %d: %s\n", i, regionHosts->hosts[myHost].hostname);

	share_meas_pos (catalog, Ncatalog, regionHosts, i);
	slurp_meas_pos (catalog, Ncatalog, regionHosts, i);
	MARKTIME("done exchange loop %d, host %d: %f sec\n", i, REGION_HOST_ID, dtime);
	client_logger_message ("slurp meas loop %d: %s\n", i, regionHosts->hosts[myHost].hostname);
      }
      // create summary plots of the process
      // relastroVisualSummaryChips();
      break;

    case TARGET_MOSAICS:
      for (i = 0; i < NLOOP; i++) {
	UpdateObjects (catalog, Ncatalog, i);
	share_mean_pos (catalog, Ncatalog, regionHosts, i);
	slurp_mean_pos (catalog, Ncatalog, regionHosts, i);
	UpdateMosaic (catalog, Ncatalog);
	share_image_pos (regionHosts, i);
	slurp_image_pos (catalog, Ncatalog, regionHosts, i);
      }
      break;

    default:
      fprintf (stderr, "programming error at %s:%d", __FILE__, __LINE__);
      exit (2);
  }

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

  share_image_pos (regionHosts, -1);
  client_logger_message ("share image pos loop %d: %s\n", -1, regionHosts->hosts[myHost].hostname);

  exit (0);
}
