#pragma once

#include "policies.h"

#include <saas/library/daemon_base/config/watchdog_opts.h>
#include <saas/rtyserver/common/common_messages.h>
#include <saas/rtyserver/config/fwd.h>
#include <saas/rtyserver/indexer_core/merger_interfaces.h>

#include <util/thread/factory.h>
#include <library/cpp/deprecated/atomic/atomic.h>
#include <util/system/condvar.h>
#include <util/system/mutex.h>
#include <util/system/event.h>

class TAnalyzerAgent: public IObjectInQueue, public IMessageProcessor, public IMergerTaskNotifier, public IWatchdogOptionSubscriber {
private:
    const TString Path;
    const ui32 MaxSegments;
    bool Disabled;
    IMerger& Merger;
    IMergerPolicyBehavior::TPtr MergerPolicy;
    IMergerLockPolicy::TPtr LockPolicy;
    NRTYServer::ERealm Realm;
    TString RealmConfigName;
    const NRTYServer::TMergerConfig::ESegmentsSort SegmentsSort;
    const TRTYServerConfig& Config;
    bool DoStopSignal = false;
    mutable TMutex MutexCounter;
    TCondVar CondVarWaiting;
    mutable TCondVar CondVarCounter;

    TVector<bool> ActiveTasks;
    TVector<ui32> ShardNewSegments;
    IWatchdogOptions::TSubscription Watchdog;

    ui32 TasksCount = 0;
    TMutex MutexIndexesProcessing;
private:
    bool RemoveEmptyIndexes();
    bool BuildTasksForDirectory();
    ui32 GetMaxDocs();
    void CheckPerKpsDocCountRestriction();
    void ModifyStateOnMergerTaskFinish(ui32 shard);

public:
    using TPtr = TAtomicSharedPtr<TAnalyzerAgent>;

public:
    TAnalyzerAgent(const TString& path, ui32 maxSegments, IMerger& merger, const TRTYServerConfig& config,
            IMergerPolicyBehavior::TPtr mergerPolicy, IMergerLockPolicy::TPtr lockPolicy, NRTYServer::ERealm realm, const TString& realmConfigName);

    ~TAnalyzerAgent();

    TString GetRealmName() {
        return RealmConfigName;
    }

    void WaitMergingFinished() const;

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

    ui32 GetTasksCount() const {
        return TasksCount;
    }

    bool HasActiveTaskForShard(ui32 shard) const {
        CHECK_WITH_LOG(ActiveTasks.size() > shard);
        return ActiveTasks[shard];
    }

    virtual void Process(void* threadSpecificResource) override;
    virtual bool Process(IMessage* message) override;

    void SubscribeToWatchdog(IWatchdogOptions& w);
    virtual void OnWatchdogOption(const TString& key, const TString& value) override;

    void Stop();

    virtual void OnMergerTaskFinish(const IMergerTask*) override;
    virtual void OnMergerTaskStart(const IMergerTask*) override;
    virtual void OnMergerTaskFailed() override;
};
