#pragma once

#include <saas/rtyserver/indexer_core/abstract_model.h>

class TTrigramComponentConfig;
class IDocProcessor;

class TTrigramIndexManager: public NRTYServer::IIndexComponentManager {
private:
    struct TRegexpSeachInfo {
        TRegexpSeachInfo(const TStringBuf& regexpQuery, ui64 kps, bool ignoreCase);
        static std::pair<TString, TString> ParseRegexpQuery(const TStringBuf& regexpQuery); // returns {regexp, PropName}

        TDocSearchInfo SearchInfo;
        TString PropName;
        TVector<TDocSearchInfo> TrigramSubqueries;
    };

private:
    const TTrigramComponentConfig* Config;

public:
    using THash = TFixedSizeHashable<16>;

    class TIterator: public TAtomicRefCount<TIterator> {
    public:
        using TPtr = TIntrusivePtr<TIterator>;
        virtual ~TIterator() {
        }
        virtual bool Valid() const = 0;
        virtual void Next() = 0;
        virtual SUPERLONG GetPosition() const = 0;
    };

public:
    TTrigramIndexManager(const TRTYServerConfig& config);

    virtual ~TTrigramIndexManager() = default;

    virtual void InitInteractions(const NRTYServer::IIndexManagersStorage& /*storage*/) override {
    }

    virtual ui32 RemoveDocids(const TVector<ui32>& /*docids*/) override {
        return 0;
    }

    virtual ui32 GetDocumentsCount() const override {
        return Max<ui32>();
    }

    virtual bool UpdateDoc(ui32 /*docId*/, const TParsedDocument::TPtr /*doc*/) override {
        return true;
    }

    virtual bool GetDocInfo(const ui32 /* docId */, NJson::TJsonValue& /* result */) const override {
        return false;
    }

    ERTYSearchResult DoSearch(const TRTYSearchRequestContext& context, ICustomReportBuilder& reportBuilder, const IIndexController& controller) const override;

    bool SearchImpl(const TRTYSearchRequestContext& context, const IIndexController& controller, TVector<TDocIdCandidate>& docIds, TMessagesCollector& errors) const;

private:
    void ExtractRequestParams(const TCgiParameters& cgi, TVector<TRegexpSeachInfo>& searchInfos) const;

public:
    virtual bool GetData(const TString& keyName, const TString& value, const IDocProcessor* filter, TSet<SUPERLONG>& result) const = 0;
    virtual TIterator::TPtr CreateIterator(const TString& keyName, const TString& value, const IDocProcessor* filter) const = 0;

    inline bool GetData(const TString& keyName, const THash& keyHash, const IDocProcessor* filter, TSet<SUPERLONG>& result) const {
        return GetData(keyName, keyHash.Quote(), filter, result);
    }
    inline TIterator::TPtr CreateIterator(const TString& keyName, const THash& keyHash, const IDocProcessor* filter) const {
        return CreateIterator(keyName, keyHash.Quote(), filter);
    }
};
