{% from "constant_definition.tmpl" import constant_def %}
{% from "enum_definition.tmpl" import enum_def %}
{% from "data_types_definition.tmpl" import struct_def %}

{%- macro declare_params(parameters, boxed=false) %}
{%-   for param in parameters -%}
{{param.kind|java_type(boxed)}} {{param|name}}
{%- if not loop.last %}, {% endif %}
{%-   endfor %}
{%- endmacro %}

{% macro declare_request_params(method) %}
{{declare_params(method.parameters)}}
{%-   if method.response_parameters != None -%}
{%- if method.parameters %}, {% endif %}
{{method|interface_response_name}} callback
{%-   endif -%}
{% endmacro %}

{%- macro declare_callback(method) -%}

interface {{method|interface_response_name}} extends org.chromium.mojo.bindings.Callbacks.Callback{{method.response_parameters|length}}{% if method.response_parameters %}<
{%-   for param in method.response_parameters -%}
{{param.kind|java_type(True)}}
{%- if not loop.last %}, {% endif %}
{%-   endfor -%}
>{% endif %} { }
{%- endmacro -%}

{%- macro run_callback(variable, parameters) -%}
{%-   if parameters -%}
{%-     for param in parameters -%}
{{variable}}.{{param|name}}
{%-   if not loop.last %}, {% endif %}
{%-     endfor -%}
{%-   endif -%}
{%- endmacro -%}

{%- macro flags_for_method(method, is_request) -%}
{{flags(method.response_parameters != None, is_request)}}
{%- endmacro -%}

{%- macro flags(use_response_flag, is_request) -%}
{%-  if not use_response_flag -%}
org.chromium.mojo.bindings.MessageHeader.NO_FLAG
{%-   elif is_request: -%}
org.chromium.mojo.bindings.MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG
{%-   else -%}
org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG
{%-   endif -%}
{%- endmacro -%}

{%- macro manager_class(interface, fully_qualified=False) -%}
{% if fully_qualified %}org.chromium.mojo.bindings.Interface.{% endif %}Manager<{{interface|name}}, {{interface|name}}.Proxy>
{%- endmacro -%}

{%- macro manager_def(interface) -%}
public static final {{manager_class(interface, True)}} MANAGER =
        new {{manager_class(interface, True)}}() {

    public String getName() {
        return "{{namespace|replace(".","::")}}::{{interface.name}}";
    }

    public int getVersion() {
      return {{interface.version}};
    }

    public Proxy buildProxy(org.chromium.mojo.system.Core core,
                            org.chromium.mojo.bindings.MessageReceiverWithResponder messageReceiver) {
        return new Proxy(core, messageReceiver);
    }

    public Stub buildStub(org.chromium.mojo.system.Core core, {{interface|name}} impl) {
        return new Stub(core, impl);
    }

    public {{interface|name}}[] buildArray(int size) {
      return new {{interface|name}}[size];
    }
};
{%- endmacro -%}

{%- macro accept_body(interface, with_response) -%}
try {
    org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
            message.asServiceMessage();
    org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
    if (!header.validateHeader({{flags(with_response, True)}})) {
        return false;
    }
    switch(header.getType()) {
{%   if with_response %}
        case org.chromium.mojo.bindings.interfacecontrol.InterfaceControlMessagesConstants.RUN_MESSAGE_ID:
            return org.chromium.mojo.bindings.InterfaceControlMessagesHelper.handleRun(
                    getCore(), {{interface|name}}_Internal.MANAGER, messageWithHeader, receiver);
{%   else %}
        case org.chromium.mojo.bindings.interfacecontrol.InterfaceControlMessagesConstants.RUN_OR_CLOSE_PIPE_MESSAGE_ID:
            return org.chromium.mojo.bindings.InterfaceControlMessagesHelper.handleRunOrClosePipe(
                    {{interface|name}}_Internal.MANAGER, messageWithHeader);
{%   endif %}
{%   for method in interface.methods %}
{%     if (with_response and method.response_parameters != None) or
        (not with_response and method.response_parameters == None) %}
{%       set request_struct = method.param_struct %}
{%       if with_response %}
{%         set response_struct = method.response_param_struct %}
{%       endif %}
        case {{method|method_ordinal_name}}: {
{%       if method.parameters %}
            {{request_struct|name}} data =
                    {{request_struct|name}}.deserialize(messageWithHeader.getPayload());
{%       else %}
            {{request_struct|name}}.deserialize(messageWithHeader.getPayload());
{%       endif %}
            try {
                getImpl().{{method|name}}({{run_callback('data', method.parameters)}}{% if with_response %}{% if method.parameters %}, {% endif %}new {{response_struct|name}}ProxyToResponder(getCore(), receiver, header.getRequestId()){% endif %});
            } catch (RuntimeException e) {
                // TODO(lhchavez): Remove this hack. See b/28814913 for details.
                android.util.Log.wtf("{{namespace}}.{{interface.name}}", "Uncaught runtime exception", e);
            }
            return true;
        }
{%     endif %}
{%   endfor %}
        default:
            return false;
    }
} catch (org.chromium.mojo.bindings.DeserializationException e) {
    System.err.println(e.toString());
    return false;
}
{%- endmacro -%}

{% macro interface_def(interface) %}
public interface {{interface|name}} extends org.chromium.mojo.bindings.Interface {
{%  for constant in interface.constants %}

