#pragma once

#include <balancer/kernel/coro/coroutine.h>
#include <balancer/kernel/dns/resolver_face.h>
#include <balancer/kernel/fs/shared_files.h>

#include <util/datetime/base.h>
#include <util/generic/string.h>

namespace NSrvKernel::NDns {

struct THelperConfig {
    THelperConfig() {
        Ttl += TDuration::Minutes(RandomNumber<ui64>() % 60); // to avoid simultaneous DNS cache expire on all balancers
        SwitchCheckTimeout += TDuration::Seconds(RandomNumber<ui64>() % 60); // to avoid simultaneous DNS resolve on all balancers
    }

    TString ResetCacheFile;
    TDuration Timeout = TDuration::Seconds(15); //!< time to resolve by DNS, do not confuse it with resolve_timeout, which sets deadline of returning result to request
    TDuration Ttl = TDuration::Minutes(60);
    TDuration ErrorTtl = TDuration::Seconds(2);
    bool AsyncResolve = true;
    bool ResolveCachedIpIfNotSet = true;
    TDuration ResolveOnStart = TDuration::Seconds(5);
    TString Ip;
    uint16_t Port = 0;
    TString SwitchFile = "./controls/async_dns"; // should be set always
    TDuration SwitchCheckTimeout = TDuration::Seconds(1);
};

class THelper {
public:
    NDns::IResolver& Resolver() noexcept {
        return *Resolver_;
    }

    void ResetResolver(THolder<NDns::IResolver> resolver) {
        Resolver_ = std::move(resolver);
    }

    TString CreateDnsResolver(TContExecutor* executor, TSharedFiles* sharedFiles,
                              const THelperConfig& config, NDns::TStatsCounters* counters, bool useAsync, TThreadedQueue* queue);

    void ResetDnsCache() noexcept;

private: // methods
    void CreateResetDnsCacheCoro(TContExecutor* executor, const TString& resetDnsCacheFile, TSharedFiles* sharedFiles);

private: // data
    THolder<NDns::IResolver> Resolver_ = MakeHolder<NDns::TSimpleResolver>();
    TCoroutine ResetDnsCacheCont_;
    TSharedFileExistsChecker ResetDnsCacheFileChecker_;
};

}
