// This file is generated by TypeBuilder_cpp.template.

// Copyright (c) 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include {{format_domain_include(config.protocol.package, domain.domain)}}

#include {{format_include(config.protocol.package, "Protocol")}}

#include "{{config.crdtp.dir}}/cbor.h"
#include "{{config.crdtp.dir}}/find_by_first.h"
#include "{{config.crdtp.dir}}/span.h"

{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}
namespace {{domain.domain}} {

using {{config.crdtp.namespace}}::DeserializerState;
using {{config.crdtp.namespace}}::ProtocolTypeTraits;

// ------------- Enum values from types.

const char Metainfo::domainName[] = "{{domain.domain}}";
const char Metainfo::commandPrefix[] = "{{domain.domain}}.";
const char Metainfo::version[] = "{{domain.version}}";
  {% for type in domain.types %}
    {% if not protocol.generate_type(domain.domain, type.id) %}{% continue %} {% endif %}
    {% if "enum" in type %}

namespace {{type.id}}Enum {
      {% for literal in type.enum %}
const char {{ literal | dash_to_camelcase}}[] = "{{literal}}";
      {% endfor %}
} // namespace {{type.id}}Enum
      {% if protocol.is_exported(domain.domain, type.id) %}

namespace API {
namespace {{type.id}}Enum {
        {% for literal in type.enum %}
const char* {{ literal | dash_to_camelcase}} = "{{literal}}";
        {% endfor %}
} // namespace {{type.id}}Enum
} // namespace API
      {% endif %}
    {% endif %}

    {% for property in type.properties %}
      {% if "enum" in property %}

        {% for literal in property.enum %}
const char* {{type.id}}::{{property.name | to_title_case}}Enum::{{literal | dash_to_camelcase}} = "{{literal}}";
        {% endfor %}
      {% endif %}
    {% endfor %}
    {% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %}
V8_CRDTP_BEGIN_DESERIALIZER({{type.id}})
      {% for property in type.properties | sort(attribute = 'name', case_sensitive=True) %}
      {% if property.optional %}
    V8_CRDTP_DESERIALIZE_FIELD_OPT("{{property.name}}", m_{{property.name}}),
      {% else %}
    V8_CRDTP_DESERIALIZE_FIELD("{{property.name}}", m_{{property.name}}),
      {% endif %}
      {% endfor %}
V8_CRDTP_END_DESERIALIZER()

V8_CRDTP_BEGIN_SERIALIZER({{type.id}})
      {% for property in type.properties %}
    V8_CRDTP_SERIALIZE_FIELD("{{property.name}}", m_{{property.name}});
      {% endfor %}
V8_CRDTP_END_SERIALIZER();

    {% if protocol.is_exported(domain.domain, type.id) %}
// static
std::unique_ptr<API::{{type.id}}> API::{{type.id}}::fromBinary(const uint8_t* data, size_t length)
{
    return protocol::{{domain.domain}}::{{type.id}}::FromBinary(data, length);
}
    {% endif %}
  {% endfor %}

// ------------- Enum values from params.

