#pragma once

#include <saas/library/daemon_base/module/module.h>
#include <saas/services/abstract/rty_indexation.h>
#include <library/cpp/mediator/messenger.h>
#include <saas/util/queue.h>

#include <kernel/multipart_archive/queue/queue_storage.h>

#include <library/cpp/threading/future/future.h>

namespace NRTYServer {
    const TString DeferredIndexationLogic = "DeferredIndexation";

    class ISwitcher;
    using ISwitcherPtr = TAtomicSharedPtr<ISwitcher>;
}

class TDeferredIndexationLogicConfig;

class TExternalLogicDeferredIndexation: public IExternalServiceLogic, public IMessageProcessor {
private:
    TMaybeFail<ui32> CurrentVersion;
    const TDeferredIndexationLogicConfig* Config = nullptr;
    TIndexerServer* Server = nullptr;
    bool Active = false;

    TMap<ui32, NRTYArchive::TStorage::TPtr> Queues;
    TRWMutex MutexQueue;
    TRTYMtpQueue Executor{"ExtrnDeferIdx"};

private:
    static TFactory::TRegistrator<TExternalLogicDeferredIndexation> Registrator;

public:
    void StartIndexation(TIndexerServer& server) override;
    void FinishIndexation() override;

    bool AddMessage(const NRTYServer::TMessage& message, IRTYReplierAbstract* /*replier*/) override;
    TString GetName() const override;

    NJson::TJsonValue ExternalControl(const TString& command) const override {
        if (command == "get_info") {
            NJson::TJsonValue report(NJson::JSON_MAP);
            report["size"] = Queues.size();
            report["in_progress"] = Executor.Size();
            return report;
        } else {
            return NJson::TJsonValue("Incorrect command");
        }

    }

    TString GetInfo(const TString& /*key*/) const override {
        return "NO_DATA";
    }

    // IMessageProcessor
    bool Process(IMessage* message_) override;
    TString Name() const override;

private:
    void SwitchVersion(ui32 version, NRTYServer::ISwitcherPtr switcher);
    NThreading::TFuture<void> ConsumeQueue(NRTYArchive::TStorage::TPtr queue);
};
