#include "sequentialsearch.h"

#include <search/session/rcontext.h>

namespace {
    template <class T>
    inline T* Yasserted(T* object) {
        Y_ASSERT(object);
        return object;
    }
}

TMetaSearchContext* TSequentialSearchContext::CreateSeqContext() const {
    auto ctx = CheckedCast<TMetaSearchContext*>(Yasserted(ReqContext)->CreateContext());
    ctx->PageCallbackType = PageCallbackType;
    ctx->CgiParam = OriginalCgiParameters;

    ctx->LogEvent(NEvClass::TCreateSlaveContext(SearchCount, ctx->CgiParam.Get(TStringBuf("reqid")), "sequential_context"));

    return ctx;
}

int TSequentialSearchContext::LoadOrSearch() {
    int res = YXOK;

    Y_ASSERT(CurrentContext);
    OriginalCgiParameters = CurrentContext->CgiParam;

    for (; SearchCount < MaxSearchCount; ++SearchCount) {
        PrepareContext(*CurrentContext);

        res = Yasserted(CurrentContext)->TMetaSearchContext::LoadOrSearch();

        if (!ShouldContinue(res, *CurrentContext)) {
            break;
        }

        SeqContexts.push_back(CreateSeqContext());
        CurrentContext->ResumeWaiters();
        CurrentContext = SeqContexts.back();
    }

    return res;
}

IReqEnv* TSequentialSearchContext::ReqEnv() {
    return Yasserted(CurrentContext)->TMetaSearchContext::ReqEnv();
}

ICluster* TSequentialSearchContext::Cluster() {
    return Yasserted(CurrentContext)->TMetaSearchContext::Cluster();
}

IReqResults* TSequentialSearchContext::ReqResults() {
    return Yasserted(CurrentContext)->TMetaSearchContext::ReqResults();
}

IReqParams* TSequentialSearchContext::ReqParams() {
    return Yasserted(CurrentContext)->TMetaSearchContext::ReqParams();
}

const IIndexProperty* TSequentialSearchContext::IndexProperty() {
    return Yasserted(CurrentContext)->TMetaSearchContext::IndexProperty();
}

TSequentialSearchContext::~TSequentialSearchContext() {
    for (auto&& sc : SeqContexts) {
        sc->Owner.DestroyContext(sc);
    }
}

TSequentialSearchContext::TSequentialSearchContext(const TMetaSearch& owner)
    : TMetaSearchContext(owner)
    , CurrentContext(this)
    , SearchCount(0)
    , MaxSearchCount(3)
{
}
