# include "psastroInternal.h"

# define REQUIRED_RECIPE_VALUE(VALUE, NAME, TYPE)\
  VALUE = psMetadataLookup##TYPE (&status, recipe, NAME); \
  if (!status) { \
   psAbort ("Failed to find %s in recipe", NAME); }

bool psastroOneChipGrid (pmFPA *fpa, pmChip *chip, psArray *refstars, psArray *rawstars, psMetadata *recipe, psMetadata *updates) {

    bool status;
    pmAstromStats *stats = NULL;

    // do we need to get a rough initial match?
    REQUIRED_RECIPE_VALUE (bool gridSearch, "PSASTRO.GRID.SEARCH", Bool);
    if (!gridSearch) return true;

    // do we need to get a rough initial match?
    REQUIRED_RECIPE_VALUE (int maxNstar, "PSASTRO.GRID.NSTAR.MAX", S32);

    // generate the bright subset of maxNstar entries (note: rawstars is sorted by S/N)
    psArray *subset = psArrayAlloc (PS_MIN (maxNstar, rawstars->n));
    for (int i = 0; (i < maxNstar) && (i < rawstars->n); i++) {
	subset->data[i] = psMemIncrRefCounter (rawstars->data[i]);
    }

    // XXX set clump scale from recipe
    psArray *gridStars = psastroRemoveClumps (subset, 150);
    psFree (subset);

    psArray *refSubset = psastroRemoveClumps (refstars, 150);

    psLogMsg ("psastro", 3, "grid search using %ld raw vs %ld ref stars\n", gridStars->n, refSubset->n);

    // find initial offset / rotation / scale
    pmAstromStats *gridStats = pmAstromGridMatch (gridStars, refSubset, recipe);
    if (gridStats == NULL) {
	psLogMsg ("psastro", 3, "failed to find a grid match solution\n");
	psFree (gridStars);
	psFree (refSubset);
	return false;
    }
    psLogMsg ("psastro", 3, "basic grid search result - offset: %f,%f pixels, rotation: %f deg\n", gridStats->offset.x, gridStats->offset.y, DEG_RAD*gridStats->angle);

    // tweak the position by finding peak of matches stars
    stats = pmAstromGridTweak (gridStars, refSubset, recipe, gridStats);
    if (stats == NULL) {
	psLogMsg ("psastro", 3, "failed to measure tweaked grid solution\n");
	psFree (gridStats);
	psFree (gridStars);
	psFree (refSubset);
	return false;
    }
    psLogMsg ("psastro", 3, "tweak grid search result - offset: %f,%f pixels, rotation: %f deg\n", stats->offset.x, stats->offset.y, DEG_RAD*stats->angle);

    // adjust the chip.toFPA terms only
    pmAstromGridApply (chip->toFPA, stats);
    psastroUpdateChipToFPA (fpa, chip, rawstars, refstars);
    psFree (gridStats);
    psFree (gridStars);
    psFree (refSubset);
    psFree (stats);

    return true;
}
