#include "barnavig.h"

#include "hasher.h"
#include "barnavig_parser.h"

#include <balancer/kernel/custom_io/chunkio.h>
#include <balancer/kernel/http/parser/http.h>
#include <balancer/kernel/module/iface.h>

#include <util/generic/strbuf.h>
#include <util/random/random.h>

using namespace NSrvKernel;
using namespace NModHasher;

HASHER(barnavig) {
    THasher(const TModuleParams&) {}

    TErrorOr<ui64> CalcHash(const TConnDescr& descr) const noexcept override {
        TString url;

        if (descr.Request->RequestLine().Method == EMethod::POST) {
            TChunkList tmp;
            // TODO (velavokr): WHUT? What about limiting the buffer? BALANCER-1596
            while (1) {
                Y_PROPAGATE_ERROR(descr.Input->Recv(tmp, TInstant::Max()));

                if (tmp.Empty()) {
                    break;
                }

                url += StrInplace(tmp);
            }

            tmp = TChunkList(std::move(url));

            descr.Input->UnRecv(std::move(tmp));
        } else {
            url = descr.Request->RequestLine().GetURL();
        }

        TBarnavigParseContext ctx(std::move(url));

        ctx.Parse();

        if (!ctx.Barnavig_.Empty()) {
            TMurmurHash2A<ui64> hash;
            hash.Update(ctx.Barnavig_.Data(), ctx.Barnavig_.Size());
            return hash.Value();
        } else {
            return RandomNumber<ui64>();
        }
    }
};

INodeHandle<IHasher>* NModHasher::NBarnavig::Handle() {
    return THasher::Handle();
}
