#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <pslib.h>
#include <psmodules.h>

#include "ppStack.h"

//#define TESTING

pmPSF *ppStackPSF(const pmConfig *config, int numCols, int numRows,
                  const psArray *psfs, const psVector *inputMask)
{
    bool mdok = false;

#ifndef TESTING
    // Get the recipe values
    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSTACK_RECIPE); // ppStack recipe
    psAssert(recipe, "We've thrown an error on this before.");

    int psfInstances = psMetadataLookupS32(NULL, recipe, "PSF.INSTANCES"); // Number of instances for PSF
    float psfRadius = psMetadataLookupF32(NULL, recipe, "PSF.RADIUS"); // Radius for PSF
    const char *psfModel = psMetadataLookupStr(NULL, recipe, "PSF.MODEL"); // Model for PSF
    int psfOrder = psMetadataLookupS32(NULL, recipe, "PSF.ORDER"); // Spatial order for PSF

    psString maskValStr = psMetadataLookupStr(&mdok, recipe, "MASK.VAL"); // Name of bits to mask going in
    if (!mdok || !maskValStr) {
        psError(PPSTACK_ERR_CONFIG, false, "Unable to find MASK.VAL in recipe");
        return false;
    }
    psImageMaskType maskVal = pmConfigMaskGet(maskValStr, config); // Bits to mask

    for (int i = 0; i < psfs->n; i++) {
        if (inputMask->data.U8[i]) {
            psFree(psfs->data[i]);
            psfs->data[i] = NULL;
        }
    }

    // Solve for the target PSF
    pmPSF *psf = pmPSFEnvelope(numCols, numRows, psfs, psfInstances, psfRadius, psfModel, psfOrder, psfOrder, maskVal);
    if (!psf) {
        psError(PPSTACK_ERR_PSF, false, "Unable to determine output PSF.");
        return NULL;
    }
#else
    // Dummy PSF
    pmPSF *psf = pmPSFBuildSimple("PS_MODEL_PS1_V1", 4.0, 4.0, 0.0, 1.0);
    if (!psf) {
        psError(PPSTACK_ERR_PSF, false, "Unable to build dummy PSF.");
        return NULL;
    }
#endif

    return psf;
}