  {% for command in join_arrays(domain, ["commands", "events"]) %}
    {% for param in join_arrays(command, ["parameters", "returns"]) %}
      {% if "enum" in param %}

namespace {{command.name | to_title_case}} {
namespace {{param.name | to_title_case}}Enum {
        {% for literal in param.enum %}
const char* {{ literal | to_title_case}} = "{{literal}}";
        {% endfor %}
} // namespace {{param.name | to_title_case}}Enum
} // namespace {{command.name | to_title_case }}
        {% if protocol.is_exported(domain.domain, command.name + "." + param.name) %}

namespace API {
namespace {{command.name | to_title_case}} {
namespace {{param.name | to_title_case}}Enum {
        {% for literal in param.enum %}
const char* {{ literal | to_title_case}} = "{{literal}}";
        {% endfor %}
} // namespace {{param.name | to_title_case}}Enum
} // namespace {{command.name | to_title_case }}
} // namespace API
        {% endif %}
      {% endif %}
    {% endfor %}
  {% endfor %}

// ------------- Frontend notifications.
  {% for event in domain.events %}
    {% if not protocol.generate_event(domain.domain, event.name) %}{% continue %}{% endif %}

void Frontend::{{event.name | to_method_case}}(
    {%- for parameter in event.parameters %}
      {% if "optional" in parameter -%}
        Maybe<{{protocol.resolve_type(parameter).raw_type}}>
      {%- else -%}
        {{protocol.resolve_type(parameter).pass_type}}
      {%- endif %} {{parameter.name}}{%- if not loop.last -%}, {% endif -%}
    {% endfor -%})
{
    if (!frontend_channel_)
        return;
      {% if event.parameters %}
    {{config.crdtp.namespace}}::ObjectSerializer serializer;
        {% for parameter in event.parameters %}
    serializer.AddField({{config.crdtp.namespace}}::MakeSpan("{{parameter.name}}"), {{parameter.name}});
        {% endfor %}
    frontend_channel_->SendProtocolNotification({{config.crdtp.namespace}}::CreateNotification("{{domain.domain}}.{{event.name}}", serializer.Finish()));
      {% else %}
    frontend_channel_->SendProtocolNotification({{config.crdtp.namespace}}::CreateNotification("{{domain.domain}}.{{event.name}}"));
      {% endif %}
}
  {% endfor %}

void Frontend::flush()
{
    frontend_channel_->FlushProtocolNotifications();
}

void Frontend::sendRawNotification(std::unique_ptr<Serializable> notification)
{
    frontend_channel_->SendProtocolNotification(std::move(notification));
}

// --------------------- Dispatcher.

class DomainDispatcherImpl : public protocol::DomainDispatcher {
public:
    DomainDispatcherImpl(FrontendChannel* frontendChannel, Backend* backend)
        : DomainDispatcher(frontendChannel)
        , m_backend(backend) {}
    ~DomainDispatcherImpl() override { }

    using CallHandler = void (DomainDispatcherImpl::*)(const {{config.crdtp.namespace}}::Dispatchable& dispatchable);

    std::function<void(const {{config.crdtp.namespace}}::Dispatchable&)> Dispatch({{config.crdtp.namespace}}::span<uint8_t> command_name) override;

  {% for command in domain.commands %}
    {% if "redirect" in command %}{% continue %}{% endif %}
    {% if not protocol.generate_command(domain.domain, command.name) %}{% continue %}{% endif %}
    void {{command.name}}(const {{config.crdtp.namespace}}::Dispatchable& dispatchable);
  {% endfor %}
 protected:
    Backend* m_backend;
};

namespace {
// This helper method with a static map of command methods (instance methods
// of DomainDispatcherImpl declared just above) by their name is used immediately below,
// in the DomainDispatcherImpl::Dispatch method.
DomainDispatcherImpl::CallHandler CommandByName({{config.crdtp.namespace}}::span<uint8_t> command_name) {
  static auto* commands = [](){
    auto* commands = new std::vector<std::pair<{{config.crdtp.namespace}}::span<uint8_t>,
                              DomainDispatcherImpl::CallHandler>>{
      {% for command in domain.commands|sort(attribute="name",case_sensitive=True) %}
        {% if "redirect" in command %}{% continue %}{% endif %}
        {% if not protocol.generate_command(domain.domain, command.name) %}{% continue %}{% endif %}
    {
          {{config.crdtp.namespace}}::SpanFrom("{{command.name}}"),
          &DomainDispatcherImpl::{{command.name}}
    },
      {% endfor %}
    };
    return commands;
  }();
  return {{config.crdtp.namespace}}::FindByFirst<DomainDispatcherImpl::CallHandler>(*commands, command_name, nullptr);
}
}  // namespace

std::function<void(const {{config.crdtp.namespace}}::Dispatchable&)> DomainDispatcherImpl::Dispatch({{config.crdtp.namespace}}::span<uint8_t> command_name) {
  CallHandler handler = CommandByName(command_name);
  if (!handler) return nullptr;

  return [this, handler](const {{config.crdtp.namespace}}::Dispatchable& dispatchable) {
    (this->*handler)(dispatchable);
  };
}

