#pragma once

#include "search_source.h"

#include <saas/library/searchserver/replier.h>
#include <saas/rtyserver/config/fwd.h>
#include <saas/rtyserver/model/index.h>
#include <saas/rtyserver/search/common/replier.h>

class TSearchHandlers;
struct TSearchServerMetrics;

namespace NMemorySearch {
    class TResponseTimeGuard;
}

class ICustomSearchReplier
    : public ISearchReplier
    , public NRTYServer::TCommonReplierFeatures
{
public:
    ICustomSearchReplier(IReplyContext::TPtr client,
        const TSearchHandlers* handlers,
        TSearchServerMetrics* metrics,
        const NRTYServer::TSearcherConfig& searcherConfig
    )
        : ISearchReplier(client, nullptr)
        , SearchHandlers(handlers)
        , Metrics(metrics)
        , SearcherConfig(searcherConfig)
    {}

protected:
    virtual void OnQueueFailure() override;
    virtual IThreadPool* DoSelectHandler() override;
    virtual const TSearchHandlers* GetSearchHandlers() const final {
        return SearchHandlers;
    }

    THolder<NMemorySearch::TResponseTimeGuard> CreateTimeGuard() const;

    virtual TDuration GetDefaultTimeout() const override;
    virtual void OnRequestExpired(const int httpCode) override;

private:
    const TSearchHandlers* SearchHandlers;
    TSearchServerMetrics* Metrics;
    const NRTYServer::TSearcherConfig& SearcherConfig;
};

class ICustomSearchReplierWithConfig : public ICustomSearchReplier {
public:
    ICustomSearchReplierWithConfig(IReplyContext::TPtr client,
        const TSearchHandlers* handlers,
        TSearchServerMetrics* metrics,
        const TRTYServerConfig& config
    );

protected:
    const TRTYServerConfig& Config;
};

class TEmptySearchReplier: public ICustomSearchReplier {
public:
    TEmptySearchReplier(IReplyContext::TPtr context,
        TSearchServerMetrics* metrics,
        const NRTYServer::TSearcherConfig& config)
        : ICustomSearchReplier(context, nullptr, metrics, config)
    {
    }

    virtual IThreadPool* DoSelectHandler() override {
        return nullptr;
    }

protected:
    virtual void DoSearchAndReply() override;

};

class TCustomSearchReplier: public ICustomSearchReplierWithConfig {
public:
    TCustomSearchReplier(
        IReplyContext::TPtr client,
        const TSearchHandlers* handlers,
        IIndexController::TPtr customSearcher,
        TSearchServerMetrics* metrics,
        const TRTYServerConfig& config
    );

private:
    virtual void DoSearchAndReply() override;

private:
    IIndexController::TPtr CustomSearcher;
};

class TCustomMetaSearchReplier : public ICustomSearchReplierWithConfig {
public:
    TCustomMetaSearchReplier(
        IReplyContext::TPtr client,
        const TSearchHandlers* handlers,
        const TSearchersVector& customSearchers,
        TSearchServerMetrics* metrics,
        const TRTYServerConfig& config
    );
    TCustomMetaSearchReplier(
        IReplyContext::TPtr client,
        const TSearchersVector& customSearchers,
        TSearchServerMetrics* metrics,
        const TRTYServerConfig& config
    );

    virtual IThreadPool* DoSelectHandler() override {
        return ICustomSearchReplierWithConfig::DoSelectHandler();
    }

private:
    virtual void DoSearchAndReply() override;

private:
    TVector<IIndexController::TPtr> Controllers;
};
