{%- import "interface_macros.tmpl" as interface_macros %}
{%- import "struct_macros.tmpl" as struct_macros %}

{%- set class_name = interface.name %}
{%- set proxy_name = interface.name ~ "Proxy" %}
{%- set namespace_as_string = "%s"|format(namespace|replace(".","::")) %}

{%- macro alloc_params(struct, params, message, description) %}
  mojo::internal::SerializationContext serialization_context;
  serialization_context.handles.Swap(({{message}})->mutable_handles());
  serialization_context.associated_endpoint_handles.swap(
      *({{message}})->mutable_associated_endpoint_handles());
  bool success = true;
{%-   for param in struct.packed.packed_fields_in_ordinal_order %}
  {{param.field.kind|cpp_wrapper_type}} p_{{param.field.name}}{};
{%-   endfor %}
  {{struct.name}}DataView input_data_view({{params}}, &serialization_context);
  {{struct_macros.deserialize(struct, "input_data_view", "p_%s", "success")}}
  if (!success) {
    ReportValidationErrorForMessage(
        {{message}},
        mojo::internal::VALIDATION_ERROR_DESERIALIZATION_FAILED,
        "{{description}} deserializer");
    return false;
  }
{%- endmacro %}

{%- macro pass_params(parameters) %}
{%-   for param in parameters %}
std::move(p_{{param.name}})
{%-     if not loop.last %}, {% endif %}
{%-   endfor %}
{%- endmacro %}

{%- macro build_message(struct, input_pattern, struct_display_name,
                        serialization_context) -%}
  {{struct_macros.serialize(struct, struct_display_name, input_pattern,
                            "params", "builder.buffer()",
                            serialization_context)}}
  ({{serialization_context}})->handles.Swap(
      builder.message()->mutable_handles());
  ({{serialization_context}})->associated_endpoint_handles.swap(
      *builder.message()->mutable_associated_endpoint_handles());
{%- endmacro %}

