#include "apps.h"
#include "apps-list.gen.h"
#include <log4cplus/consoleappender.h>
#include <log4cplus/configurator.h>

namespace trygvis {
namespace apps {

using namespace std;

const po::options_description logging_options() {
    po::options_description desc;

    return desc;
}

void setup_logging(string app_name) {
    Appender *console = new ConsoleAppender(true, true);

    string pattern = string("%-5p ") /*"%6r "*/ + app_name + "/%-20c %m%n"; // add %M (function name)

    PatternLayout *layout = new PatternLayout(LOG4CPLUS_TEXT(pattern));
    console->setLayout(auto_ptr<Layout>(layout));

    Hierarchy &h = Logger::getDefaultHierarchy();
    h.getRoot().addAppender(SharedAppenderPtr(console));
}

template<typename App>
int launch_app(int argc, const char *argv[]) {
    App app;

    po::options_description all("Options");

    auto all_options = all.add_options();
    all_options("help", "This help message");
    app.add_options(all_options);

    all.add(logging_options());
    app.add_extra_options(all);

    po::variables_map vm;

    try {
        auto parsed = po::parse_command_line(argc, argv, all);
        po::store(parsed, vm);

        po::notify(vm);

        auto unrecognized = po::collect_unrecognized(parsed.options, po::include_positional);

        if (vm.count("help")) {
            cerr << all << "\n";
            return EXIT_FAILURE;
        }

        if (unrecognized.size()) {
            cerr << "Unrecognized option: " << unrecognized.at(0) << "\n";
            return EXIT_FAILURE;
        }

        setup_logging(app.app_name);

        Logger logger = Logger::getInstance(LOG4CPLUS_TEXT("main"));

        app_execution execution(all, vm, logger);

        return app.main(execution);
    } catch (po::required_option &e) {
        cerr << "Missing required option: " << e.get_option_name() << endl;
        cerr << all << endl;
        return EXIT_FAILURE;
    } catch (po::unknown_option &e) {
        cerr << e.what() << endl;
        return EXIT_FAILURE;
    }
}
}
}

using namespace std;
using namespace trygvis::apps;

int main(int argc, const char *argv[]) {
    if (argc == 0) {
        return EXIT_FAILURE;
    }

    string app_name;
    if (boost::ends_with(argv[0], "launcher")) {
        if (argc <= 1) {
            cerr << "Missing required argument: app" << endl;
            return EXIT_FAILURE;
        }

        app_name = argv[1];
        --argc;
        ++argv;
    } else {
        app_name = argv[0];
    }

    return launch(app_name, argc, argv);
}