#include <balancer/drlogger_nel/library/admin_server.h>
#include <balancer/drlogger_nel/library/configuration.h>
#include <balancer/drlogger_nel/library/logger.h>
#include <balancer/drlogger_nel/library/metric_storage.h>
#include <balancer/drlogger_nel/library/nel_server.h>
#include <balancer/drlogger_nel/library/stats_server.h>

#include <library/cpp/getopt/last_getopt.h>


static bool Launch(const TConfiguration& configuration);
static bool StartServer(THttpServer& server);


int main(int argc, const char *argv[]) {
    NLastGetopt::TOpts options = NLastGetopt::TOpts::Default();
    options.AddLongOption("config").RequiredArgument("PATH");
    NLastGetopt::TOptsParseResult parsedOptions(&options, argc, argv);

    TConfiguration configuration;
    if (!configuration.ReadFromYAMLFile(parsedOptions.Get<TString>("config"))) {
        return 1;
    }

    if (!Launch(configuration)) {
        return 1;
    }

    return 0;
}


static bool Launch(const TConfiguration& configuration) {
    TMetricStorage metricStorage(configuration);
    TLogger logger(configuration, 0);

    TNELServer nelServer(
        THttpServer::TOptions().SetPort(configuration.NELPort),
        configuration,
        metricStorage, 
        logger
    );
    TStatsServer statsServer(
        THttpServer::TOptions().SetPort(configuration.StatsPort),
        configuration,
        metricStorage
    );
    TAdminServer adminServer(
        THttpServer::TOptions().SetPort(configuration.AdminPort).SetHost("localhost"),
        [&statsServer, &nelServer] () { nelServer.Shutdown(); statsServer.Shutdown(); },
        [&logger] () { logger.ReopenLog(); }
    );

    if (!StartServer(nelServer) || 
        !StartServer(statsServer) ||
        !StartServer(adminServer))
    {
        return false;
    }

    nelServer.Wait();
    statsServer.Wait();
    adminServer.Wait();
    
    return true;
}

static bool StartServer(THttpServer& server) {
    server.Start();
    if (server.GetErrorCode() != 0) {
        Cerr << "Error when starting server: " << server.GetErrorCode() << ' ' << server.GetError() << Endl;
        return false;
    }
    return true;
}

