#pragma once

#include "documents_queue.h"

#include <saas/rtyserver/index_storage/index_storage.h>
#include <saas/rtyserver/modifier/document_modifier.h>
#include <saas/library/daemon_base/metrics/servicemetrics.h>

#include <library/cpp/http/server/http.h>
#include <library/cpp/neh/rpc.h>
#include <library/cpp/neh/multi.h>

#include <saas/util/queue.h>
#include <saas/util/transaction.h>

#include <util/system/mutex.h>

class TIndexationStopGuard {
public:
    TIndexationStopGuard();
    ~TIndexationStopGuard();
};

class TIndexerServer: public NNeh::IOnRequest, public IMessageProcessor {
public:
    const NRTYServer::TIndexerConfig& Config;
    const TString& ServiceName;
    static ITransaction RequestsTransaction;
    static TMutex RequestMutex;

protected:
    TSynchronizedDocumentsQueue DocumentsQueue;
    TIndexStorage& IndexStorage;
    TAtomicSharedPtr<IIndexerManager> IndexerManager;
    TAutoPtr<IThreadFactory::IThread> ThreadManager;
    NNeh::IRequesterRef Requester;
    NNeh::TListenAddrs Addrs;
    TRTYMtpQueue Requests;
    TAutoGlobal<TServiceMetric> RepliesMetric;

public:
    TIndexerServer(TIndexStorage& indexStorage, TDocumentModifier& modifier, const NRTYServer::TIndexerConfig& config, const TString& serviceName);
    virtual ~TIndexerServer();

    void RegisterManager(IIndexerManager* manager);
    bool GetIsRunning() const;
    bool WaitReady() const;
    void Wait(bool rigidStop);

    // NNeh::IOnRequest
    virtual void OnRequest(NNeh::IRequestRef req) override;

    // IMessageProcessor
    virtual bool Process(IMessage* message) override;
    virtual TString Name() const override {
        return "IndexerServer";
    }

    TSynchronizedDocumentsQueue& GetDocumentsQueue();
    bool StartIndexerServer();
    void StopIndexerServer(bool rigidStop);
    void AddDocument(TQueuedDocument qDoc, const NRTYServer::TMessage& message, bool forcePut = false);
    bool IsIndexingPaused() const {
        return IndexingPaused;
    }

    TServiceMetric& GetRepliesMetric() {
        return RepliesMetric;
    }

    const TString& GetServiceName() {
        return ServiceName;
    }

private:
    void TerminateAllRequests(bool rigidStop);

private:
    TMutex PauseMutex;
    TThreadStatus Status;
    ITransaction TransactionServer;
    TAtomic ClientId;
    TAtomic DbgDocumentCounter;
    std::atomic<bool> IndexingPaused;
};

