# include "relphot.h"
int save_images_backup (FITS_DB *db);

int relphot_parallel_regions () {

  int status;
  FITS_DB db;

  INITTIME;

  // load the RegionTable (UserRegion should not be used at this level)
  RegionHostTable *regionHosts = RegionHostTableLoad (CATDIR, REGION_FILE);
  if (!regionHosts) {
    fprintf (stderr, "ERROR: problem with region host table\n");
    exit (2);
  }

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

  // register database handle with shutdown procedure
  set_db (&db);
  db.mode   = dvo_catalog_catmode (CATMODE);
  db.format = dvo_catalog_catformat (CATFORMAT);

  // lock and load the image db table
  status = dvo_image_lock (&db, ImageCat, 60.0, (UPDATE ? LCK_XCLD : LCK_SOFT));
  if (!status && UPDATE) {
    fprintf (stderr, "error\n");
    Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
  }

  if ((db.dbstate == LCK_EMPTY) || (db.dbstate == LCK_MISSING)) {
    // if the Image.dat file is missing, db.dbstate will have a value of either:
    // LCK_EMPTY (if UPDATE) or LCK_MISSING (if !UPDATE)
    Shutdown ("ERROR: database %s contains no image data", CATDIR);
  }

  // read data from Image.dat file
  if (!dvo_image_load (&db, VERBOSE, FALSE)) Shutdown ("can't read image catalog %s", db.filename);
  MARKTIME("-- load image data: %f sec\n", dtime);

  // save Images.dat using the copied structure
  if (UPDATE_CATFORMAT) {
    // ensure the db format is updated
    db.format = dvo_catalog_catformat (UPDATE_CATFORMAT);
  }

  /* assign the images to the different region hosts */
  if (!assign_images (&db, regionHosts)) Shutdown ("error assigning images to region hosts");
  MARKTIME("-- assign images: %f sec\n", dtime);

  /* launch processing on the parallel region hosts */
  if (!launch_region_hosts (regionHosts)) Shutdown ("error launching region hosts");
  MARKTIME ("finished relphot -parallel-regions: %f sec total\n", dtime);

  // retrieve updated image parameters from the remote hosts (also set Image.mcal)
  if (!slurp_image_mags (regionHosts, -1)) Shutdown ("error loading image updates");

  if (!UPDATE) { 
    dvo_image_unlock (&db); 
    MARKTIME ("finished relphot -parallel-regions: %f sec total\n", dtime);
    fprintf (stderr, "NOTE: UPDATE is OFF (results are not saved)\n");
    exit (0);
  }

  SkyTable *sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, TRUE, SKY_DEPTH, VERBOSE);
  SkyTableSetFilenames (sky, CATDIR, "cpt");
  SkyList *skylist = SkyListByBounds (sky, -1, regionHosts->Rmin, regionHosts->Rmax, regionHosts->Dmin, regionHosts->Dmax);

  // I have to save a copy because dvo_image_save and _unlock swap and free the data
  save_images_backup (&db);

  /* update catalogs (in parallel) */
  reload_catalogs (skylist, flatcorr, 0, NULL);

  // save the changes to the image parameters
  dvo_image_save (&db, VERBOSE);
  dvo_image_unlock (&db); 
  MARKTIME ("finished relphot -parallel-regions: %f sec total\n", dtime);

  exit (0);
}

int save_images_backup (FITS_DB *db) {

  FITS_DB dbX;
  char filename[1024];

  INITTIME;

  gfits_db_init (&dbX);
  dbX.lockstate = LCK_XCLD;
  dbX.timeout   = 60.0;
  dbX.mode      = db->mode;
  dbX.format    = db->format;

  snprintf (filename, 1024, "%s.bck", ImageCat);
  if (!gfits_db_lock (&dbX, filename)) {
    fprintf (stderr, "can't lock backup image image catalog\n");
    return (FALSE);
  }
    
  // copy Images.dat data (all or only the subset / vtable elements?)  I think I need to dump
  // the entire Image table, but with the updates in place I think this says: re-work the
  // ftable/vtable usage in this program to be more sensible...
  gfits_copy_header (&db->header,  &dbX.header);
  gfits_copy_matrix (&db->matrix,  &dbX.matrix);
  gfits_copy_header (&db->theader, &dbX.theader);
  gfits_copy_ftable (&db->ftable,  &dbX.ftable);

  dbX.ftable.header = &dbX.theader;

  dvo_image_save (&dbX, VERBOSE);
  dvo_image_unlock (&dbX); 
  MARKTIME("-- save Image.dat.bck: %f sec\n", dtime);

  return TRUE;
}
