#pragma once


#include "searchserverconfig.h"

#include <saas/searchproxy/proxy_meta/rearrange/abstract/rearrange.h>
#include <saas/searchproxy/proxy_meta/config.h>
#include <saas/searchproxy/logging/reqans_log.h>
#include <saas/rtyserver/factors/factors_config.h>

#include <saas/library/searchserver/http_status_config.h>

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

#include <util/generic/hash_set.h>
#include <util/generic/string.h>
#include <library/cpp/cgiparam/cgiparam.h>

using TSourcesConfig = TSearchServerConfig;

class TServiceConfig {
public:
    enum TConsistencyPolicy {
        cpNo /* "NO" */,
        cpAllSources /* "ALL" */,
        cpLocalDC /* "LOCAL" */
    };

    class TExtraCgi {
    public:
        enum class EPolicy {
            Add,
            AddIfEmpty,
            Calculate,
            Remove,
            Replace,
            CalculateAdditional,
            CalculateIfEmpty
        };
        struct TParameter {
            TString Name;
            TVector<TString> Values;
            EPolicy Policy;
        };
        using TParameters = TVector<TParameter>;

    public:
        const TParameters& Get() const {
            return Parameters;
        }

        void Add(const TString& name, const TString& value, EPolicy policy);
        void Clear();
        void Update(TExtraCgi&& patch);
        size_t Size() const;

    private:
        TParameters Parameters;
    };

    struct TTvmParams {
        enum EMode {
            Disabled,
            DryRun,
            Enabled
        };
        THashSet<ui32> AllowedSourceTvmIds;
        EMode Mode = Disabled;
        TVector<ui32> AllowedUserAbcGroups;
    };

private:
    TCopyPtr<TSearchServerConfig> MetaSearchConfig = MakeHolder<TSearchServerConfig>().Release();
    TCopyPtr<NProxyMeta::TConfig> ProxyMetaConfig;
    TCopyPtr<THttpStatusManagerConfig> HttpStatusManagerConfig = MakeHolder<THttpStatusManagerConfig>().Release();

    TExtraCgi ExtraCgi;
    TExtraCgi GlobalExtraCgi;
    TVector<TString> CgiCorrectorRules;

    TString Name;
    TString DefaultMetaSearch = "meta";
    TString EventLogTemplate;
    TString EventLogCompressionFormat;
    bool EventLogEnable;
    bool ReqAnsLogEnabled = true;
    bool Compression = false;
    bool GroupingByDC = true;
    bool SmartQueue = false;
    TConsistencyPolicy ConsistencyPolicy = cpNo;
    bool NormalizeReplicas = true; // default is different for full-text and key-value (SAAS-4313, SAAS-5470)

    TVector<TCustomRearrangeParams> CustomRearranges;
    TTvmParams Tvm;
    TAtomicSharedPtr<NRTYFactors::TConfig> Factors;
    NSearchProxy::NLogging::EFactorsAggregationStrategy FactorsLogAggregationStrategy {NSearchProxy::NLogging::EFactorsAggregationStrategy::Intersect};

private:
    static void ReadCgiParams(const TYandexConfig::TSectionsMap& sections, const TString& sectionName, TExtraCgi::EPolicy defaultPolicy, TExtraCgi& extraCgi);
    void ReadCustomRearranges(const TYandexConfig::TSectionsMap& sections, const TString& sectionName);
    static void ReadExtraCgi(const TYandexConfig::TSectionsMap& sections, const TString& sectionName, TExtraCgi& extraCgi);

public:
    void InitFromSection(TYandexConfig::Section* section, TConfigPatcher& preprocessor, bool forceMetaSearch = false);
    void SetMainThreadCount(ui32 count);
    void SetPort(ui16 port);
    void SetWorkDir(const TString& directory);

    TString GetEventLogFromTemplate() const;
    TString GetEventLogName() const;
    TString GetEventLogCompressionFormat() const;
    const TString& GetDefaultMetaSearch() const;
    bool IsEventLogEnabled() const;
    bool IsReqAnsLogEnabled() const;
    TSourcesConfig GetSourcesConfig(bool metaservice) const;

    TConsistencyPolicy GetConsistencyPolicy() const {
        return ConsistencyPolicy;
    }

    inline bool UseCompression() const {
        return Compression;
    }

    inline bool UseGroupingByDC() const {
        return GroupingByDC;
    }

    inline bool UseSmartQueue() const {
        return SmartQueue;
    }

    inline bool UseElasticQueues() const {
        return MetaSearchConfig ? MetaSearchConfig->ProtoCollection_.GetElasticQueues() : false;
    }

    bool GetNormalizeReplicas() const {
        return NormalizeReplicas;
    }

    const TExtraCgi& GetExtraCgi() const {
        return ExtraCgi;
    }

    const TExtraCgi& GetGlobalExtraCgi() const {
        return GlobalExtraCgi;
    }

    const TSearchServerConfig* GetMetaSearchConfig() const {
        return MetaSearchConfig.Get();
    }

    const NProxyMeta::TConfig* GetProxyMetaConfig() const {
        return ProxyMetaConfig.Get();
    }

    const TAtomicSharedPtr<NRTYFactors::TConfig> GetFactorsConfig() const {
        return Factors;
    }

    const THttpStatusManagerConfig& GetHttpStatusManagerConfig() const {
        CHECK_WITH_LOG(HttpStatusManagerConfig);
        return *HttpStatusManagerConfig;
    }

    const TVector<TCustomRearrangeParams>& GetCustomRearranges() const {
        return CustomRearranges;
    }

    const TVector<TString>& GetCgiCorrectorRules() const {
        return CgiCorrectorRules;
    }

    const TString& GetName() const {
        return Name;
    }

    const TTvmParams& GetTvmParams() const {
        return Tvm;
    }

    NSearchProxy::NLogging::EFactorsAggregationStrategy GetFactorsLogAggregationStrategy() const {
        return FactorsLogAggregationStrategy;
    }
};

