/** @file ppSubDefineOutput.c
 *
 *  @brief
 *
 *  @ingroup ppSub
 *
 *  @author IfA
 *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2009-02-18 00:31:20 $
 *  Copyright 2009 Institute for Astronomy, University of Hawaii
 */

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

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

#include "ppSub.h"

bool ppSubDefineOutput(const char *name, pmConfig *config)
{
    psAssert(name, "Require name");
    psAssert(config, "Require configuration");

    pmFPAview *view = ppSubViewReadout(); // View to readout
    pmCell *outCell = pmFPAfileThisCell(config->files, view, name); // Output cell
    pmFPA *outFPA = outCell->parent->parent; // Output FPA
    pmHDU *outHDU = outFPA->hdu;        // Output HDU
    if (!outHDU->header) {
        outHDU->header = psMetadataAlloc();
    }

    // The output readout may already be present if we read in the convolution kernel
    pmReadout *outRO = NULL;            // Output readout
    if (outCell->readouts && outCell->readouts->n > 0 && outCell->readouts->data[0]) {
        outRO = psMemIncrRefCounter(outCell->readouts->data[0]);
    } else {
        outRO = pmReadoutAlloc(outCell);
    }

    // Convolved input images
    pmReadout *inConv = pmFPAfileThisReadout(config->files, view, "PPSUB.INPUT.CONV"); // Input readout
    pmReadout *refConv = pmFPAfileThisReadout(config->files, view, "PPSUB.REF.CONV"); // Reference readout
    psFree(view);

    // Add kernel descrption to header.
    // We don't know which readout has the kernels because it depends on which PSF is larger
    bool mdok;                          // Status of MD lookup
    psMetadata *analysis = inConv->analysis; // Analysis metadata with kernel information
    pmHDU *hdu = pmHDUFromCell(inConv->parent);
    pmSubtractionKernels *kernels = psMetadataLookupPtr(&mdok, analysis, PM_SUBTRACTION_ANALYSIS_KERNEL); // Subtraction kernel

    if (!kernels) {
        hdu = pmHDUFromCell(refConv->parent);
        analysis = refConv->analysis;
        kernels = psMetadataLookupPtr(&mdok, analysis, PM_SUBTRACTION_ANALYSIS_KERNEL);
    }
    if (!kernels) {
        psError(PPSUB_ERR_UNKNOWN, true, "Unable to find SUBTRACTION.KERNEL");
        psFree(outRO);
        return false;
    }
    psAssert (hdu, "unable to find HDU");
    psMetadataAddStr(outHDU->header, PS_LIST_TAIL, "PPSUB.KERNEL", 0, "Subtraction kernel", kernels->description);
    outHDU->header = psMetadataCopy(outHDU->header, hdu->header);

    // Add additional data to the header
    pmFPAfile *refFile = psMetadataLookupPtr(NULL, config->files, "PPSUB.REF"); // Reference file
    pmFPAfile *inFile = psMetadataLookupPtr(NULL, config->files, "PPSUB.INPUT"); // Input file
    psMetadataAddStr(outHDU->header, PS_LIST_TAIL, "PPSUB.REFERENCE", 0,
                     "Subtraction reference", refFile->filename);
    psMetadataAddStr(outHDU->header, PS_LIST_TAIL, "PPSUB.INPUT", 0,
                     "Subtraction input", inFile->filename);
    ppSubVersionHeader(outHDU->header);


    outRO->analysis = psMetadataCopy(outRO->analysis, analysis);

    psFree(outRO);

    return true;
}