  {% for command in domain.commands %}
    {% set command_name_title = command.name | to_title_case %}
    {% if "redirect" in command %}{% continue %}{% endif %}
    {% if not protocol.generate_command(domain.domain, command.name) %}{% continue %}{% endif %}
    {% if protocol.is_async_command(domain.domain, command.name) %}

class {{command_name_title}}CallbackImpl : public Backend::{{command_name_title}}Callback, public DomainDispatcher::Callback {
public:
    {{command_name_title}}CallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, int callId, {{config.crdtp.namespace}}::span<uint8_t> message)
        : DomainDispatcher::Callback(std::move(backendImpl), callId,
{{config.crdtp.namespace}}::SpanFrom("{{domain.domain}}.{{command.name}}"), message) { }

    void sendSuccess(
      {%- for parameter in command.returns -%}
        {%- if "optional" in parameter -%}
        Maybe<{{protocol.resolve_type(parameter).raw_type}}> {{parameter.name}}
        {%- else -%}
        {{protocol.resolve_type(parameter).pass_type}} {{parameter.name}}
        {%- endif -%}
        {%- if not loop.last -%}, {% endif -%}
      {%- endfor -%}) override
    {
        {{config.crdtp.namespace}}::ObjectSerializer serializer;
        {% for parameter in command.returns %}
        serializer.AddField({{config.crdtp.namespace}}::MakeSpan("{{parameter.name}}"), {{parameter.name}});
        {% endfor %}
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

    void sendFailure(const DispatchResponse& response) override
    {
        DCHECK(response.IsError());
        sendIfActive(nullptr, response);
    }
};
    {% endif %}

namespace {