    {{constant_def(constant)|indent(4)}}
{%  endfor %}
{%  for enum in interface.enums %}

    {{enum_def(enum, false)|indent(4)}}
{% endfor %}

    public interface Proxy extends {{interface|name}}, org.chromium.mojo.bindings.Interface.Proxy {
    }

    {{manager_class(interface)}} MANAGER = {{interface|name}}_Internal.MANAGER;
{% for method in interface.methods %}

    void {{method|name}}({{declare_request_params(method)}});
{%   if method.response_parameters != None %}
    {{declare_callback(method)|indent(4)}}
{%   endif %}
{% endfor %}
}
{% endmacro %}

{% macro interface_internal_def(interface) %}
class {{interface|name}}_Internal {

    {{manager_def(interface)|indent(4)}}

{% for method in interface.methods %}
    private static final int {{method|method_ordinal_name}} = {{method.ordinal}};
{% endfor %}

    static final class Proxy extends org.chromium.mojo.bindings.Interface.AbstractProxy implements {{interface|name}}.Proxy {

        Proxy(org.chromium.mojo.system.Core core,
              org.chromium.mojo.bindings.MessageReceiverWithResponder messageReceiver) {
            super(core, messageReceiver);
        }
{% for method in interface.methods %}

        @Override
        public void {{method|name}}({{declare_request_params(method)}}) {
{%   set request_struct = method.param_struct %}
            {{request_struct|name}} _message = new {{request_struct|name}}();
{%   for param in method.parameters %}
            _message.{{param|name}} = {{param|name}};
{%   endfor %}
{%   if method.response_parameters != None %}
            getProxyHandler().getMessageReceiver().acceptWithResponder(
                    _message.serializeWithHeader(
                            getProxyHandler().getCore(),
                            new org.chromium.mojo.bindings.MessageHeader(
                                    {{method|method_ordinal_name}},
                                    {{flags_for_method(method, True)}},
                                    0)),
                    new {{method.response_param_struct|name}}ForwardToCallback(callback));
{%   else %}
            getProxyHandler().getMessageReceiver().accept(
                    _message.serializeWithHeader(
                            getProxyHandler().getCore(),
                            new org.chromium.mojo.bindings.MessageHeader({{method|method_ordinal_name}})));
{%   endif %}
        }
{% endfor %}

    }

    static final class Stub extends org.chromium.mojo.bindings.Interface.Stub<{{interface|name}}> {

        Stub(org.chromium.mojo.system.Core core, {{interface|name}} impl) {
            super(core, impl);
        }

        @Override
        public boolean accept(org.chromium.mojo.bindings.Message message) {
            {{accept_body(interface, False)|indent(12)}}
        }

        @Override
        public boolean acceptWithResponder(org.chromium.mojo.bindings.Message message, org.chromium.mojo.bindings.MessageReceiver receiver) {
            {{accept_body(interface, True)|indent(12)}}
        }
    }
{% for method in interface.methods %}

    {{ struct_def(method.param_struct, True)|indent(4) }}
{%   if method.response_parameters != None %}
{%   set response_struct = method.response_param_struct %}

    {{ struct_def(response_struct, True)|indent(4) }}

    static class {{response_struct|name}}ForwardToCallback extends org.chromium.mojo.bindings.SideEffectFreeCloseable
            implements org.chromium.mojo.bindings.MessageReceiver {
        private final {{interface|name}}.{{method|interface_response_name}} mCallback;

        {{response_struct|name}}ForwardToCallback({{interface|name}}.{{method|interface_response_name}} callback) {
            this.mCallback = callback;
        }

        @Override
        public boolean accept(org.chromium.mojo.bindings.Message message) {
            try {
                org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
                        message.asServiceMessage();
                org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
                if (!header.validateHeader({{method|method_ordinal_name}},
                                           {{flags_for_method(method, False)}})) {
                    return false;
                }
{%   if method.response_parameters|length %}
                {{response_struct|name}} response = {{response_struct|name}}.deserialize(messageWithHeader.getPayload());
{%   endif %}
                mCallback.call({{run_callback('response', method.response_parameters)}});
                return true;
            } catch (org.chromium.mojo.bindings.DeserializationException e) {
                return false;
            }
        }
    }

    static class {{response_struct|name}}ProxyToResponder implements {{interface|name}}.{{method|interface_response_name}} {

        private final org.chromium.mojo.system.Core mCore;
        private final org.chromium.mojo.bindings.MessageReceiver mMessageReceiver;
        private final long mRequestId;

        {{response_struct|name}}ProxyToResponder(
                org.chromium.mojo.system.Core core,
                org.chromium.mojo.bindings.MessageReceiver messageReceiver,
                long requestId) {
            mCore = core;
            mMessageReceiver = messageReceiver;
            mRequestId = requestId;
        }

        @Override
        public void call({{declare_params(method.response_parameters, true)}}) {
            {{response_struct|name}} _response = new {{response_struct|name}}();
{%   for param in method.response_parameters %}
            _response.{{param|name}} = {{param|name}};
{%   endfor %}
            org.chromium.mojo.bindings.ServiceMessage _message =
                    _response.serializeWithHeader(
                            mCore,
                            new org.chromium.mojo.bindings.MessageHeader(
                                    {{method|method_ordinal_name}},
                                    {{flags_for_method(method, False)}},
                                    mRequestId));
            mMessageReceiver.accept(_message);
        }
    }
{%   endif %}
{% endfor %}

}
{% endmacro %}
