#include "manager.h"
#include "core.h"

#include <saas/rtyserver/components/l2/l2_disk_manager.h>
#include <saas/rtyserver/components/l2/l2_memory_manager.h>

#include <saas/library/proto_helper/proto_helper.h>

#include <saas/library/cgi/cgi.h>

namespace NRTYServer {
    template <class TBase>
    ERTYSearchResult TPropManagerBase<TBase>::DoSearch(const TRTYSearchRequestContext& context, ICustomReportBuilder& reportBuilder, const IIndexController& controller) const {
        const auto& cgi = context.CgiParams();
        const TString& kps = cgi.Get("sgkps");

        TStackVec<ui64, 8> prefixes;
        if (!kps.empty()) {
            StringSplitter(kps).Split(',').ParseInto(&prefixes);
        } else {
            prefixes.push_back(0);
        }

        TVector<TDocSearchInfo> searchInfos;
        if (cgi.Has("saas_no_text_split")) {
            for (const auto& text: cgi.Range("text")) {
                for (ui64 prefix : prefixes) {
                    if (!text.empty()) {
                        searchInfos.emplace_back(text, prefix);
                    }
                }
            }
        } else {
            const TString& text = cgi.Get("text");
            for (const auto key : StringSplitter(text).Split(',').SkipEmpty()) {
                const TString keyStr = TString(key.Token());
                for (ui64 prefix : prefixes) {
                    searchInfos.emplace_back(keyStr, prefix);
                }
            }
        }

        const TGtaFilter gta(cgi);
        const auto* ddk = controller.GetDDKManager();

        for (const auto& searchInfo: searchInfos) {
            ui32 docId;
            if (!controller.RemapUrl2DocId(searchInfo, docId) || controller.IsRemoved(docId)) {
                continue;
            }
            NMetaProtocol::TDocument doc;
            doc.SetDocId(ToString(docId));
            doc.SetUrl(searchInfo.GetUrl());
            if (gta.Has("_Title")) {
                doc.MutableArchiveInfo()->SetTitle(searchInfo.GetUrl());
            }
            TSearchProtoHelper helper(doc);

            WalkDocumentProperties(docId, [&](TStringBuf name, TStringBuf value) {
                if (gta.NeedProperty(name)) {
                    helper.AddProperty(TString{name}, value);
                }
            });

            if (gta.NeedTimestamp()) {
                helper.AddProperty("_Timestamp", ddk->GetTimeLiveStart(docId));
            }
            if (gta.NeedVersion()) {
                helper.AddProperty("_Version", ddk->GetVersion(docId));
            }
            if (gta.NeedDeadline()) {
                helper.AddProperty("_Deadline", ddk->GetDeadline(docId));
            }

            reportBuilder.AddDocument(doc);
        }

        return SR_OK;
    }

    template <class TBase>
    const TPropConfig* TPropManagerBase<TBase>::GetConfig() const {
        return dynamic_cast<TPropCore&>(*this->GetCore()).GetConfig();
    }

    template class TPropManagerBase<TL2ComponentDiskManagerBase>;
    template class TPropManagerBase<TL2ComponentMemoryManagerBase>;
} // namespace NRTYServer
