#pragma once

#include "metrics.h"

#include <saas/rtyserver/config/indexer_config.h>
#include <saas/rtyserver/indexer_server/indexers_thread.h>
#include <saas/rtyserver/index_storage/index_storage.h>
#include <saas/rtyserver/modifier/document_modifier.h>
#include <saas/util/events_rate_calcer.h>
#include <saas/util/queue.h>

class TIndexerManager : public IIndexerManager {
protected:
    TRTYMtpQueue QueueCloseIndexers;
    TRTYMtpQueue QueueReopen;
    TRTYMtpQueue IndexHandler;
    TSynchronizedDocumentsQueue& DocumentsQueue;
    TAtomicSharedPtr<TIndexersList> Indexers;
    const ui32 IndexPoolSize;
    TIndexStorage& IndexStorage;
    TDocumentModifier& Deleter;
    TMutex Mutex;
    std::atomic<bool> IsActive;
    std::atomic<bool> RigidStop;
    const NRTYServer::TIndexerConfig& Config;
    const TString& ServiceName;
    TEventRate<> IndexRateMeterMemory;
    TEventRate<> IndexRateMeterDisk;
    ITransaction CloseTransaction;
    TAutoGlobal<TIndexerMetrics> IndexerMetrics;

protected:
    TIndexersThread* CreateIndexersThread(ui32 threadId);

public:
    TIndexerManager(const NRTYServer::TIndexerConfig& config, const TString& serviceName, TIndexStorage& indexStorage,
        TDocumentModifier& deleter, TSynchronizedDocumentsQueue& documentsQueue
    )
        : IIndexerManager()
        , QueueCloseIndexers("IdxMngrClose")
        , QueueReopen("IdxMngrReopen")
        , IndexHandler("IdxMngrIdxHndlr")
        , DocumentsQueue(documentsQueue)
        , IndexPoolSize(config.Threads)
        , IndexStorage(indexStorage)
        , Deleter(deleter)
        , IsActive(false)
        , RigidStop(false)
        , Config(config)
        , ServiceName(serviceName)
    {
        NOTICE_LOG << "Starting indexer manager" << Endl;
    }

    virtual ~TIndexerManager() {
        NOTICE_LOG << "Destroying indexer manager" << Endl;
        VERIFY_WITH_LOG(!IsActive, "Try to destruct working indexer manager");
    }

    void WaitCloseTasks() {
        TGuardTransaction gt(CloseTransaction);
    }

    bool GetIsActive() const {
        return IsActive;
    }

    TIndexerMetrics* GetIndexerMetrics() {
        return &IndexerMetrics;
    }

    const std::atomic<bool>* GetRigidStopSignal() const {
        return &RigidStop;
    }

    bool IsExistsClosing() const {
        return QueueCloseIndexers.Size();
    }

    void StartCloseIndexer(TAtomicSharedPtr<IIndexer> indexer, ITransaction* transaction);
    void StartReopenIndexer(TQueuedDocument replier, const TString& realmName);
    void ResetIndexers(bool force, ui32 shard, bool doLock, bool timeToLiveSec, bool memoryIndexer, const TString& realmName);
    IIndexer* GetDiskIndexer(const TString& indexDirName, const TString& tempDirName, int shard);

    virtual void OpenIndexers() override;
    virtual void CloseIndexers(bool rigidStop) override;
    virtual void ReopenIndexers();

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

    virtual bool Process(IMessage* message) override;
};

