#include <search/meta/mergedres.h>

#include <search/web/core/rule.h>

#include <util/generic/algorithm.h>
#include <util/string/vector.h>
#include <util/stream/file.h>
#include <library/cpp/string_utils/url/url.h>
#include <util/string/split.h>

namespace NRTYRedirect {

    class TRTYPriorityDocsOnlyRearrangeRule: public IRearrangeRule {
        public:
            TRTYPriorityDocsOnlyRearrangeRule() {
            }

            virtual ~TRTYPriorityDocsOnlyRearrangeRule() {
            }

        private:
            IRearrangeRuleContext* DoConstructContext() const override;
            TString TemplUrl;
    };

    class TRTYPriorityDocsOnlyRearrangeContext: public IRearrangeRuleContext {
    public:
        TRTYPriorityDocsOnlyRearrangeContext() {
        }
        void DoRearrangeAfterFetch(TRearrangeParams& rearrangeParams) override;
    private:
    };

    IRearrangeRuleContext* TRTYPriorityDocsOnlyRearrangeRule::DoConstructContext() const {
        return new TRTYPriorityDocsOnlyRearrangeContext();
    }

    void TRTYPriorityDocsOnlyRearrangeContext::DoRearrangeAfterFetch(TRearrangeParams& rearrangeParams) {
        const TCgiParameters& cgi = rearrangeParams.GetRequestCgi();
        const TString& groupName = cgi.Get("pr_doc_name");
        if (!groupName || groupName == "no")
            return;
        TMetaGrouping* g = rearrangeParams.Current.Grouping;
        TSet<TMsString> marked;
        for (size_t ind = 0; ind < g->Size(); ind++) {
            TMetaGroup::TDocs& docs = g->GetMetaGroup(ind).MetaDocs;
            for (size_t docInd = 0; docInd < docs.size();) {
                const TMergedDoc::TDocAttributes& attrs = docs[docInd].Attributes();
                bool noChange = false;
                const TMergedDoc::TDocAttributes::TValues& idValues = attrs.GetValues("GrId" + groupName);
                const TMergedDoc::TDocAttributes::TValues& primValues = attrs.GetValues("Prim" + groupName);
                if (!idValues.empty()) {
                    if (!primValues.empty()) {
                        for (ui32 i = 0; i < idValues.size(); ++i) {
                            marked.insert(idValues[i]);
                        }
                    } else {
                        for (ui32 i = 0; i < idValues.size(); ++i) {
                            if (marked.find(idValues[i]) != marked.end()) {
                                docs.erase(docs.begin() + docInd);
                                noChange = true;
                                break;
                            }
                        }
                    }
                }

                if (!noChange)
                    docInd++;
            }
        }
    }

}

IRearrangeRule* CreateRTYPriorityDocsOnlyRule(const TString& /*params*/, const TSearchConfig&) {
    return new NRTYRedirect::TRTYPriorityDocsOnlyRearrangeRule();
}

REGISTER_REARRANGE_RULE(RTYPriorityDocsOnly, CreateRTYPriorityDocsOnlyRule);
