#include "module.h"

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

using namespace NConfig;
using namespace NSrvKernel;
using namespace NModMeta;

namespace {
    class TKeyValueParser : public NConfig::IConfig::IFunc {
    public:
        explicit TKeyValueParser(TVector<std::pair<TString, TString>>& storage)
            : Storage_(storage)
        {}
        void DoConsume(const TString& key, NConfig::IConfig::IValue* value) override {
            Storage_.emplace_back(key, value->AsString());
        }
    private:
        TVector<std::pair<TString, TString>>& Storage_;
    };
}

MODULE_BASE(meta, TModuleWithSubModule) {
    TModule(const TModuleParams& mp)
        : TModuleBase(mp)
    {
        Config->ForEach(this);

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

        for (const auto& field : Fields_) {
            FieldsAsString_.append(" <::").append(field.first).append(":").append(field.second).append("::>");
        }
    }

    START_PARSE {
        ON_KEY("id", Id_) {
            return;
        }

        if (key == "fields") {
            TKeyValueParser parser(Fields_);
            value->AsSubConfig()->ForEach(&parser);
            return;
        }

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

private:
    TError DoRun(const TConnDescr& descr) const noexcept override {
        if (Id_) {
            descr.ExtraAccessLog << ' ' << Id_;
        }
        descr.ExtraAccessLog << FieldsAsString_;
        return Submodule_->Run(descr);
    }

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

    bool DoCanWorkWithoutHTTP() const override {
        return true;
    }

private:
    TString Id_;
    TVector<std::pair<TString, TString>> Fields_;
    TString FieldsAsString_;
};

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