#include "obfuscation.h"

#include <util/string/ascii.h>
#include <util/string/strip.h>
#include <util/string/escape.h>
#include <util/string/cast.h>

namespace NSrvKernel {

    void ObfuscateSetCookieValue(TString& out, TStringBuf headerValue) noexcept {
        // We cannot use TSetCookie here because SetCookieMeta is a reference to validate TSetCookie logic
        const auto s = headerValue;
        TStringBuf cookie = StripString(s);

        if (!cookie) {
            return;
        }

        out.reserve(out.size() + cookie.size() + 3);

        const auto attrPos = std::min(cookie.find(';'), cookie.size());
        auto eqPos = std::min(cookie.find('='), attrPos);

        EscapeC(cookie.data(), eqPos, out);

        if (eqPos < attrPos) {
            eqPos += 1;
            out.append('=');
            char buf[32] = {};
            out.append(buf, IntToString<10>(attrPos - eqPos, buf, sizeof(buf)));
            out.append(':');
            for (auto i = eqPos; i < attrPos; ++i) {
                if (IsAsciiAlnum(cookie[i])) {
                    out.append('a');
                    ++i;
                    while (i < attrPos && IsAsciiAlnum(cookie[i])) {
                        ++i;
                    }
                }
                if (i < attrPos) {
                    EscapeC(cookie.data() + i, 1, out);
                }
            }
        }

        EscapeC(cookie.SubStr(attrPos), out);
    }

    TString ObfuscateSetCookieValue(TStringBuf headerValue) noexcept {
        TString res;
        ObfuscateSetCookieValue(res, headerValue);
        return res;
    }

}
