#pragma once

#include "disk_indexer_ttl.h"
#include "disk_indexer_updater.h"
#include <saas/rtyserver/common/common_rty.h>
#include <saas/rtyserver/components/generator/builders_storage.h>
#include <saas/rtyserver/config/fwd.h>
#include <saas/rtyserver/indexer_core/guarded_document.h>
#include <saas/rtyserver/indexer_core/indexer_core.h>
#include <saas/rtyserver/index_storage/index_storage.h>
#include <saas/rtyserver/merger/merger_task.h>
#include <saas/rtyserver/model/component.h>
#include <kernel/docindexer/idstorage.h>
#include <kernel/keyinv/indexfile/memoryportion.h>
#include <util/folder/filelist.h>
#include <util/stream/direct_io.h>

#include <atomic>

class TDiskFAManager;

class TIndexer: public TIndexerCore {
    friend class TDiskIndexUpdater;
private:
    class TIndexerCloseCallback;
    TDiskIndexTtl Ttl;
    THolder<TDiskIndexUpdater> Updater;
    TIndexStorage& IndexStorage;
    TRTYIndexBuildersStorage Builders;
    TRWMutex RWFAMutex;
    THolder<TDiskFAManager> ReservedFAManager;
    TVector<ui32> RemapTableOnClose;
    bool RemapIsUsefulFlag;
    bool RestoreIsDeniedFlag;
    bool ManagersClosedFlag;
    bool IndexedSameUrls;
    TRWMutex MutexDocIdsByNextVersionSourceHash;
    TMap<ui32, TVector<ui32>> DocIdsByNextVersionSourceHash;
private:
    bool RemoveDocIdUnsafe(const ui32 docId);
    ui32 RemoveKps(ui64 kps) override;
    ui32 RemoveAll() override;

    void BuildReservedFA(const TString& path);
    void SignalStartRemapUsage();

protected:
    typedef THashMap<ui32, TDocSearchInfo> TDocIdToSearchInfo;
    typedef THashMap<TDocSearchInfo::THash, ui32> THashToDocId;
    typedef TSet<ui32> TRemovedDocs;

protected:
    virtual bool Process(IMessage* message) override;
    virtual ui32 GetDocumentsCount(bool keyWithDeleted = true) const override;
    virtual ui32 GetSearchableDocumentsCount() const override;
    virtual ui32 DoRemoveDocIdsUnsafe(const TVector<ui32>& docIds) override;
    virtual ui32 MarkDocIdsForDeleteUnsafe(const TVector<ui32>& docIds, ui32 /*marker*/) override;

protected:
    ITransaction TransactionModifyUrl;
    THashToDocId Hash2DocId;
    TDocIdToSearchInfo DocId2SearchInfo;
    TRemovedDocs RemovedDocs;
    TMutex MutexProcess;
    const IDDKManager* DDKManager;
protected:
    void KillEmptySegment();
    virtual void StartModification() override;
    virtual void FinishModification() override;
public:
    TIndexer(const TString& indexDirName, const TString& tempDirName, const TString& rootDir,
             const NRTYServer::TIndexerConfig& config,
             TIndexStorage& indexStorage, unsigned shard = 0);

    virtual ~TIndexer();

    virtual TString GetSearcherId() const override;
    virtual bool IsSearching() const override;

    virtual TCommonSearch* GetCommonSearch() const override;
    virtual bool HasSearcher() const override;

    virtual bool UpdateDoc(ui32 docId, const TParsedDocument::TPtr doc) override;
    virtual bool RestoreDoc(ui32 docId, TParsedDocument::TPtr& doc) override;

    virtual ERequestType RequestType(const TCgiParameters&) const override;

    virtual bool IsRemoved(const ui32 docId) const override;
    virtual bool RemapUrl2DocIdCandidate(const TDocSearchInfo& docInfo, TDocIdCandidate& docId) const override;
    virtual bool RemapUrl2DocId(const TDocSearchInfo& docInfo, ui32& docId) const override;

    virtual const NRTYServer::IIndexComponentManager* GetManager(const TString& componentName) const override {
        return Builders.GetManagers()->GetManager<NRTYServer::IIndexComponentManager>(componentName);
    }

    virtual TString Name() const override;

    TFinalIndexGuardedPtr BuildIndexFromPortions(TDeferredGuardTransaction& dg, const std::atomic<bool>* rigidStopSignal, NRTYServer::EExecutionContext execContext);
    virtual void CloseIndex(const std::atomic<bool>* rigidStopSignal, NRTYServer::EExecutionContext execContext) override;
    virtual bool Index(const TQueuedDocument& qDocument, int threadID) override;
    virtual bool UpdateTimestampsOnDelete(const TQueuedDocument& qDocument, int threadID) override;
    virtual bool IsFull() const override;
    virtual IIndexUpdater* GetUpdater() override;
    virtual const IDDKManager* GetDDKManager() const override;

    virtual EIndexType GetType() const override;
    virtual NRTYServer::ERealm GetRealm() const override;
    virtual TString GetRealmName() const override;

    bool Index(TParsedDocument& qDocument, int threadID = 0);

    virtual ui64 GetFilesSize() const override; //IIndexController
    virtual ui64 GetLockedMemorySize() const override; //IIndexController

};
