#include "cookie_registry.h"
#include "cookie_type.h"

namespace NGdprCookie {

    TCookieRegistry::TCookieRegistry(TCookies cfg, bool detectConflicts) {
        NRegExp::TFsm names = NRegExp::TFsm::False();
        TVector<TCookie> cookies(1);
        cookies.back().set_type(ECookieType::Other);
        NPire::TFsm all = NPire::TFsm::MakeFalse();

        for (auto&& c : cfg.cookies()) {
            NPire::TFsm rawFsm;
            NRegExp::TFsm fsm{NRegExp::TFsm::False()};
            if (c.has_name_pattern()) {
                rawFsm = NPire::TLexer(c.name_pattern()).Parse();
                fsm = NRegExp::TFsm(NPire::TFsm(rawFsm).Compile<NRegExp::TFsm::TScanner>());
            } else if (c.has_name()) {
                rawFsm = NPire::TFsm().Append(c.name());
                fsm = NRegExp::TFsm(NPire::TFsm(rawFsm).Compile<NRegExp::TFsm::TScanner>());
            }
            if (detectConflicts) {
                auto intersect = (all & rawFsm);
                Y_ENSURE(intersect.DeadStates().contains(intersect.Initial()),
                    "Conflict in cookie name patterns after adding "
                    << (c.has_name_pattern() ? c.name_pattern() : c.name()).Quote());
                all |= rawFsm;
            }
            names = names | fsm;
            cookies.emplace_back(std::move(c));
        }

        Names_ = std::move(names);
        Cookies_ = std::move(cookies);
    }

    const TCookie& TCookieRegistry::Get(TStringBuf name) const noexcept {
        NRegExp::TMatcher matcher(Names_);
        matcher.Match(name);
        if (matcher.Final()) {
            return Cookies_[*matcher.MatchedRegexps().first];
        }
        return Cookies_[0];
    }
}
