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

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

#define TIMERNAME "PPSTATS"

#include "ppStats.h"
#include "ppStatsSetupFromArgs.h"

int main(int argc, char *argv[])
{
    psExit status = PS_EXIT_SUCCESS;

    psLibInit(NULL);
    psTimerStart(TIMERNAME);

    // Parse the configuration and arguments
    pmConfig *config = pmConfigRead(&argc, argv, PPSTATS_RECIPE);
    if (!config) {
        psErrorStackPrint(stderr, "Unable to read configuration.\n");
        exit(PS_EXIT_CONFIG_ERROR);
    }

    // Get the options, open the files
    ppStatsData *data = ppStatsSetupFromArgs(&argc, argv, config);
    if (!data) {
        psErrorStackPrint(stderr, "Unable to parse command-line arguments.\n");
        exit(PS_EXIT_CONFIG_ERROR);
    }

    // Output filename is optional
    const char *outName = NULL;         // Output file name
    FILE *outFile = stdout;             // Output file
    if (argc == 2) {
        outName = argv[1];
        psString resolved = pmConfigConvertFilename(outName, config, true); // Resolved filename

        if (resolved && strlen(resolved) > 0) {
            outFile = fopen(resolved, "w");
            if (!outFile) {
                psLogMsg("ppStats", PS_LOG_ERROR, "Unable to open output file %s\n", resolved);
                psFree(resolved);
                // XXX this could be a system or config error, but not a data error
                status = PS_EXIT_CONFIG_ERROR;
                goto die;
            }
        } else {
            psErrorStackPrint(stderr, "Unable to open output file %s.\n", resolved);
            exit(PS_EXIT_CONFIG_ERROR);
        }
        psFree(resolved);
    }

    // Go through the FPA and do the hard work
    psMetadata *results = ppStatsLoop(&status, data, config);
    if (status != PS_EXIT_SUCCESS) {
        psErrorStackPrint(stderr, "Error in stats loop.\n");
        exit (status);
    }
    if (psListLength(results->list) == 0) {
        psErrorStackPrint(stderr, "No output.\n");
        exit (status);
    }

    if (data->fileLevel) {
        const char *level = pmFPALevelToName(pmFPAPHULevel(config->format)); // Level for file
        psMetadataAddStr(results, PS_LIST_HEAD, "FILE.LEVEL", 0, "File level", level);
    }

    // Format and print the output
    psString output = psMetadataConfigFormat(results);
    if (!output) {
        psErrorStackPrint(stderr, "Unable to generate configuration file with result.\n");
        psFree(results);
        exit(PS_EXIT_CONFIG_ERROR);
    }
    fprintf(outFile, "%s", output);
    psFree(output);

    // Clean up
    psFree(results);
    if (outName) {
        fclose(outFile);
    }

    // Common code for the death.
die:
    if (status) {
        psErrorStackPrint (stderr, "failure in %s", __func__);
    }
    psFree(data);
    psFree(config);
    pmConceptsDone();
    pmConfigDone();
    psLibFinalize();

    return status;
}