    {% if "parameters" in command %}
struct {{command.name}}Params : public {{config.crdtp.namespace}}::DeserializableProtocolObject<{{command.name}}Params> {
      {% for parameter in command.parameters %}
        {% set parameter_type = protocol.resolve_type(parameter) %}
        {% if parameter.optional %}
    Maybe<{{parameter_type.raw_type}}> {{parameter.name}};
        {% else %}
    {{parameter_type.type}} {{parameter.name}};
        {% endif %}
      {% endfor %}
    DECLARE_DESERIALIZATION_SUPPORT();
};

V8_CRDTP_BEGIN_DESERIALIZER({{command.name}}Params)
      {% for parameter in command.parameters  | sort(attribute = 'name', case_sensitive=True) %}
      {% if parameter.optional %}
    V8_CRDTP_DESERIALIZE_FIELD_OPT("{{parameter.name}}", {{parameter.name}}),
      {% else %}
    V8_CRDTP_DESERIALIZE_FIELD("{{parameter.name}}", {{parameter.name}}),
      {% endif %}
      {% endfor %}
V8_CRDTP_END_DESERIALIZER()
     {% endif %}

}  // namespace

void DomainDispatcherImpl::{{command.name}}(const {{config.crdtp.namespace}}::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    {% if "parameters" in command %}
    auto deserializer = {{config.crdtp.namespace}}::DeferredMessage::FromSpan(dispatchable.Params())->MakeDeserializer();
    {{command.name}}Params params;
    {{command.name}}Params::Deserialize(&deserializer, &params);
    if (MaybeReportInvalidParams(dispatchable, deserializer))
      return;
    {% endif %}

    {% if "returns" in command and not protocol.is_async_command(domain.domain, command.name) %}
    // Declare output parameters.
      {% for parameter in command.returns %}
        {% if "optional" in parameter %}
    Maybe<{{protocol.resolve_type(parameter).raw_type}}> out_{{parameter.name}};
        {% else %}
    {{protocol.resolve_type(parameter).type}} out_{{parameter.name}};
        {% endif %}
      {% endfor %}
    {% endif %}

    {% if not protocol.is_async_command(domain.domain, command.name) %}
    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->{{command.name | to_method_case}}(
      {%- for parameter in command.parameters -%}
        {%- if not loop.first -%}, {% endif -%}
        {%- if "optional" in parameter -%}
        std::move(params.{{parameter.name}})
        {%- else -%}
        {{protocol.resolve_type(parameter).to_pass_type % ("params." + parameter.name)}}
        {%- endif -%}
      {%- endfor %}
      {%- if "returns" in command %}
        {%- for parameter in command.returns -%}
          {%- if not loop.first or command.parameters -%}, {% endif -%}
          &out_{{parameter.name}}
        {%- endfor %}
      {% endif %});
    if (response.IsFallThrough()) {
        channel()->FallThrough(dispatchable.CallId(), {{config.crdtp.namespace}}::SpanFrom("{{domain.domain}}.{{command.name}}"), dispatchable.Serialized());
        return;
    }
      {% if "returns" in command %}
      if (weak->get()) {
        std::unique_ptr<{{config.crdtp.namespace}}::Serializable> result;
        if (response.IsSuccess()) {
          {{config.crdtp.namespace}}::ObjectSerializer serializer;
          {% for parameter in command.returns %}
          serializer.AddField({{config.crdtp.namespace}}::MakeSpan("{{parameter.name}}"), out_{{parameter.name}});
          {% endfor %}
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
      {% else %}
    if (weak->get())
        weak->get()->sendResponse(dispatchable.CallId(), response);
      {% endif %}
    return;
    {% else %}
    m_backend->{{command.name | to_method_case}}(
      {%- for property in command.parameters -%}
        {%- if not loop.first -%}, {% endif -%}
        {%- if "optional" in property -%}
        std::move(params.{{property.name}})
        {%- else -%}
        {{protocol.resolve_type(property).to_pass_type % ("params." + property.name)}}
        {%- endif -%}
      {%- endfor -%}
        {%- if command.parameters -%}, {% endif -%}
        std::make_unique<{{command_name_title}}CallbackImpl>(weakPtr(), dispatchable.CallId(), dispatchable.Serialized()));
    {% endif %}
}
  {% endfor %}

namespace {
// This helper method (with a static map of redirects) is used from Dispatcher::wire
// immediately below.
const std::vector<std::pair<{{config.crdtp.namespace}}::span<uint8_t>, {{config.crdtp.namespace}}::span<uint8_t>>>& SortedRedirects() {
  static auto* redirects = [](){
    auto* redirects = new std::vector<std::pair<{{config.crdtp.namespace}}::span<uint8_t>, {{config.crdtp.namespace}}::span<uint8_t>>>{
      {% for command in domain.commands|sort(attribute="name",case_sensitive=True) %}
        {% if "redirect" in command %}
          { {{config.crdtp.namespace}}::SpanFrom("{{domain.domain}}.{{command.name}}"), {{config.crdtp.namespace}}::SpanFrom("{{command.redirect}}.{{command.name}}") },
        {% endif %}
      {% endfor %}
    };
    return redirects;
  }();
  return *redirects;
}
}  // namespace

// static
void Dispatcher::wire(UberDispatcher* uber, Backend* backend)
{
    auto dispatcher = std::make_unique<DomainDispatcherImpl>(uber->channel(), backend);
    uber->WireBackend({{config.crdtp.namespace}}::SpanFrom("{{domain.domain}}"), SortedRedirects(), std::move(dispatcher));
}

} // {{domain.domain}}
{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}}
{% endfor %}
