#pragma once

#include "factors_blocks.h"
#include "fictive_factors_info.h"

#include <kernel/factors_info/factors_info.h>

class TConfigPreprocessor;
class TFactorStorage;

namespace NRearr {
    class TDataRegistry;
}

namespace NRTYFeatures {
    class IFeature;
}

namespace NFactorSlices {
    class TFactorDomain;
}

namespace NRTYFactors {

    class TBaseDomain;
    class TRankModelHolder;
    class TFactorsSet;
    class TFactorSet;
    using TUserFunctionsList = TMap<TString, TString>;

    class TConfig: public IFactorsInfo, public TFictiveFactorsInfo {
    public:
        typedef THashMap<TString, TAtomicSharedPtr<TRankModelHolder> > TRankModels;
        typedef NRearr::TDataRegistry TFactorModels;

    public:
        TConfig(const char* filename, TStringBuf factorsModels = {}, TConfigPreprocessor *configPreprocessor = nullptr, i32 configVersion = -1);
        virtual ~TConfig();
        bool IsZoneUsed(const char* name) const;
        const TFactorsList& GetZoneFactors() const;
        const TFactorsList& StaticFactors() const;
        const TFactorsList& IgnoredFactors() const;
        const TFactorsList& DynamicFactors() const;
        const TFactorsList& UserFactors() const;
        const TFactorsList& RtyDynamicFactors() const;
        const TFactorsList& GetSuggestFactors() const;
        const TFactorsList& GetSuggestDictFactors() const;
        const TQSFactorsHashList& GetQuerySpecFactors() const;
        const TQSFactorsList::TPtr GetQuerySpecFactors(const TString& fName) const;
        const TCSFactorsHashList& GetCommonStatFactors() const;
        const TCSFactorsList::TPtr GetCommonStatFactors(const TString& fName) const;
        const TAnnFactorsHashList& GetAnnStreams() const;
        const TAnnFactorsList::TPtr GetAnnStreams(const TString& fName) const;
        const TGeoLayersList& GetGeoLayers() const;
        virtual size_t GetFactorCount() const;
        const TFactor* GetFactorByName(TStringBuf name) const;
        virtual const char* GetFactorName(size_t index) const;
        virtual const char* const* GetFactorNames() const;
        virtual bool GetFactorIndex(const char* name, size_t* index) const;
        virtual bool IsUnusedFactor(size_t index) const;
        const TFactor* GetFactorByFormulaIndex(size_t indexFormula, bool checkFactorExists = true) const;
        const TFactorsList* GetFactorsByRtyType(const TString& userInput) const;
        TVector<const TFactor*> ListFactorsByRange(size_t beginGlobalIndex, size_t endGlobalIndex) const;

        size_t GetFactorNum(const TString& name) const;
        size_t GetFactorGlobalNum(const char* name, size_t length = TString::npos) const;
        size_t GetFactorGlobalNum(TStringBuf name) const;
        bool IsDpFactor(TStringBuf name) const;
        TString GetKey() const;
        const TFactorSet* GetFactorSet(const TString& name) const;
        bool GetStreamIndex(const TString& name, size_t* index) const;
        const TUserFunctionsList& GetUserFunctions() const;
        const TRankModelHolder* GetRankModel(const TStringBuf name, const TStringBuf baseRankModel = {}, const TStringBuf polynom = {}) const;
        const TRankModelHolder* GetFastRankModel(const TStringBuf name, const TStringBuf polynom = {}) const;
        const TRankModelHolder* GetFilterModel(const TStringBuf name, const TStringBuf polynom = {}) const;
        const TRankModelHolder* GetFastFilterModel(const TStringBuf name, const TStringBuf polynom = {}) const;
        const TRankModelHolder* GetL3RankModel(const TStringBuf name) const;
        TRankModels GetRankModels() const;
        TFactorModels& GetFactorModels() const;
        bool HasRankModel(const TString& name) const;
        static void CopyFactors(const TFactorChunks& chunks, const TFactorStorage& src, TFactorStorage& dst);
        static void BuildChunks(TFactorChunks& chunks, const TMap<ui32, ui32>& srcToDest);
        ui32 GetFactorsCountByIndex(bool withMn = true) const;

        const TVector<TIntrusivePtr<NRTYFeatures::IFeature>>& GetRTYFeatures() const;

        NJson::TJsonValue GetUnusedFactorsReport();
        void GetAllFactorsIndexes(TSet<ui32>& factors) const;
        const NJson::TJsonValue& GetJsonConfig() const;
        const TString GetFileName() const;
        const TFsPath GetModelPath(const TString& value) const;
        bool IsInitialized() const;
        bool NeedDocsLens() const;
        bool IsStaticOnly(const TUsedFactors& factors) const;
        const TBaseDomain* GetBaseDomain() const;
        const NFactorSlices::TFactorDomain& GetFactorsDomain() const;
        i32 GetVersion() const;

    private:
        class TImpl;
        THolder<TImpl> Impl;
    };

};
