#include "gdpr.h"

#include <balancer/kernel/cookie/gdpr/common/gdpr.h_serialized.h>
#include <balancer/kernel/cookie/utils/utils.h>

#include <util/string/builder.h>

namespace NGdprCookie {
    TMaybe<EGdpr> ParseGdprCookie(TStringBuf value) noexcept {
        if (value.size() != 1) {
            return Nothing();
        }
        EGdpr m = EGdpr::KeepAll;
        if (!TryFromString(value, m)) {
            return Nothing();
        }
        return m;
    }

    TStringBuf RenderGdprCookie(EGdpr mode) noexcept {
        return ToString(mode);
    }

    EGdpr MergeGdprCookie(EGdpr prev, EGdpr next) noexcept {
        if (prev == EGdpr::KeepAll || next == EGdpr::KeepAll) {
            return EGdpr::KeepAll;
        }
        // 0 > 3 > 2 > 1 to stay on the safe side. See METR-39259
        // The conflict situation should be extremely rare anyway.
        return *ParseGdprCookie(std::max(
            RenderGdprCookie(prev),
            RenderGdprCookie(next)
        ));
    }

    TMaybe<EIsGdpr> ParseIsGdprCookie(TStringBuf value) noexcept {
        if (value.size() != 1) {
            return Nothing();
        }
        EIsGdpr m = EIsGdpr::False;
        if (!TryFromString(value, m)) {
            return Nothing();
        }
        return m;
    }

    TStringBuf RenderIsGdprCookie(EIsGdpr v) noexcept {
        return ToString(v);
    }

    EIsGdpr MergeIsGdprCookie(EIsGdpr prev, EIsGdpr next) noexcept {
        // 0 > 1 to stay on the safe side.
        // The conflict situation should be extremely rare anyway.
        return *ParseIsGdprCookie(std::min(
            RenderIsGdprCookie(prev),
            RenderIsGdprCookie(next)
        ));
    }

    namespace {
        TStringBuf Print(EGdpr mode) noexcept {
            switch (mode) {
            case EGdpr::KeepAll: return "EGdpr::KeepAll"sv;
            case EGdpr::KeepTech: return "EGdpr::KeepTech"sv;
            case EGdpr::KeepTechAnalytic: return "EGdpr::KeepTechAnalytic"sv;
            case EGdpr::KeepTechOther: return "EGdpr::KeepTechOther"sv;
            }
        }
    }
}

using namespace NGdprCookie;

template <>
void Out<TXIpProperties>(IOutputStream& out, const TXIpProperties& c) {
    out << "{.IsGdpr="sv << c.IsGdpr;
    out << ",.IsVpn="sv << c.IsVpn;
    out << "}"sv;
}

template <>
void Out<TGdprCache>(IOutputStream& out, const TGdprCache& c) {
    using namespace NGdprCookie;
    out << "{.XIpProperties=TXIpProperties"sv;
    NSrvKernel::NCookie::PrintTo(out, c.XIpProperties);
    out << ",.XYandexEURequest="sv;
    NSrvKernel::NCookie::PrintTo(out, c.XYandexEURequest);
    out << "}"sv;
}

template <>
void Out<TGdpr::TVal>(IOutputStream& out, const TGdpr::TVal& gdpr) {
    out << "{.Mode="sv << Print(gdpr.Mode);
    out << ",.IsGdpr="sv << gdpr.IsGdpr;
    out << "}"sv;
}

template <>
void Out<TGdpr>(IOutputStream& out, const TGdpr& gdpr) {
    out << "{.Value="sv << gdpr.Value;
    out << ",.SafeValue="sv << gdpr.SafeValue;
    out << "}"sv;
}
