#include "module.h"

#include <balancer/modules/srcrwr_ext/handler.h>

#include <balancer/kernel/http/parser/common_headers.h>
#include <balancer/kernel/http/parser/http.h>
#include <balancer/kernel/log/errorlog.h>
#include <balancer/kernel/module/module.h>
#include <balancer/kernel/srcrwr/srcrwr_addrs.h>


using namespace NSrvKernel;

namespace NModSrcrwrExt {

MODULE(srcrwr_ext) {
public:
    explicit TModule(const TModuleParams& mp)
        : TModuleBase(mp)
    {
        Config->ForEach(this);
    }

private:
    START_PARSE
    {
        ON_KEY("remove_prefix", Handler_.PrefixToRemove()) {
            return;
        }

        ON_KEY("domains", Handler_.Domains()) {
            return;
        }

        {
            Y_ENSURE_EX(!Submodule_, TConfigParseError() << "several modules");
            Submodule_ = Loader->MustLoad(key, Copy(value->AsSubConfig()));
            return;
        }
    } END_PARSE

    void HandleSrcrwr(const TConnDescr& descr) const
    {
        if (!descr.Request || !descr.Properties) {
            return;
        }

        TStringBuf host = descr.Request->Headers().GetFirstValue("host");
        if (!host) {
            return;
        }

        TString hostStr{StripString(host)};
        if (Handler_.Handle(hostStr, descr.Properties->SrcrwrAddrs)) {
            LOG_ERROR(TLOG_DEBUG, descr, "set srcrwr_ext for " << host);
        }
    }

    TError DoRun(const TConnDescr& descr) const override
    {
        try {
            HandleSrcrwr(descr);
        } catch(std::exception& e) {
            LOG_ERROR(TLOG_ERR, descr, "exception in srcrwr_ext module: " << e.what());
        } catch(...) {
            LOG_ERROR(TLOG_ERR, descr, "exception in srcrwr_ext module");
        }

        Y_DEFER {
            if (descr.Properties) {
                Handler_.CleanUp(descr.Properties->SrcrwrAddrs);
            }
        };

        auto result = Submodule_->Run(descr);

        return result;
    }

private:
    THandler Handler_;
    THolder<IModule> Submodule_;
};

}

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