# include "psphotInternal.h"

// replace the flux for sources which failed
bool psphotReplaceUnfitSources (psArray *sources, psMaskType 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);
        source->mode &= ~PM_SOURCE_MODE_SUBTRACTED;
    }
    psLogMsg ("psphot.replace", 3, "replace unfitted models: %f sec (%ld objects)\n", psTimerMark ("psphot.replace"), sources->n);
    return true;
}

bool psphotReplaceAllSources (psArray *sources, 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)
    psMaskType maskVal = psMetadataLookupU8(&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->mode & PM_SOURCE_MODE_SUBTRACTED)) continue;

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

bool psphotRemoveAllSources (psArray *sources, 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)
    psMaskType maskVal = psMetadataLookupU8(&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->mode & PM_SOURCE_MODE_SUBTRACTED) continue;

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

// add source, if the source has been subtracted; do not modify state
bool psphotAddWithTest (pmSource *source, bool useState, psMaskType maskVal) {

    // what is current state? (true : add; false : sub)
    bool state = !(source->mode & PM_SOURCE_MODE_SUBTRACTED);
    if (state && useState) return true;

    pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    return true;
}

// sub source, if the source has been added; do not modify state
bool psphotSubWithTest (pmSource *source, bool useState, psMaskType maskVal) {

    // what is current state? (true : sub; false : add)
    bool state = (source->mode & PM_SOURCE_MODE_SUBTRACTED);
    if (state && useState) return true;

    pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    return true;
}

// add or sub source to match recorded state: supply current state as true (add) or false (sub)
bool psphotSetState (pmSource *source, bool curState, psMaskType maskVal) {

    // what is desired state? (true : add; false : sub)
    bool newState = !(source->mode & PM_SOURCE_MODE_SUBTRACTED);
    if (curState == newState) return true;

    if (curState && !newState) {
        pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    }
    if (newState && !curState) {
        pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    }
    return true;
}
