#pragma once

#include <saas/library/daemon_base/config/daemon_config.h>
#include <saas/library/searchmap/searchmap.h>

#include <kernel/searchlog/searchlog.h>
#include <kernel/multipart_archive/config/config.h>

#include <library/cpp/logger/global/global.h>
#include <library/cpp/yconf/conf.h>

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

class TProxyConfig;

struct TDeferredMQConfig {
public:
    enum TType {DISABLED, LOCAL_MULTIPART};

    struct TMultipartConfig {
        TMultipartConfig();
        void Init(const TYandexConfig::Section& serverSection);
        TString ToString() const;

        TFsPath Directory;
        ui64 SizeInBytesLimit;
        NRTYArchive::TMultipartConfig ArchiveConfig;
    };

    struct TFailControlConfig {
        void Init(const TYandexConfig::Section& section);
        TString ToString() const;
        TDuration CheckPeriod = TDuration::Seconds(10);
        float MinRate = 1.f;
        float CriticalRatio = .5f;
    };

public:
    void Init(const TYandexConfig::Section& section);
    TString ToString() const;

    inline bool Enabled() const {
        return Type != DISABLED;
    }

    TMultipartConfig MultipartConfig;
    TFailControlConfig FailControlConfig;
    TType Type = DISABLED;
    TDuration DeferredMessagesTimeout = TDuration::Seconds(100);
    TDuration GarbageCollectionPeriod = TDuration::Seconds(60);
    TDuration RereadPeriod = TDuration::MilliSeconds(100);
    ui32 Workers = 4;
    ui32 QueueSizeLimit = Max<ui32>();
    ui64 SpaceLimitInBytes = Max<ui64>();
    bool AsyncMode = true;
};

class TDispatcherConfig {
private:
    const TCopyPtr<TSearchLog> LoadLog;
    const TProxyConfig& Owner;

    TDeferredMQConfig DeferredMQConfig;

    ui32 SenderThreads = 20;
    float MaxUnresolvedEndpoints = 0.2f;

public:
    TDispatcherConfig(const TProxyConfig& owner);

    void Init(const TYandexConfig::Section& section);

    ui32 GetSenderThreads() const {
        return SenderThreads;
    }

    float GetMaxUnresolvedEndpoints() const {
        return MaxUnresolvedEndpoints;
    }

    const TDeferredMQConfig& GetDeferredMQConfig() const {
        return DeferredMQConfig;
    }

    inline TSearchLog& GetLog() const {
        return *LoadLog;
    }

    const TProxyConfig& GetOwner() const {
        return Owner;
    }

    TString ToString() const;
    const NSearchMapParser::TSearchMap::TServiceMap& GetServiceMap() const;
};

