# include "psphotInternal.h"

// replace the flux for sources which failed
bool psphotReplaceUnfitSources (psArray *sources, psImageMaskType maskVal) {

    pmSource *source;

    psTimerStart ("psphot.replace");

    for (int i = 0; i < sources->n; i++) {
      source = sources->data[i];

      // replace other sources?
      if (source->mode & PM_SOURCE_MODE_FAIL) goto replace;
      continue;

    replace:
        pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    }
    psLogMsg ("psphot.replace", 3, "replace unfitted models: %f sec (%ld objects)\n", psTimerMark ("psphot.replace"), sources->n);
    return true;
}

// for now, let's store the detections on the readout->analysis for each readout
bool psphotReplaceAllSources (pmConfig *config, const pmFPAview *view)
{
    bool status = true;

    // select the appropriate recipe information
    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
    psAssert (recipe, "missing recipe?");

    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");

    // loop over the available readouts
    for (int i = 0; i < num; i++) {
	if (!psphotReplaceAllSourcesReadout (config, view, "PSPHOT.INPUT", i, recipe)) {
            psError (PSPHOT_ERR_CONFIG, false, "failed to replace all sources for PSPHOT.INPUT entry %d", i);
	    return false;
	}
    }
    return true;
}

bool psphotReplaceAllSourcesReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) {

    bool status;
    pmSource *source;

    psTimerStart ("psphot.replace");

    // find the currently selected readout
    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
    psAssert (file, "missing file?");

    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
    psAssert (readout, "missing readout?");

    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
    psAssert (detections, "missing detections?");

    psArray *sources = detections->allSources;
    psAssert (sources, "missing sources?");

    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
    psAssert (maskVal, "missing mask value?");

    for (int i = 0; i < sources->n; i++) {
      source = sources->data[i];

      // replace other sources?
      if (!(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED)) continue;

      pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    }
    psLogMsg ("psphot.replace", PS_LOG_INFO, "replaced models for %ld objects: %f sec\n", sources->n, psTimerMark ("psphot.replace"));
    return true;
}

bool psphotRemoveAllSources (const psArray *sources, const psMetadata *recipe) {

    bool status;
    pmSource *source;

    psTimerStart ("psphot.replace");

    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
    assert (maskVal);

    for (int i = 0; i < sources->n; i++) {
      source = sources->data[i];

      // replace other sources?
      if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) continue;

      pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    }
    psLogMsg ("psphot.replace", PS_LOG_INFO, "replaced models for %ld objects: %f sec\n", sources->n, psTimerMark ("psphot.replace"));
    return true;
}
