#include "module.h"

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

using namespace NSrvKernel;

Y_TLS(unpack) {
    TTls(TSharedCounter& parsingErrors, size_t workerId)
        : ParsingErrors(parsingErrors, workerId)
    {}

    TSharedCounter ParsingErrors;
};

MODULE_WITH_TLS_BASE(unpack, TModuleWithSubModule) {
public:
    TModule(const TModuleParams& mp)
        : TModuleBase(mp)
        , ParsingErrors_(mp.Control->SharedStatsManager().MakeCounter("unpack-http_parsing_errors").AllowDuplicate().Build())
    {
        Config->ForEach(this);

        if (!Submodule_) {
            ythrow TConfigParseError() << "no module configured";
        }
    }

private:
    START_PARSE {
        Submodule_.Reset(Loader->MustLoad(key, Copy(value->AsSubConfig())).Release());
        return;
    } END_PARSE

    THolder<TTls> DoInitTls(IWorkerCtl* process) override {
        return MakeHolder<TTls>(ParsingErrors_, process->WorkerId());
    }

    TError DoRun(const TConnDescr& descr, TTls& tls) const noexcept override {
        TRequest innerRequest;
        Y_TRY(TError, error) {
            TChunkList unparsed;
            return innerRequest.Read(descr.Input, unparsed, TInstant::Max());
        } Y_CATCH {
            ++tls.ParsingErrors;
            descr.ExtraAccessLog.SetSummary(GetHandle()->Name(), "request read error");
            return error;
        }

        TConnDescr newDescr = descr.Copy();
        newDescr.Request = &innerRequest;

        return Submodule_->Run(newDescr);
    }

    bool DoExtraAccessLog() const noexcept override {
        return true;
    }

private:
    TSharedCounter ParsingErrors_;
};

IModuleHandle* NModUnpack::Handle() {
    return TModule::Handle();
}
