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

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

#include "ppStack.h"
#include "ppStackLoop.h"

bool ppStackSetup(ppStackOptions *options, pmConfig *config)
{
    psAssert(options, "Require options");
    psAssert(config, "Require configuration");

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

    int num = psMetadataLookupS32(NULL, config->arguments, "INPUTS.NUM"); // Number of inputs
    options->num = num;

    bool mdok;                          // Status of MD lookup
    const char *statsName = psMetadataLookupStr(&mdok, config->arguments, "STATS"); // Filename for statistics
    if (statsName && strlen(statsName) > 0) {
        psString resolved = pmConfigConvertFilename(statsName, config, true, true); // Resolved filename
        options->statsFile = fopen(resolved, "w");
        if (!options->statsFile) {
            psError(PS_ERR_IO, true, "Unable to open statistics file %s for writing.\n", resolved);
            psFree(resolved);
            return false;
        }
        psFree(resolved);
        options->stats = psMetadataAlloc();
    }

    const char *tempDir = psMetadataLookupStr(NULL, recipe, "TEMP.DIR"); // Directory for temporary images
    if (!tempDir) {
        psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Unable to find TEMP.DIR in recipe");
        return false;
    }

    psString outputName = psStringCopy(psMetadataLookupStr(NULL, config->arguments,
                                                           "OUTPUT")); // Name for temporary files
    const char *tempName = basename(outputName);
    if (!tempName) {
        psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Unable to construct basename for temporary files.");
        psFree(outputName);
        return false;
    }

    const char *tempImage = psMetadataLookupStr(NULL, recipe, "TEMP.IMAGE"); // Suffix for temporary images
    const char *tempMask = psMetadataLookupStr(NULL, recipe, "TEMP.MASK"); // Suffix for temporary masks
    const char *tempVariance = psMetadataLookupStr(NULL, recipe, "TEMP.VARIANCE"); // Suffix for temp var maps
    if (!tempImage || !tempMask || !tempVariance) {
        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
                "Unable to find TEMP.IMAGE, TEMP.MASK and TEMP.VARIANCE in recipe");
        psFree(outputName);
        return false;
    }

    options->imageNames = psArrayAlloc(num);
    options->maskNames = psArrayAlloc(num);
    options->varianceNames = psArrayAlloc(num);
    for (int i = 0; i < num; i++) {
        psString imageName = NULL, maskName = NULL, varianceName = NULL; // Names for convolved images
        psStringAppend(&imageName, "%s/%s.%d.%s", tempDir, tempName, i, tempImage);
        psStringAppend(&maskName, "%s/%s.%d.%s", tempDir, tempName, i, tempMask);
        psStringAppend(&varianceName, "%s/%s.%d.%s", tempDir, tempName, i, tempVariance);
        psTrace("ppStack", 5, "Temporary files: %s %s %s\n", imageName, maskName, varianceName);
        options->imageNames->data[i] = imageName;
        options->maskNames->data[i] = maskName;
        options->varianceNames->data[i] = varianceName;
    }
    psFree(outputName);

    if (!pmConfigMaskSetBits(NULL, NULL, config)) {
        psError(PS_ERR_UNKNOWN, false, "Unable to determine mask value.");
        return false;
    }

    return true;
}
