#include <balancer/drlogger/library/collector_server.h>
#include <balancer/drlogger/library/stats_collector.h>
#include <balancer/drlogger/library/logs_collector.h>
#include <balancer/drlogger/library/stats_server.h>
#include <balancer/drlogger/library/admin_server.h>

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

int main(int argc, const char *argv[]) {
    NLastGetopt::TOpts opts = NLastGetopt::TOpts::Default();
    opts.AddLongOption("port").RequiredArgument("PORT");
    opts.AddLongOption("stats-port").RequiredArgument("PORT");
    opts.AddLongOption("admin-port").RequiredArgument("PORT");
    opts.AddLongOption("access-log-file").RequiredArgument("PATH");
    opts.AddLongOption("geodata").OptionalArgument("PATH")
        .Help("If not set, per-ASN stats will not be available");
    opts.AddLongOption("log-queue-size").RequiredArgument("INT").DefaultValue(0)
        .Help("0 for no limit");
    NLastGetopt::TOptsParseResult parsedOpts(&opts, argc, argv);

    TStatsCollector statsCollector(
        parsedOpts.Has("geodata")
        ? std::optional<TString>(parsedOpts.Get("geodata"))
        : std::nullopt
    );
    TLogsCollector logsCollector(
        parsedOpts.Get<TString>("access-log-file"),
        parsedOpts.Get<size_t>("log-queue-size")
    );
    TCollectorServer srv(&statsCollector, &logsCollector,
        THttpServer::TOptions().SetPort(parsedOpts.Get<ui16>("port")));

    TStatsServer statsSrv(&statsCollector.YasmStats(),
        &statsCollector.SolomonStats(),
        THttpServer::TOptions().SetPort(parsedOpts.Get<ui16>("stats-port")));

    TAdminServer adminSrv(
        [&statsSrv, &srv]() { srv.Shutdown(); statsSrv.Shutdown(); },
        [&logsCollector]() { logsCollector.ReopenLog(); },
        THttpServer::TOptions().SetPort(parsedOpts.Get<ui16>("admin-port")).SetHost("localhost")
    );

    srv.Start();
    statsSrv.Start();
    adminSrv.Start();
    srv.Wait();
    statsSrv.Wait();
    adminSrv.Wait();
    return 0;
}
