#include <saas/rtyserver/common/search_area_modifier.h>
#include <search/meta/context.h>
#include <search/meta/mergedres.h>
#include <search/meta/rearrange/rearrange.h>
#include <search/web/core/rule.h>

#include <library/cpp/json/json_writer.h>


class TFacetGroupsOnlyRule : public IRearrangeRule {
    class TFacetGroupsOnlyContext : public IRearrangeRuleContext {
        const char KeyValSep_ = ':';
        const char NextPairSep_ = ';';
        bool Disabled = true;

        TString Trim(const TString& prop, const THashSet<TMsString>& categs) {
            NJson::TJsonValue propValJs;
            NJson::ReadJsonTree(prop, &propValJs);
            const char delim[] = {KeyValSep_, NextPairSep_, '\0'};
            TVector<TString> tmp, out;
            out.reserve(categs.size());
            StringSplitter(propValJs["result"].GetString()).SplitBySet(delim).AddTo(&tmp);
            if (tmp.size() < 2) {
                return "";
            }
            for (size_t i = 0; i <= tmp.size() / 2 - 1; ++i) {
                if (categs.contains(tmp[2 * i])) {
                    out.push_back(tmp[2 * i] + KeyValSep_ + tmp[2 * i+1]);
                }
            }
            propValJs["result"] = JoinStrings(out, TStringBuf(&NextPairSep_, 1));
            return NJson::WriteJson(propValJs, false);
        }
    public:
        void DoRearrangeAfterMerge(TRearrangeParams& rearrangeParams) override {
            if (Disabled) {
                return;
            }
            TMetaGrouping* g = rearrangeParams.Current.Grouping;
            THashSet<TMsString> categs;
            for (size_t ind = 0; ind < g->Size(); ind++) {
                categs.insert(g->GetMetaGroup(ind).GetCateg());
            }
            TSearcherProps& searcherProps = rearrangeParams.GetProperties();
            for (TSearcherProps::iterator prop = searcherProps.begin(); prop != searcherProps.end(); ++prop) {
                if (prop->first.StartsWith("rty_efacet_")) {
                    prop->second = Trim(prop->second, categs);
                }
            }
        }

        void DoAdjustClientParams(const TAdjustParams& /*params*/) override {
            Disabled = !LocalScheme()["Enabled"].IsTrue();
        }
    };
public:
    inline TFacetGroupsOnlyRule(const TString& /*config*/, const TSearchConfig& /*searchConfig*/)
    {
    }

    virtual ~TFacetGroupsOnlyRule() {
    }

    IRearrangeRuleContext* DoConstructContext() const override {
        return new TFacetGroupsOnlyContext;
    }
};

IRearrangeRule* CreateFacetGroupsOnlyRule(const TString& config, const TSearchConfig& searchConfig) {
    return new TFacetGroupsOnlyRule(config, searchConfig);
}

REGISTER_REARRANGE_RULE(FacetGroupsOnly, CreateFacetGroupsOnlyRule);
