#pragma once

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

#include <search/meta/scatter/options/options.h>

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

#include <util/datetime/base.h>
#include <util/system/types.h>

namespace NSimpleMeta {

    class TConfig {
    private:
        TString RouteHashType;
        ui32 ThreadsSenders = 4;
        ui32 ThreadsStatusChecker = 1;
        ui32 MaxQueueSize = 0;
        ui32 MaxAttempts = 3;
        ui32 MaxKeysPerRequest = Max<ui32>();
        TDuration SendingTimeout = TDuration::MilliSeconds(20);
        TDuration ConnectTimeout = TDuration::MilliSeconds(20);
        TDuration GlobalTimeout = TDuration::MilliSeconds(300);
        float SourceTimeoutFactor = 1.0f;
        ui32 ParallelRequestCount = 1;
        TDuration TasksCheckInterval = TDuration::MilliSeconds(20);
        bool AllowDynamicWeights = false;
        bool LoggingEnabled = true;
        bool ReqAnsEnabled = false;
        bool EventLogEnabled = false;
        TString EventLogPath;
        TString EventLogPathFromTemplate;
        TString EventLogCompressionFormat;
        bool PrechargeSourceConnections = true;
        ui64 HedgedRequestTimeoutMs = 0;
        float HedgedRequestRateThreshold = 0.0f;
        float HedgedRequestRateSmooth = 0.995f;
        TString HedgedRequestTimeoutsRange;
        TSimpleSharedPtr<NScatter::TConnStatOptions> ConnStatOptions;

    public:
        static TConfig ParseFromString(const TString& configStr) {
            TConfig result;
            TAnyYandexConfig config;
            CHECK_WITH_LOG(config.ParseMemory(configStr.data()));
            result.InitFromSection(config.GetRootSection(), "");
            return result;
        }

    public:
        void InitFromSection(const TYandexConfig::Section* section, const TString& eventLogNameFromTemplate);

        const TString& GetRouteHashType() const {
            return RouteHashType;
        }

        const TString& GetEventLogPath() const {
            return !!EventLogPath ? EventLogPath : EventLogPathFromTemplate;
        }

        const TString& GetEventLogCompressionFormat() const {
            return EventLogCompressionFormat;
        }

        inline const TDuration& GetTasksCheckInterval() const {
            return TasksCheckInterval;
        }

        inline ui32 GetParallelRequestCount() const {
            return ParallelRequestCount;
        }

        inline TDuration GetSendingTimeout() const {
            return SendingTimeout;
        }

        inline TDuration GetConnectTimeout() const {
            return ConnectTimeout;
        }

        inline TDuration GetGlobalTimeout() const {
            return GlobalTimeout;
        }

        inline float GetSourceTimeoutFactor() const {
            return SourceTimeoutFactor;
        }

        inline ui32 GetMaxAttempts() const {
            return MaxAttempts;
        }

        inline ui32 GetMaxKeysPerRequest() const {
            return MaxKeysPerRequest;
        }

        inline ui32 GetThreadsSenders() const {
            return ThreadsSenders;
        }

        inline ui32 GetThreadsStatusChecker() const {
            return ThreadsStatusChecker;
        }

        inline ui32 GetMaxQueueSize() const {
            return MaxQueueSize;
        }

        inline bool GetAllowDynamicWeights() const {
            return AllowDynamicWeights;
        }

        inline bool GetLoggingEnabled() const {
            return LoggingEnabled;
        }

        inline bool GetEventLogEnabled() const noexcept {
            return EventLogEnabled;
        }

        inline bool GetReqAnsEnabled() const {
            return ReqAnsEnabled;
        }

        inline bool GetPrechargeSourceConnections() const noexcept {
            return PrechargeSourceConnections;
        }

        inline ui64 GetHedgedRequestTimeoutMs() const {
            return HedgedRequestTimeoutMs;
        }

        inline float GetHedgedRequestRateThreshold() const {
            return HedgedRequestRateThreshold;
        }

        inline float GetHedgedRequestRateSmooth() const {
            return HedgedRequestRateSmooth;
        }

        inline TString GetHedgedRequestTimeoutsRange() const {
            return HedgedRequestTimeoutsRange;
        }

        const NScatter::TConnStatOptions* GetConnStatOptions() const {
            return ConnStatOptions.Get();
        }
    };
}
