# include "psastroInternal.h"
# define NONLIN_TOL 0.001 /* tolerance in pixels */

// apply the generic astrometry model to this image.  this assumes the WCS terms either do not
// exist or are invalid 
bool psastroUseModel (pmConfig *config, psMetadata *recipe) {

  bool status;

  bool useModel = psMetadataLookupBool (&status, config->arguments, "PSASTRO.USE.MODEL");
  if (!status) {
      useModel = psMetadataLookupBool (&status, recipe, "PSASTRO.USE.MODEL");
  }
  if (!useModel) return true;

  // identify reference astrometry table.  
  // if not defined, correction was not requested; skip step
  pmFPAfile *astrom = psMetadataLookupPtr (NULL, config->files, "PSASTRO.MODEL");
  if (!astrom) psAbort ("programming error: model was not supplied, though requested");

  // select the input data sources
  pmFPAfile *input = psMetadataLookupPtr (NULL, config->files, "PSASTRO.INPUT");
  if (!input) psAbort ("programming error: no input data");

  // make sure the astrometry model is loaded.  de-activate all files except PSASTRO.MODEL.
  pmFPAfileActivate (config->files, false, NULL);
  pmFPAfileActivate (config->files, true, "PSASTRO.MODEL");

  pmFPAview *view = pmFPAviewAlloc (0);

  // files associated with the science image
  if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
      psError (PS_ERR_IO, false, "Can't load the astrometry model file");
      return false;
  }

  // set the model using the RA, DEC, POSANGLE of the input image.
  pmAstromModelSetTP (astrom, input->fpa->concepts);

  // loop over all chips, replace input astrometry elements with those from astrom 
  pmChip *obsChip = NULL;
  while ((obsChip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
    psTrace ("psastro", 4, "Chip %d: %x %x\n", view->chip, obsChip->file_exists, obsChip->process);
    if (!obsChip->process || !obsChip->file_exists || !obsChip->data_exists) { continue; }

    // set the chip astrometry using the astrom file
    pmChip *refChip = pmFPAviewThisChip (view, astrom->fpa);

    psFree (obsChip->toFPA);
    psFree (obsChip->fromFPA);

    // supply astrometry from model 
    obsChip->toFPA   = psMemIncrRefCounter (refChip->toFPA);
    obsChip->fromFPA = psMemIncrRefCounter (refChip->fromFPA);

    // XXX if we want to write out the result, update the header here.  this needs to be
    // updated with the correct HDU selection.  obsChip->hdu may not exist.
    // pmAstromWriteBilevelChip (obsChip->hdu->header, obsChip, NONLIN_TOL);

    

  }

  psFree (input->fpa->toSky);
  psFree (input->fpa->toTPA);
  psFree (input->fpa->fromTPA);
  input->fpa->toSky   = psMemIncrRefCounter (astrom->fpa->toSky);
  input->fpa->toTPA   = psMemIncrRefCounter (astrom->fpa->toTPA);
  input->fpa->fromTPA = psMemIncrRefCounter (astrom->fpa->fromTPA);

  // XXX this is temporarily hardwired because of model error
  input->fpa->toSky->type = PS_PROJ_TAN;

  // psastroDumpCorners ("corners.useModel.dat", input->fpa);

  // updated with the correct HDU selection.  obsChip->hdu may not exist.
  // psMetadata *updates = psMetadataAlloc();
  // pmAstromWriteBilevelMosaic (updates, input->fpa, NONLIN_TOL);
  // psMetadataAddMetadata (input->fpa->analysis, PS_LIST_TAIL, "PSASTRO.HEADER",  PS_META_REPLACE, "psastro header stats", updates);
  // psFree (updates);

  psFree (view);
  return true;
}

