#include <myapp/cmdargs/options.h>
#include <myapp/configuration/configproviderfactory.h>
#include <myapp/persistence/databasefactory.h>
#include <iostream>
#include "lib/persistence/sqlite3database.h"

namespace myapp {

using namespace cmdargs;
using namespace configuration;
using namespace persistence;

static void
maybe_show_help(options const& opt)
{
    if (!opt.showhelp) return;
    std::cout << "Allowed options:" << std::endl
              << "  -h\tHelp (list all command line options)" << std::endl
              << "  -C\tUse file as master configuration file instead of the default" << std::endl;
    std::exit(EXIT_SUCCESS);
}

static config
read_config(options const& opt)
{
    auto factory = config_provider_factory::create_yaml_config_provider();
    return factory->from_file(opt.config);
}

static std::shared_ptr<sqlite3_database> open_database(config const& cfg)
{
    auto connection_string = cfg.sqlite_persistence_connection_string;
    if (!connection_string.empty())
    {
        return std::dynamic_pointer_cast<sqlite3_database>(
            database_factory::create_sqlite3(std::move(connection_string)));
    }

    throw std::runtime_error("No sqlite3 connection string configured.");
}

} /* namespace myapp */

int
main(int argc, char* argv[])
{
    using namespace myapp;

    try {
        auto options = options::parse_arguments(argc, argv);
        maybe_show_help(options);

        if (options.config.empty())
            options.config = u8"/etc/myapp.yml";

        auto config = read_config(options);
        auto sqlite3 = open_database(config);
        
        std::cout << sqlite3->dump() << std::endl;
    }
	catch (configuration::error const& e)
	{
		std::cerr << "Configuration error: " << e.what() << std::endl;
		return EXIT_FAILURE;
	}
    catch (std::exception const& e)
    {
        std::cerr << e.what() << std::endl;
		return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
