/** @file pswarp.c
 *
 *  @brief
 *
 *  @ingroup pswarp
 *
 *  @author IfA
 *  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2009-02-11 23:27:58 $
 *  Copyright 2009 Institute for Astronomy, University of Hawaii
 */

#include "pswarp.h"
#include "pswarpFileNames.h"

int main (int argc, char **argv)
{
    psTimerStart("pswarp");

    psLibInit(NULL);
    pmModelClassInit();
    psphotInit();

    const char *statsName = NULL;       // Filename for statistics
    psMetadata *stats = NULL;           // Container for statistics
    FILE *statsFile = NULL;             // File stream for statistics

    pmConfig *config = pswarpArguments(argc, argv);
    if (!config) {
        goto DIE;
    }

    pswarpVersionPrint();

    // load identify the data sources
    if (!pswarpParseCamera(config)) {
        goto DIE;
    }

    if (!pswarpOptions(config)) {
        goto DIE;
    }

    // load the skycell layout information
    if (!pswarpDefine(config)) {
        goto DIE;
    }

    // Open the statistics file
    bool mdok;                          ///< Status of MD lookup
    statsName = psMetadataLookupStr(&mdok, config->arguments, "STATS"); ///< Filename for statistics
    if (mdok && statsName && strlen(statsName) > 0) {
        psString resolved = pmConfigConvertFilename(statsName, config, true, true);
        statsFile = fopen(resolved, "w");
        if (!statsFile) {
            psError(PS_ERR_IO, true, "Unable to open statistics file %s for writing.\n", resolved);
            psFree(resolved);
            goto DIE;
        }
        psFree(resolved);
        stats = psMetadataAlloc();
        psMetadataAddS32(stats, PS_LIST_TAIL, "QUALITY", 0, "No problems", 0);
    }

    // load and warp
    if (!pswarpLoop(config, stats)) {
        goto DIE;
    }

    psLogMsg("pswarp", PS_LOG_INFO, "complete pswarp run: %f sec\n", psTimerMark("pswarp"));

DIE:
    {
        psExit exitValue = pswarpExitCode(PS_EXIT_SUCCESS); // Exit code

        // Ensure everything is written out, at every level
        pswarpFileActivation(config, detectorFiles, true);
        pswarpFileActivation(config, skycellFiles, true);
        pswarpFileActivation(config, photFiles, true);
        pswarpFileActivation(config, independentFiles, true);
        if (!pswarpIOChecksAfter(config)) {
            psError(psErrorCodeLast(), false, "Unable to write files.");
            exitValue = pswarpExitCode(exitValue);
            pmFPAfileFreeSetStrict(false);
        }

        // Write out summary statistics
        if (stats) {
            psMetadataAddF32(stats, PS_LIST_TAIL, "DT_WARP", 0, "Time for warp completion",
                             psTimerMark("pswarp"));

            const char *statsMDC = psMetadataConfigFormat(stats);
            if (!statsMDC) {
                psError(psErrorCodeLast(), false, "Unable to get statistics file.");
                exitValue = pswarpExitCode(exitValue);
            }
            psFree(stats);
            if (fprintf(statsFile, "%s", statsMDC) != strlen(statsMDC)) {
                psError(PSWARP_ERR_IO, true, "Unable to write statistics file.");
                exitValue = pswarpExitCode(exitValue);
            }
            psFree(statsMDC);
            if (fclose(statsFile) == EOF) {
                psError(PSWARP_ERR_IO, true, "Unable to close statistics file.");
                exitValue = pswarpExitCode(exitValue);
            }
            pmConfigRunFilenameAddWrite(config, "STATS", statsName);
        }

        // Dump configuration
        psString dump_file = psMetadataLookupStr(&mdok, config->arguments, "DUMP_CONFIG");
        if (dump_file) {
            if (!pmConfigDump(config, dump_file)) {
                psError(psErrorCodeLast(), false, "Unable to dump configuration");
                exitValue = pswarpExitCode(exitValue);
            }
        }

        psThreadPoolFinalize();
        psMemCheckCorruption(stderr, true);

        psFree(config);

        psTimerStop();
        pmVisualClose();
        pmModelClassCleanup();
        pmConceptsDone();
        pmConfigDone();
        psLibFinalize();

        exitValue = pswarpExitCode(exitValue);
        return exitValue;
    }
}
