# include "psastroInternal.h"

bool psastroAnalysis (pmConfig *config) {

    bool status;
    int nStars;

    // measure the total elapsed time in psastroAnalysis.
    psTimerStart ("psastroAnalysis");

    // select the current recipe
    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSASTRO_RECIPE);
    if (!recipe) {
        psError(PSASTRO_ERR_CONFIG, true, "Can't find PSASTRO recipe");
        return false;
    }

    if (!psastroUseModel (config, recipe)) {
        psError (PSASTRO_ERR_UNKNOWN, false, "failed to set model astrometry\n");
        return false;
    }

    // interpret the available initial astrometric information
    // apply the initial guess
    if (!psastroAstromGuess (&nStars, config)) {
        psError (PSASTRO_ERR_UNKNOWN, false, "failed to determine initial astrometry guess\n");
        return false;
    }
    if (nStars == 0) {
        psLogMsg ("psastro", 2, "skipping astrometry analysis : no stars\n");
        return false;
    }

    // load the reference stars overlapping the data stars
    psArray *refs = psastroLoadRefstars(config);
    if (!refs) {
        psError (PSASTRO_ERR_UNKNOWN, false, "failed to load reference data\n");
        return false;
    }
    if (refs->n == 0) {
        psError(PSASTRO_ERR_REFSTARS, true, "no reference stars found");
        psFree(refs);
        return false;
    }

    if (!psastroChooseRefstars (config, refs)) {
        psError (PSASTRO_ERR_UNKNOWN, false, "failed to select reference data for chips\n");
        psFree(refs);
        return false;
    }

    // check the command-line arguments first
    bool chipastro = psMetadataLookupBool (&status, config->arguments, "PSASTRO.CHIP.MODE");
    if (!status) {
        chipastro = psMetadataLookupBool (&status, recipe, "PSASTRO.CHIP.MODE");
    }
    bool mosastro  = psMetadataLookupBool (&status, config->arguments, "PSASTRO.MOSAIC.MODE");
    if (!status) {
        mosastro  = psMetadataLookupBool (&status, recipe, "PSASTRO.MOSAIC.MODE");
    }
    if (!chipastro && !mosastro) {
        psLogMsg ("psastro", 3, "no astrometry mode selected, assuming chip astrometry\n");
        chipastro = true;
    }

    if (chipastro) {
        if (!psastroChipAstrom (config)) {
            psError (PSASTRO_ERR_UNKNOWN, false, "failed to perform single chip astrometry\n");
            psFree(refs);
            return false;
        }
    }
    if (mosastro) {
        if (!psastroMosaicAstrom (config)) {
            psError (PSASTRO_ERR_UNKNOWN, false, "failed to perform mosaic camera astrometry\n");
            psFree(refs);
            return false;
        }
    }

    psastroZeroPoint (config);

    psastroAstromGuessCheck (config);

    psastroMaskUpdates (config);

    // XXX how do we specify stack astrometry?
    // psastroStackAstrom (config, refs);

    psFree (refs);
    return true;
}
