#include "Application.h"
#include "Configuration.h"
#include "Core/Logger.h"
#include "Core/Singleton.h"
#include <boost/asio/signal_set.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>

int main(int argc, char const *argv[]) {
    using namespace Core;
    using namespace Older;

    boost::program_options::options_description description("Allowed options");
    // clang-format off
    description.add_options()
            ("help,h", "produce help message.")
            ("version,v", "print app version.")
            ("exit,e", "signal program to exit.")
            ("prefix", boost::program_options::value<std::string>(),"set prefix path (default: ${pwd})");
    // clang-format on
    boost::program_options::variables_map values;

    boost::log::initialize("logs/Older");

    try {
        boost::program_options::store(boost::program_options::parse_command_line(argc, argv, description), values);
        boost::program_options::notify(values);

        if (values.count("help")) {
            std::cout << description << std::endl;
            std::exit(0);
        } else if (values.count("version")) {
            std::cout << "version: " << APP_VERSION << std::endl;
            std::cout << "commit: " << GIT_COMMIT_ID << std::endl;
            std::cout << "compiled on: " << __DATE__ << " " << __TIME__ << std::endl;
            std::exit(0);
        } else if (values.count("exit")) {
            // Application::requetExit();
            std::exit(0);
        }
        LOG(info) << "version: " << APP_VERSION << std::endl;
        LOG(info) << "commit: " << GIT_COMMIT_ID << std::endl;
        LOG(info) << "compiled on: " << __DATE__ << " " << __TIME__ << std::endl;
        auto application = Singleton<Application>::construct();

        boost::asio::signal_set signals(application->ioContext(), SIGINT, SIGTERM, SIGHUP);
        signals.async_wait([&application](boost::system::error_code const &, int signal) {
            LOG(info) << "capture " << (signal == SIGINT ? "SIGINT" : "SIGTERM") << ",stop!";
            application->exit(5);
        });
        return application->exec();
    } catch (const std::exception &e) {
        LOG(error) << e.what();
        return -1;
    }
}
