/******************************************************************
 *
 *    THIS FILE HAS BEEN AUTOGENERATED, DO NOT MODIFY
 *
 ******************************************************************/

#include "{{listener_header}}"

namespace {{namespace}} {

void {{name}}Listener::DoReceive() {
  zmq::socket_t sock(_zmq, ZMQ_REP);
  sock.bind(_address);

  while (true) {
    try {
      rs::RequestReceiver receiver;
      receiver.Receive(sock);

      rs::Arena rep_content_arena;
      bool has_rep_content = false;

      rs::Stopwatch sw;

      try {
        switch (receiver.method_id()) {
          {% for s in services -%}
          {% for m in s.methods -%}
          case {{m.method_id}}:
            rs::Log::Info("Processing {{s.name}}::{{m.name}}");
            {% if m.has_reply -%}
            _{{s.var_name}}.{{m.name}}(
              receiver.GetContent<::{{namespace}}::{{m.request}}>(),
              {{m.reply}}(&rep_content_arena));
            has_rep_content = true;
            {% else -%}
            _{{s.var_name}}.{{m.name}}(
              receiver.GetContent<::{{namespace}}::{{m.request}}>());
            {% endif %}
          break;
          {% endfor %}
          {% endfor %}
        }

        if (has_rep_content) {
          rs::ReplySender sender(true, "OK", rep_content_arena.arena(), rep_content_arena.size());
          sender.Send(sock);          
        } else {
          rs::ReplySender sender(true, "OK", nullptr, 0);
          sender.Send(sock);
        }

        rs::Log::Info("Message processed in: " + std::to_string(sw.LapseTime()) + "ms");
      } catch (std::exception &ex) {
        rs::ReplySender sender(false, ex.what(), nullptr, 0);
        sender.Send(sock);

        rs::Log::Error(std::string("Processing failed: ") + ex.what());
      }
    } catch (zmq::error_t &err) {
      rs::Log::Error(std::string("ZMQ error: ") + err.what());
      return;
    }
  }
}

}