#include "indexer_proxy_specific.h"
#include "request_opts.h"

#include <saas/indexerproxy/context/action_reply.h>
#include <saas/protos/rtyserver.pb.h>

#include <util/generic/ptr.h>
#include <saas/indexerproxy/adapters/plugin_adapter.h>
#include <saas/indexerproxy/context/document.h>

TAdaptersManager::TAdaptersManager(const TProxyConfig& config, TProxyWatchdogSubsciber& wdSub, TDispatcher& dispatcher, NSaas::TAuthorization& authorizer)
    : Config(config)
    , WatchdogSubsciber(wdSub)
    , Dispatcher(dispatcher)
    , Authorizer(authorizer)
{
    for (TVector<TAdapterConfig>::const_iterator i = Config.GetAdaptersConfigVector().begin(), e = Config.GetAdaptersConfigVector().end(); i != e; ++i) {
        AdapterByName[i->Name] = new TAdapterHolder(*i);
    }
}

int TAdaptersManager::FillDocuments(ISenderTask& context) const {
    TSimpleSharedPtr<TAdapterHolder> adapter;
    TMap<TString, TSimpleSharedPtr<TAdapterHolder> >::const_iterator i = AdapterByName.find(context.GetContext().GetAdapterName());
    VERIFY_WITH_LOG(i != AdapterByName.end(), "Incorrect adapter name: %s", context.GetContext().GetAdapterName().data());
    CHECK_WITH_LOG(!context.GetContext().GetRequestOptions().IsTrace());
    adapter = i->second;
    adapter->ProcessMessage(context);
    return context.GetReply().GetHttpCode();
}

bool TAdaptersManager::Authorize(ISenderTask& context) const {
    auto i = Config.GetServiceMap().find(context.GetContext().GetServiceName());

    if (i == Config.GetServiceMap().end() || !i->second.RequireAuth)
        return true;

    bool authFailed = false;
    if (!!context.GetContext().GetDocument()) {
        const ui64 prefix = context.GetContext().GetDocument()->GetMessage().GetDocument().GetKeyPrefix();
        if (!Authorizer.CheckAuthorization(context.GetContext().GetRequestOptions().GetAuthCookie(), context.GetContext().GetServiceName(), prefix)) {
            authFailed = true;
        }
    }

    if (authFailed) {
        context.GetReply().SetInfo(401, "authorization failed");
        return false;
    } else {
        return true;
    }
}

bool TAdaptersManager::IsAcceptableByFilter(ISenderTask &context) const {
    bool result = false;
    if (!!context.GetContext().GetDocument()) {
        const NRTYServer::TMessage& message = context.GetContext().GetDocument()->GetMessage();
        result = !message.HasDocument() || WatchdogSubsciber.GetMinRank() <= message.GetDocument().GetFilterRank();
    }
    return result;
}


bool TAdaptersManager::ShouldDump(const TString& service) const {
    const TString& servicesToDump = Config.GetDumpServices();
    return servicesToDump.find(service) != TString::npos ||
           servicesToDump.find("all") != TString::npos;
}
