#pragma once

#include "async_cache_i.h"

#include <balancer/kernel/dns/async_entry_i.h>
#include <balancer/kernel/dns/resolver_config.h>
#include <balancer/kernel/dns/stats_counters.h>

#include <util/generic/hash.h>


namespace NSrvKernel::NDns {

class IAsyncCoro;
class ICounters;

class TAsyncCache final : public IAsyncCache {
public:
    TAsyncCache(TContExecutor* e, const TResolverConfig& config,
                THolder<IAsyncCoro>&& resolver, THolder<IEntryBuilder>&& builder,
                ICounters& counters);
    TAsyncCache(const TAsyncCache&) = delete;
    TAsyncCache(TAsyncCache&&) = delete;
    TAsyncCache& operator=(const TAsyncCache&) = delete;
    TAsyncCache& operator=(TAsyncCache&&) = delete;

    TErrorOr<TSockAddrInfo> LookupOrResolve(const TResolveInfo& info, bool onlyCache, TInstant deadline) override;

private:
    bool Resolve(const TString& host, int family, TInstant deadline, IEntry& result) noexcept;
    void SetPort(TSockAddrInfo& result, uint16_t port) const noexcept;

private:
    TContExecutor* Executor_;
    const TResolverConfig& Config_; // not owned
    ICounters& Counters_;
    THashMap<TString, TEntryHolder> Storage_;
    THolder<IAsyncCoro> Resolver_;
    THolder<IEntryBuilder> EntryBuilder_;
};

}