#pragma once

#include <saas/protos/rtyserver.pb.h>
#include <saas/rtyserver/common/common_rty.h>
#include <saas/rtyserver/modifier/document_modifier.h>
#include <saas/rtyserver/indexer_core/guarded_document.h>
#include <saas/rtyserver/indexer_server/indexers_list.h>
#include <saas/rtyserver/indexer_server/indexers_thread.h>
#include <saas/library/daemon_base/metrics/metrics.h>
#include <library/cpp/object_factory/object_factory.h>
#include <util/system/mutex.h>
#include <util/system/guard.h>
#include <util/generic/ptr.h>

class IIndexationAction {
public:
    typedef TAtomicSharedPtr<IIndexationAction> TPtr;
    typedef NObjectFactory::TObjectFactory<IIndexationAction, NRTYServer::TMessage::TMessageType> TFactory;

public:
    virtual ~IIndexationAction() {};
    virtual void Execute(TQueuedDocument document, TIndexersThread& indexersThread) = 0;
    virtual ui32 GetShard() = 0;
    virtual TAtomicSharedPtr<TIndexersPack> GetIndexer() = 0;
};

class TCommonAction: public IIndexationAction {
protected:
    TQueuedDocument Document;
    ui32 Shard;
    TModifyResult ModifyResult;
    TIndexersThread* IndexersThread = nullptr;
    TIndexerMetrics* IndexerMetrics = nullptr;
    THolder<TReadGuard> Guard;
    TAtomicSharedPtr<TIndexersPack> Indexer;

public:
    virtual ui32 GetShard() override {
        return Shard;
    }

    virtual TAtomicSharedPtr<TIndexersPack> GetIndexer() override {
        return Indexer;
    }

    void DoComplete();
    void DoDuplicated();
    void DoRedundant();
    void DoIndexDocument();
    void DoOutdated();

    void LockIndexer();
    void UnLockIndexer();

    void Initialize(TQueuedDocument document, TIndexersThread& indexersThread);
    TString GetFirstIndexerName();

    virtual void Execute(TQueuedDocument document, TIndexersThread& indexersThread) override;
    virtual void DoPrepare() = 0;

private:
    void UpdateTimestampsOnDelete();
};
