#pragma once

#include "document_parser.h"

#include <util/system/mutex.h>
#include <library/cpp/mediator/messenger.h>

class TIndexComponentsStorage: public IMessageProcessor {
public:
    typedef TAtomicSharedPtr<NRTYServer::IIndexComponent> TComponentPtr;
    typedef TMap<TString, TComponentPtr> TComponents;
    typedef TVector<TComponentPtr> TComponentsOrdered;

private:
    TMutex Mutex;
    TComponents Components;
    TComponentsOrdered ComponentsForParse;
    TComponentsOrdered ComponentsForIndex;
    TComponentsOrdered ComponentsForNormalization;
    TComponentsOrdered ComponentsForOpen;
    THolder<TDocumentParser> DocumentParser;
    const TRTYServerConfig* Config = nullptr;
    void RegisterComponent(const TString& component);

public:
    TIndexComponentsStorage() {
    }

    static TIndexComponentsStorage& Instance() {
        return *Singleton<TIndexComponentsStorage>();
    }

    const TComponentsOrdered& GetComponentsForOpen() const;

    bool Process(IMessage* message) override;

    virtual TString Name() const override {
        return "TIndexComponentsStorage";
    }

    TString GetComponentsDescription() const;

    void CorrectSearchConfig(TSearchConfig& config, NRTYServer::TSearcherConfig::TSearchConfigType searchConfigType);
    bool CheckConfig() const;
    void ReleaseComponents();
    void ResetConfig(const TRTYServerConfig& config);
    const TDocumentParser& GetDocumentParser() const;
    virtual void CreateParsedEntities(TParsedDocument& parsedDocument) const;

    void Fill(NRTYServer::IIndexBuildersStorage* builders, const NRTYServer::TBuilderConstructionContext& buildersContext) const;
    void Fill(NRTYServer::IIndexManagersStorage* managers, const NRTYServer::TManagerConstructionContext& managersContext) const;
    bool Merge(const NRTYServer::TMergeContext& context) const;
    bool AllRight(const NRTYServer::TNormalizerContext& context) const;
    void CheckAndFix(const NRTYServer::TNormalizerContext& context) const;
    virtual THolder<TPruningConfig::ICalcer> CreatePruningCalcer(const NRTYServer::IIndexManagersStorage* managers) const;

    virtual bool CheckComponent(TStringBuf compName) const {
        return Components.find(compName) != Components.end();
    }

    virtual const NRTYServer::IIndexComponent* GetComponent(TStringBuf compName) const {
        TComponents::const_iterator i = Components.find(compName);
        VERIFY_WITH_LOG(i != Components.end(), "Incorrect component processing");
        return i->second.Get();
    }

    const TComponents& GetComponents() const {
        return Components;
    }
};
