#include "quota_manager.h"

#include <balancer/kernel/rpslimiter/rpslimiter_instance.cfgproto.pb.h>

#include <library/cpp/proto_config/config.h>

namespace NSrvKernel::NRpsLimiter {
    THolder<TQuotaManager> CreateQuotaManager(NConfig::IConfig& cfg, TInstant now) {
        using namespace NProtoConfig;
        TRpslimiterInstanceCfg config;
        TVector<TString> hosts;
        ParseConfig(cfg, config,
            [&](const TKeyStack& keys, const TString& key, NConfig::IConfig::IValue*) {
                if (keys && std::holds_alternative<TField>(keys.front())) {
                    const auto parent = std::get<TField>(keys.front());
                    if (parent.Name == "module") {
                        return;
                    }
                    if (parent.Name == "remote") {
                        hosts.emplace_back(key);
                        return;
                    }
                    ythrow NConfig::TConfigParseError() << "unknown node " << key << " at " << keys;
                }
            }
        );

        TVector<TQuota> quotas;
        THashMap<TString, THolder<IModule>> remotes;
        for (auto&& h : hosts) {
            remotes.emplace(h, nullptr);
        }
        for (auto&& q : config.quotas()) {
            quotas.emplace_back(TQuota{
                .Name=q.first,
                .Start=now,
                .Window=TDuration::MilliSeconds(q.second.interval()),
                .Limit=q.second.quota(),
                .By={q.second.by().begin(), q.second.by().end()}
            });
        }
        return MakeHolder<TQuotaManager>(TQuotaManager{
            .Remote=std::move(remotes),
            .Storage=TQuotaState(config.remote().local_host_id(), now, hosts, quotas),
            .QuotaSyncPath=config.remote().sync_path(),
            .QuotaSyncInterval=config.remote().sync_interval(),
        });
    }
}
