{% import "utils.inc.jinja" as utils %}
{{- utils.do_not_edit() }}
// This file was generated from {{ proto.source_file }}
#include "{{ proto.source_file_without_ext }}_client.usrv.pb.hpp"

{# DO NOT ADD NEW INCLUDES HERE! Add them inside codegen_definitions.hpp instead #}
#include <userver/ugrpc/client/impl/codegen_definitions.hpp>

{{ utils.include_grpcpp(proto.source_file_without_ext) }}

{% call utils.optional_namespace(proto.namespace) %}

{% for service in proto.services %}

// Inline to deduplicate between client.usrv.cpp and service.usrv.cpp
inline constexpr std::string_view k{{service.name}}MethodNames[] = {
{% for method in service.method %}
    "{{proto.package_prefix}}{{service.name}}/{{method.name}}",
{% endfor %}
};

// Inline to deduplicate between client.usrv.cpp and service.usrv.cpp
inline const bool k{{service.name}}TypesRegistration =
    (USERVER_NAMESPACE::ugrpc::impl::RegisterMessageTypes({
{% for method in service.method %}
        std::string("{{method.input_type}}").substr(1),
        std::string("{{method.output_type}}").substr(1),
{% endfor %}
    }),
    false);

{{service.name}}Client::{{service.name}}Client(
    USERVER_NAMESPACE::ugrpc::client::impl::ClientDependencies&& dependencies)
    : impl_(std::move(dependencies), GetMetadata(),
            std::in_place_type<{{utils.namespace_with_colons(proto.namespace)}}::{{service.name}}>) {
    }
{% for method in service.method %}
{% set method_id = loop.index0 %}

{% if not method.client_streaming and not method.server_streaming %}
{{ method.output_type | grpc_to_cpp_name }} {{service.name}}Client::{{method.name}}(
    const {{ method.input_type | grpc_to_cpp_name }}& request,
    std::unique_ptr<::grpc::ClientContext> context,
    const USERVER_NAMESPACE::ugrpc::client::Qos& qos
) const {
    return Async{{method.name}}(request, std::move(context), qos).Get();
}

{{service.name}}Client::{{method.name}}ResponseFuture {{service.name}}Client::Async{{method.name}}(
    const {{ method.input_type | grpc_to_cpp_name }}& request,
    std::unique_ptr<::grpc::ClientContext> context,
    const USERVER_NAMESPACE::ugrpc::client::Qos& qos
) const {
    auto& stub = impl_.NextStubFromMethodId<{{utils.namespace_with_colons(proto.namespace)}}::{{service.name}}>({{method_id}});
    return {
        USERVER_NAMESPACE::ugrpc::client::impl::CreateCallParams(
          impl_, {{method_id}}, std::move(context), qos
        ),
        [&stub](auto&&... args) { return stub.PrepareAsync{{method.name}}(std::forward<decltype(args)>(args)...); },
        request,
    };
}
{% endif %}
{% if method.client_streaming or method.server_streaming %}

{{service.name}}Client::{{method.name}}Call
{{service.name}}Client::{{method.name}}(
    {% if not method.client_streaming %}
    const {{ method.input_type | grpc_to_cpp_name }}& request,
    {% endif %}
    std::unique_ptr<::grpc::ClientContext> context,
    const USERVER_NAMESPACE::ugrpc::client::Qos& qos
) const {
      auto& stub = impl_.NextStubFromMethodId<{{utils.namespace_with_colons(proto.namespace)}}::{{service.name}}>({{method_id}});
      return {
          USERVER_NAMESPACE::ugrpc::client::impl::CreateCallParams(
              impl_, {{method_id}}, std::move(context), qos
          ),
          [&stub](auto&&... args) { return stub.PrepareAsync{{method.name}}(std::forward<decltype(args)>(args)...); },
{% if not method.client_streaming %}
          request,
{% endif %}
      };
}
{% endif %}
{% endfor %}

USERVER_NAMESPACE::ugrpc::impl::StaticServiceMetadata
{{ service.name }}Client::GetMetadata() {
  (void)k{{service.name}}TypesRegistration;  // odr-use

  return USERVER_NAMESPACE::ugrpc::impl::MakeStaticServiceMetadata<
      {{utils.namespace_with_colons(proto.namespace)}}::{{service.name}}>(
          k{{service.name}}MethodNames);
}
{% endfor %}
{% endcall %} {# utils.optional_namespace #}
