# include "psphotInternal.h"

bool psphotMagnitudes(pmConfig *config, const pmFPAview *view, psArray *sources, psMetadata *recipe, pmPSF *psf) {

    bool status = false;
    int Nap = 0;

    psTimerStart ("psphot.mags");

    pmReadout *backModel = psphotSelectBackground (config, view);
    pmReadout *backStdev = psphotSelectBackgroundStdev (config, view);

    // XXX require that we have a background model, or
    // allow it to be missing, setting local sky to 0.0?
    PS_ASSERT (backModel, false);
    PS_ASSERT (backStdev, false);

    // bit-masks to test for good/bad pixels
    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT");
    assert (maskVal);

    // bit-mask to mark pixels not used in analysis
    psMaskType markVal = psMetadataLookupU8(&status, recipe, "MARK.PSPHOT");
    assert (markVal);

    // maskVal is used to test for rejected pixels, and must include markVal
    maskVal |= markVal;

    pmSourceMagnitudesInit (recipe);

    // the binning details are saved on the analysis metadata
    psImageBinning *binning = psMetadataLookupPtr(&status, recipe, "PSPHOT.BACKGROUND.BINNING");
    PS_ASSERT (status, false);

    bool IGNORE_GROWTH = psMetadataLookupBool (&status, recipe, "IGNORE_GROWTH");
    bool INTERPOLATE_AP = psMetadataLookupBool (&status, recipe, "INTERPOLATE_AP");

    pmSourcePhotometryMode photMode = PM_SOURCE_PHOT_APCORR | PM_SOURCE_PHOT_WEIGHT;
    if (!IGNORE_GROWTH) photMode |= PM_SOURCE_PHOT_GROWTH;
    if (INTERPOLATE_AP) photMode |= PM_SOURCE_PHOT_INTERP;

    for (int i = 0; i < sources->n; i++) {
        pmSource *source = (pmSource *) sources->data[i];
        status = pmSourceMagnitudes (source, psf, photMode, maskVal);
        if (status && isfinite(source->apMag)) Nap ++;

        source->sky = psImageUnbinPixel(source->peak->x, source->peak->y, backModel->image, binning);
        if (isnan(source->sky) && false) {
          psError(PSPHOT_ERR_SKY, false, "Setting pmSource.sky");
          psErrorStackPrint(NULL, " ");
          psErrorClear();
        }

        source->skyErr = psImageUnbinPixel(source->peak->x, source->peak->y, backStdev->image, binning);
        if (isnan(source->skyErr) && false) {
          psError(PSPHOT_ERR_SKY, false, "Setting pmSource.sky");
          psErrorStackPrint(NULL, " ");
          psErrorClear();
        }
    }

    psLogMsg ("psphot.magnitudes", PS_LOG_DETAIL, "measure magnitudes : %f sec for %ld objects (%d with apertures)\n", psTimerMark ("psphot.mags"), sources->n, Nap);
    return true;
}

// XXX add in a measurement of the bright and faint completeness values
// XXX push these into the recipe