{#--- Begin #}
const char {{class_name}}::Name_[] = "{{namespace_as_string}}::{{class_name}}";

{#--- Constants #}
{%-  for constant in interface.constants %}
{%-   if constant.kind|is_string_kind %}
const char {{interface.name}}::{{constant.name}}[] = {{constant|constant_value}};
{%-   endif %}
{%- endfor %}


{%- for method in interface.methods %}
{%-   if method.sync %}
bool {{class_name}}::{{method.name}}({{interface_macros.declare_sync_method_params("", method)}}) {
  NOTREACHED();
  return false;
}
{%-   endif %}
{%- endfor %}

{#--- ForwardToCallback definition #}
{%- for method in interface.methods -%}
{%-   if method.response_parameters != None %}
{%-     if method.sync %}
class {{class_name}}_{{method.name}}_HandleSyncResponse
    : public mojo::MessageReceiver {
 public:
  {{class_name}}_{{method.name}}_HandleSyncResponse(
      bool* result
{%-       for param in method.response_parameters -%}
      , {{param.kind|cpp_wrapper_type}}* out_{{param.name}}
{%-       endfor %})
      : result_(result)
{%-       for param in method.response_parameters -%}
        , out_{{param.name}}_(out_{{param.name}})
{%-       endfor %} {
    DCHECK(!*result_);
  }
  bool Accept(mojo::Message* message) override;
 private:
  bool* result_;
{%-       for param in method.response_parameters %}
  {{param.kind|cpp_wrapper_type}}* out_{{param.name}}_;
{%-       endfor -%}
  DISALLOW_COPY_AND_ASSIGN({{class_name}}_{{method.name}}_HandleSyncResponse);
};
bool {{class_name}}_{{method.name}}_HandleSyncResponse::Accept(
    mojo::Message* message) {
  internal::{{class_name}}_{{method.name}}_ResponseParams_Data* params =
      reinterpret_cast<internal::{{class_name}}_{{method.name}}_ResponseParams_Data*>(
          message->mutable_payload());

{%-       set desc = class_name~"::"~method.name~" response" %}
  {{alloc_params(method.response_param_struct, "params", "message", desc)}}

{%-       for param in method.response_parameters %}
  *out_{{param.name}}_ = std::move(p_{{param.name}});
{%-       endfor %}
  mojo::internal::SyncMessageResponseSetup::SetCurrentSyncResponseMessage(
      message);
  *result_ = true;
  return true;
}
{%-     endif %}

class {{class_name}}_{{method.name}}_ForwardToCallback
    : public mojo::MessageReceiver {
 public:
  {{class_name}}_{{method.name}}_ForwardToCallback(
{%-     if use_once_callback %}
      {{class_name}}::{{method.name}}Callback callback
{%-     else %}
      const {{class_name}}::{{method.name}}Callback& callback
{%-     endif %}
      ) : callback_(std::move(callback)) {
  }
  bool Accept(mojo::Message* message) override;
 private:
  {{class_name}}::{{method.name}}Callback callback_;
  DISALLOW_COPY_AND_ASSIGN({{class_name}}_{{method.name}}_ForwardToCallback);
};
bool {{class_name}}_{{method.name}}_ForwardToCallback::Accept(
    mojo::Message* message) {
  internal::{{class_name}}_{{method.name}}_ResponseParams_Data* params =
      reinterpret_cast<internal::{{class_name}}_{{method.name}}_ResponseParams_Data*>(
          message->mutable_payload());

{%-     set desc = class_name~"::"~method.name~" response" %}
  {{alloc_params(method.response_param_struct, "params", "message", desc)}}
  if (!callback_.is_null()) {
    mojo::internal::MessageDispatchContext context(message);
    std::move(callback_).Run({{pass_params(method.response_parameters)}});
  }
  return true;
}
{%-   endif %}
{%- endfor %}

{{proxy_name}}::{{proxy_name}}(mojo::MessageReceiverWithResponder* receiver)
    : receiver_(receiver) {
}

{#--- Proxy definitions #}

{%- for method in interface.methods %}
{%-   set message_name =
          "internal::k%s_%s_Name"|format(interface.name, method.name) %}
{%-   set params_struct = method.param_struct %}
{%-   set params_description =
          "%s.%s request"|format(interface.name, method.name) %}
{%-   if method.sync %}
bool {{proxy_name}}::{{method.name}}(
    {{interface_macros.declare_sync_method_params("param_", method)}}) {
  mojo::internal::SerializationContext serialization_context;
  {{struct_macros.get_serialized_size(params_struct, "param_%s",
                                      "&serialization_context")}}

  mojo::internal::MessageBuilder builder(
      {{message_name}},
      mojo::Message::kFlagIsSync | mojo::Message::kFlagExpectsResponse,
      size, serialization_context.associated_endpoint_count);

  {{build_message(params_struct, "param_%s", params_description,
                  "&serialization_context")}}

  bool result = false;
  std::unique_ptr<mojo::MessageReceiver> responder(
      new {{class_name}}_{{method.name}}_HandleSyncResponse(
          &result
{%-     for param in method.response_parameters -%}
          , param_{{param.name}}
{%-     endfor %}));
  ignore_result(receiver_->AcceptWithResponder(builder.message(),
                                               std::move(responder)));
  return result;
}
{%-   endif %}

void {{proxy_name}}::{{method.name}}(
    {{interface_macros.declare_request_params("in_", method, use_once_callback)}}) {
  mojo::internal::SerializationContext serialization_context;
  {{struct_macros.get_serialized_size(params_struct, "in_%s",
                                      "&serialization_context")}}

{%- if method.response_parameters != None %}
  constexpr uint32_t kFlags = mojo::Message::kFlagExpectsResponse;
{%- else %}
  constexpr uint32_t kFlags = 0;
{%- endif %}
  mojo::internal::MessageBuilder builder(
      {{message_name}}, kFlags, size,
      serialization_context.associated_endpoint_count);

  {{build_message(params_struct, "in_%s", params_description,
                  "&serialization_context")}}

{%- if method.response_parameters != None %}
  std::unique_ptr<mojo::MessageReceiver> responder(
      new {{class_name}}_{{method.name}}_ForwardToCallback(
          std::move(callback)));
  ignore_result(receiver_->AcceptWithResponder(builder.message(),
                                               std::move(responder)));
{%- else %}
  // This return value may be ignored as false implies the Connector has
  // encountered an error, which will be visible through other means.
  ignore_result(receiver_->Accept(builder.message()));
{%- endif %}
}
{%- endfor %}

{#--- ProxyToResponder definition #}
{%- for method in interface.methods -%}
{%-   if method.response_parameters != None %}
{%-     set message_name =
            "internal::k%s_%s_Name"|format(interface.name, method.name) %}
{%-     set response_params_struct = method.response_param_struct %}
{%-     set params_description =
            "%s.%s response"|format(interface.name, method.name) %}
class {{class_name}}_{{method.name}}_ProxyToResponder {
 public:
  static {{class_name}}::{{method.name}}Callback CreateCallback(
      uint64_t request_id,
      bool is_sync,
      std::unique_ptr<mojo::MessageReceiverWithStatus> responder) {
    std::unique_ptr<{{class_name}}_{{method.name}}_ProxyToResponder> proxy(
        new {{class_name}}_{{method.name}}_ProxyToResponder(
            request_id, is_sync, std::move(responder)));
    return base::Bind(&{{class_name}}_{{method.name}}_ProxyToResponder::Run,
                      base::Passed(&proxy));
  }

  ~{{class_name}}_{{method.name}}_ProxyToResponder() {
#if DCHECK_IS_ON()
    if (responder_) {
      // Is the Service destroying the callback without running it
      // and without first closing the pipe?
      responder_->DCheckInvalid("The callback passed to "
          "{{class_name}}::{{method.name}}() was never run.");
    }
#endif
    // If the Callback was dropped then deleting the responder will close
    // the pipe so the calling application knows to stop waiting for a reply.
    responder_ = nullptr;
  }

 private:
  {{class_name}}_{{method.name}}_ProxyToResponder(
      uint64_t request_id,
      bool is_sync,
      std::unique_ptr<mojo::MessageReceiverWithStatus> responder)
      : request_id_(request_id),
        is_sync_(is_sync),
        responder_(std::move(responder)) {
  }

  void Run(
      {{interface_macros.declare_responder_params(
          "in_", method.response_parameters, for_blink)}});

  uint64_t request_id_;
  bool is_sync_;
  std::unique_ptr<mojo::MessageReceiverWithStatus> responder_;

  DISALLOW_COPY_AND_ASSIGN({{class_name}}_{{method.name}}_ProxyToResponder);
};

void {{class_name}}_{{method.name}}_ProxyToResponder::Run(
    {{interface_macros.declare_responder_params(
        "in_", method.response_parameters, for_blink)}}) {
  mojo::internal::SerializationContext serialization_context;
  {{struct_macros.get_serialized_size(response_params_struct, "in_%s",
                                      "&serialization_context")}}

  uint32_t flags = (is_sync_ ? mojo::Message::kFlagIsSync : 0) |
                   mojo::Message::kFlagIsResponse;
  mojo::internal::MessageBuilder builder(
      {{message_name}}, flags, size,
      serialization_context.associated_endpoint_count);
  builder.message()->set_request_id(request_id_);

  {{build_message(response_params_struct, "in_%s", params_description,
                  "&serialization_context")}}
  ignore_result(responder_->Accept(builder.message()));
  // TODO(darin): Accept() returning false indicates a malformed message, and
  // that may be good reason to close the connection. However, we don't have a
  // way to do that from here. We should add a way.
  responder_ = nullptr;
}
{%-   endif -%}
{%- endfor %}

{#--- StubDispatch definition #}

// static
bool {{class_name}}StubDispatch::Accept(
    {{interface.name}}* impl,
    mojo::Message* message) {
{%- if interface.methods %}
  switch (message->header()->name) {
{%-   for method in interface.methods %}
    case internal::k{{class_name}}_{{method.name}}_Name: {
{%-     if method.response_parameters == None %}
      internal::{{class_name}}_{{method.name}}_Params_Data* params =
          reinterpret_cast<internal::{{class_name}}_{{method.name}}_Params_Data*>(
              message->mutable_payload());

{%-       set desc = class_name~"::"~method.name %}
      {{alloc_params(method.param_struct, "params", "message", desc)|
          indent(4)}}
      // A null |impl| means no implementation was bound.
      assert(impl);
      TRACE_EVENT0("mojom", "{{class_name}}::{{method.name}}");
      mojo::internal::MessageDispatchContext context(message);
      impl->{{method.name}}({{pass_params(method.parameters)}});
      return true;
{%-     else %}
      break;
{%-     endif %}
    }
{%-   endfor %}
  }
{%- endif %}
  return false;
}

// static
bool {{class_name}}StubDispatch::AcceptWithResponder(
    {{interface.name}}* impl,
    mojo::Message* message,
    std::unique_ptr<mojo::MessageReceiverWithStatus> responder) {
{%- if interface.methods %}
  switch (message->header()->name) {
{%-   for method in interface.methods %}
    case internal::k{{class_name}}_{{method.name}}_Name: {
{%-     if method.response_parameters != None %}
      internal::{{class_name}}_{{method.name}}_Params_Data* params =
          reinterpret_cast<internal::{{class_name}}_{{method.name}}_Params_Data*>(
              message->mutable_payload());

{%-       set desc = class_name~"::"~method.name %}
      {{alloc_params(method.param_struct, "params", "message", desc)|
          indent(4)}}
      {{class_name}}::{{method.name}}Callback callback =
          {{class_name}}_{{method.name}}_ProxyToResponder::CreateCallback(
              message->request_id(),
              message->has_flag(mojo::Message::kFlagIsSync),
              std::move(responder));
      // A null |impl| means no implementation was bound.
      assert(impl);
      TRACE_EVENT0("mojom", "{{class_name}}::{{method.name}}");
      mojo::internal::MessageDispatchContext context(message);
      impl->{{method.name}}(
{%- if method.parameters -%}{{pass_params(method.parameters)}}, {% endif -%}std::move(callback));
      return true;
{%-     else %}
      break;
{%-     endif %}
    }
{%-   endfor %}
  }
{%- endif %}
  return false;
}

{#--- Request validator definitions #}

bool {{class_name}}RequestValidator::Accept(mojo::Message* message) {
  if (mojo::internal::ControlMessageHandler::IsControlMessage(message))
    return true;

  mojo::internal::ValidationContext validation_context(
    message->payload(), message->payload_num_bytes(),
    message->handles()->size(), message->payload_num_interface_ids(), message,
    "{{class_name}} RequestValidator");

  switch (message->header()->name) {
{%- for method in interface.methods %}
    case internal::k{{class_name}}_{{method.name}}_Name: {
{%-   if method.response_parameters != None %}
      if (!mojo::internal::ValidateMessageIsRequestExpectingResponse(
              message, &validation_context)) {
        return false;
      }
{%-   else %}
      if (!mojo::internal::ValidateMessageIsRequestWithoutResponse(
              message, &validation_context)) {
        return false;
      }
{%-   endif %}
      if (!mojo::internal::ValidateMessagePayload<
               internal::{{class_name}}_{{method.name}}_Params_Data>(
                  message, &validation_context)) {
        return false;
      }
      return true;
    }
{%- endfor %}
    default:
      break;
  }

  // Unrecognized message.
  ReportValidationError(
      &validation_context,
      mojo::internal::VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD);
  return false;
}

{#--- Response validator definitions #}
{% if interface|has_callbacks %}
bool {{class_name}}ResponseValidator::Accept(mojo::Message* message) {
  if (mojo::internal::ControlMessageHandler::IsControlMessage(message))
    return true;

  mojo::internal::ValidationContext validation_context(
    message->payload(), message->payload_num_bytes(),
    message->handles()->size(), message->payload_num_interface_ids(), message,
    "{{class_name}} ResponseValidator");

  if (!mojo::internal::ValidateMessageIsResponse(message, &validation_context))
    return false;
  switch (message->header()->name) {
{%- for method in interface.methods if method.response_parameters != None %}
    case internal::k{{class_name}}_{{method.name}}_Name: {
      if (!mojo::internal::ValidateMessagePayload<
               internal::{{class_name}}_{{method.name}}_ResponseParams_Data>(
                    message, &validation_context)) {
        return false;
      }
      return true;
    }
{%- endfor %}
    default:
      break;
  }

  // Unrecognized message.
  ReportValidationError(
      &validation_context,
      mojo::internal::VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD);
  return false;
}
{%- endif -%}
