# include "relastro.h"

int relastro_images (SkyList *skylist) {

  int i, status, Ncatalog;
  Catalog *catalog;
  FITS_DB db;

  INITTIME;

  /* register database handle with shutdown procedure */
  set_db (&db);

  /* lock and load the image db table */
  status = dvo_image_lock (&db, ImageCat, 60.0, (UPDATE ? LCK_XCLD : LCK_SOFT));
  if (!status) Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
  if (db.dbstate == LCK_EMPTY) Shutdown ("ERROR: No images in catalog %s (1)", db.filename);
  if (!dvo_image_load (&db, VERBOSE, FALSE)) Shutdown ("can't read image catalog %s", db.filename);
  MARKTIME("load image data: %f sec\n", dtime);

  /* load regions and images based on specified sky patch (default depth) (require full overlap) */
  load_images (&db, skylist, TRUE);
  MARKTIME("load images: %f sec\n", dtime);

  /* load catalog data from region files : subselect high-quality measurements */

  // photcodesKeep is used here to allow measurements from the images being calibrated
  // note if -reset-to-photcode is selected, photocodesKeep is replaced with below with photcodesReset
  catalog = load_catalogs (skylist, &Ncatalog, TRUE, 0, NULL, NULL);
  MARKTIME("load catalog data: %f sec\n", dtime);

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

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

  if (Ncatalog == 0) {
    fprintf (stderr, "ERROR: no valid data for relastro, exiting\n");
    exit (2);
  }

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

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

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

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

  // XXX NOTE : for 2mass reset, photcodesKeep should now limit to 2MASS measurements

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

    case TARGET_CHIPS:
      if (RESET_IMAGES) UpdateMeasures (catalog, Ncatalog);
      for (i = 0; i < NLOOP; i++) {
	UpdateObjects (catalog, Ncatalog, (i > 0)); // calculate <R>,<D>; if (i > 0), apply Galaxy Motion Model (if desired)
	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.
	  FrameCorrectionSerial (catalog, Ncatalog);
	}
	UpdateChips (catalog, Ncatalog);   // measure.X,Y -> R,D, fit image.coords
	MARKTIME("update chips: %f sec\n", dtime);
      }
      // create summary plots of the process
      // relastroVisualSummaryChips();
      break;

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

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

  if (!UPDATE) exit (0);

  // free the image / measurement pointers
  freeImageBins (1);

  // XXX why do I do this exactly?
  reload_images (&db);
    
  if (PARALLEL) {
    // save the updated image parameters
    // need to also save the image map table...
    save_astrom_table ();
    dvo_image_update (&db, VERBOSE);
    dvo_image_unlock (&db); 
  }

  // iterate over catalogs to make detection coordinates consistant
  UpdateObjectOffsets (skylist, 0, NULL);

  if (!PARALLEL) {
    // save the updated image parameters
    save_astrom_table ();
    dvo_image_update (&db, VERBOSE);
    dvo_image_unlock (&db); 
  }

  exit (0);
}
