#pragma once

#include "kpsinfo.h"

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

class TRTYIndexData;
class TBaseIndexComponent;

namespace NRTYServer {
    enum class EUrlIdSource;
}

class TBaseGeneratorManager: public NRTYServer::IRTYIndexManager, public IDocLenCalcer {
public:
    TBaseGeneratorManager(const TRTYServerConfig& config, const TString& componentName)
        : NRTYServer::IRTYIndexManager(componentName)
        , Config(config)
        , CachedRemovedDocNum(Max<ui32>())
        , LinkedCounter(0)
        , CachedDocNum(Max<ui32>())
    {
    }

    // NRTYServer::IRTYIndexManager
    virtual i64 GroupAttrValue(ui32 /*docid*/, const char* /*attrname*/, i64 /*defaultValue*/) const override {
        FAIL_LOG("Incorrect method usage case");
    }

    ui32 GetSearchableDocumentsCount() const override {
        return GetDocumentsCount() - GetDeletedDocumentsCount();
    }

    virtual ui32 GetDocumentsCount() const final;
    virtual ui32 GetDeletedDocumentsCount() const;
    virtual ui32 GetDocumentsCountImpl() const = 0;
    virtual bool GetDocumentsByKeyPrefix(ui64 kps, TVector<ui32>& docIds) const;

    virtual bool GetIndexInfo(NJson::TJsonValue&) const override {
        return false;
    }

    virtual ui32 RemoveDocids(const TVector<ui32>& docids) override final;
    virtual ui32 RemoveDocidsUnsafe(const TVector<ui32>& docids) override final;
    virtual bool UpdateDoc(ui32 /*docId*/, const TParsedDocument::TPtr /*doc*/) override;

    virtual bool DoClose() override {
        return true;
    }

    virtual bool DoOpen() override {
        CachedDocNum = Max<ui32>();
        CachedRemovedDocNum = Max<ui32>();
        return true;
    }

    virtual IKeysAndPositions* BuildYndex() const {
        return nullptr;
    }

    virtual ui32 GetDocLen(ui32 /*docid*/) const override {
        FAIL_LOG("Invalid usage");
    }

    virtual void LinkIndexData(IRemapperUrlDocId& remapper, TRTYIndexData* indexData) const;
    virtual void UnlinkIndexData() const;

    virtual bool IsLinked() const {
        return LinkedCounter;
    }

    virtual ui32 GetState() const {
        return 0;
    }

    virtual bool IsRemoved(ui32 docid) const = 0;
    virtual bool IsSearching() const = 0;

    virtual TCommonSearch* GetSearcher() const {
        return nullptr;
    }

    virtual const IUrlIdInfo* GetUrlIdInfo() const {
        return nullptr;
    }

    virtual NRTYServer::EUrlIdSource GetUrlIdSource() const;

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

public:
    const TRTYServerConfig& GetRTYConfig() const {
        return Config;
    }

protected:
    virtual ui32 DoRemoveDocids(const TVector<ui32>& docids) = 0;
    virtual ui32 DoRemoveDocidsUnsafe(const TVector<ui32>& docids) { // For special components locks
        return DoRemoveDocids(docids);
    }

    const TBaseIndexComponent* GetIndexComponent() const;

protected:
    const TRTYServerConfig& Config;

private:
    mutable ui32 CachedRemovedDocNum;

    mutable i32 LinkedCounter;
    mutable ui32 CachedDocNum;
    TMutex Mutex;
};

class TBaseIndexManager: public TBaseGeneratorManager {
public:
    TBaseIndexManager(const NRTYServer::TManagerConstructionContext& context, const TString& componentName);
    ~TBaseIndexManager();

    virtual ui32 GetSearchableDocumentsCount() const override;
    virtual ui32 GetDocumentsCountImpl() const override;
    virtual bool GetDocumentsByKeyPrefix(ui64 kps, TVector<ui32>& docIds) const override;
    virtual ui32 GetState() const override;

    virtual IKeysAndPositions* BuildYndex() const override;
    virtual i64 GroupAttrValue(ui32 docid, const char* attrname, i64 defaultValue) const override;

    virtual void LinkIndexData(IRemapperUrlDocId& remapper, TRTYIndexData* indexData) const override;
    virtual void UnlinkIndexData() const override;
    virtual bool IsLinked() const override;
    virtual void Prefetch() const override;

    virtual bool IsRemoved(ui32 docid) const override;
    virtual bool IsSearching() const override;
    virtual TCommonSearch* GetSearcher() const override;
    virtual THolder<NRTYServer::IDocSearchInfoIterator> GetDocSearchInfoIterator() const override;

    virtual bool DoOpen() override;
    virtual bool DoClose() override;

    virtual bool GetDocInfo(const ui32 docId, NJson::TJsonValue& result) const override;
    virtual bool GetIndexInfo(NJson::TJsonValue& result) const override;

public:
    const THolder<TFileMap>& GetFileIndexFrq() const {
        return FileIndexFrq;
    }

protected:
    virtual ui32 GetDeletedDocumentsCountFrq() const final;
    virtual ui32 GetDocumentsCountFrq() const final;

    virtual ui32 DoRemoveDocids(const TVector<ui32>& docids) override;

protected:
    const IArchiveData* GetArchiveData() const;
    const IKeysAndPositions* GetYndex() const;

protected:
    NRTYServer::IIndexOwner& Index;
    mutable THolder<TBaseSearch> BaseSearch;

    mutable TMaybe<ui64> CachedSentCount;
    mutable TMaybe<ui64> CachedWordCount;
    TKpsInfo KpsInfo;

    THolder<TFileMap> FileIndexFrq;

    const bool UseGlobalMapping;
    const bool IsReadOnly;
    const TPathName IndexDir;

    bool CheckFrqBordersForRemoveFlag;
    TMutex MutexFrqCounter;
    mutable ui32 CachedRemovedFrqDocNum;
};
