#include "common_search_request.h"

#include <search/unistat_logger/unistat_logger.h>
#include <search/engine/makepage.h>
#include <search/engine/search_output.h>
#include <search/request/data/reqdata.h>
#include <search/session/comsearch.h>
#include <search/output_context/stream_output_context.h>

#include <library/cpp/http/io/stream.h>
#include <library/cpp/http/misc/httpreqdata.h>
#include <library/cpp/logger/global/global.h>

TCommonSearchRequest::TCommonSearchRequest(const TCommonSearch* search, const TString& query,
    const TString& searcherHost, const ui16 searcherPort
)
    : Search(search)
    , Query(query)
    , SearcherHost(searcherHost)
    , SearcherPort(searcherPort)
{
    CHECK_WITH_LOG(Search);
}

// TODO: think about using kind of specific report which will return only
// documents ids
void TCommonSearchRequest::DoExecute() {
    Y_STATIC_THREAD(TAutoPtr<TSocket>) Socket;
    if (!Socket.Get()) {
        Socket = new TSocket(TNetworkAddress(SearcherHost, SearcherPort));
        Socket->SetKeepAlive(true);
    }
    TSearchRequestData requestData;
    requestData.SetSocket(*Socket.Get());
    requestData.Parse(Query.data());
    requestData.Scan();
    requestData.SetHost(SearcherHost, SearcherPort);

    TString result;
    {
        TSelfFlushLogFramePtr frame(new TSelfFlushLogFrame());
        TUnistatFramePtr statFrame(new TUnistatFrame);

        TStringOutput output(result);
        TSearchOutputStack outContext(&output);

        class TFakeIOCallbacks: public IIOCallbacks {
        public:
            bool ClientConnected() override {
                return true;
            }
            void EnableKeepAlive(bool) override {
            }
        } fakeIOCallbacks;

        TSearchCountHolder sch(Search);
        if (!Search->IsSearching()) {
            INFO_LOG << "Search is not active, exiting now" << Endl;
            return;
        }
        TMakePageContext context = {
            Search,
            &requestData,
            nullptr,
            {
                &outContext,
                &fakeIOCallbacks,
                frame.Get(),
                statFrame.Get()
            },
            TBlob(),
            static_cast<ui32>(RequestId),
            RT_Unknown,
            false,
            nullptr,
            GetRUsageCheckPoint(),
        };
        MakePage(context);
    }

    TStringInput input(result);
    THttpInput httpInput(&input);
    if (!Report.ParseFromArcadiaStream(&httpInput)) {
        ERROR_LOG << "Could not parse result" << Endl;
    }
}
