// This file is generated

// 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_include(config.protocol.package, domain.domain)}}

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

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

// ------------- 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 "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 %}

std::unique_ptr<{{type.id}}> {{type.id}}::fromValue(protocol::Value* value, ErrorSupport* errors)
{
    if (!value || value->type() != protocol::Value::TypeObject) {
        errors->addError("object expected");
        return nullptr;
    }

    std::unique_ptr<{{type.id}}> result(new {{type.id}}());
    protocol::DictionaryValue* object = DictionaryValue::cast(value);
    errors->push();
    {% for property in type.properties %}
    protocol::Value* {{property.name}}Value = object->get("{{property.name}}");
      {% if property.optional %}
    if ({{property.name}}Value) {
        errors->setName("{{property.name}}");
        result->m_{{property.name}} = ValueConversions<{{protocol.resolve_type(property).raw_type}}>::fromValue({{property.name}}Value, errors);
    }
      {% else %}
    errors->setName("{{property.name}}");
    result->m_{{property.name}} = ValueConversions<{{protocol.resolve_type(property).raw_type}}>::fromValue({{property.name}}Value, errors);
      {% endif %}
    {% endfor %}
    errors->pop();
    if (errors->hasErrors())
        return nullptr;
    return result;
}

std::unique_ptr<protocol::DictionaryValue> {{type.id}}::toValue() const
{
    std::unique_ptr<protocol::DictionaryValue> result = DictionaryValue::create();
    {% for property in type.properties %}
      {% set property_type = protocol.resolve_type(property) %}
      {% set property_field = "m_" + property.name %}
      {% if property.optional %}
    if ({{property_field}}.isJust())
        result->setValue("{{property.name}}", ValueConversions<{{property_type.raw_type}}>::toValue({{property_field}}.fromJust()));
      {% else %}
    result->setValue("{{property.name}}", ValueConversions<{{property_type.raw_type}}>::toValue({{property_type.to_raw_type % property_field}}));
      {% endif %}
    {% endfor %}
    return result;
}

std::unique_ptr<{{type.id}}> {{type.id}}::clone() const
{
    ErrorSupport errors;
    return fromValue(toValue().get(), &errors);
}
    {% if protocol.is_exported(domain.domain, type.id) %}

{{config.exported.string_out}} {{type.id}}::toJSONString() const
{
    String json = toValue()->serialize();
    return {{config.exported.to_string_out % "json"}};
}

// static
std::unique_ptr<API::{{type.id}}> API::{{type.id}}::fromJSONString(const {{config.exported.string_in}}& json)
{
    ErrorSupport errors;
    std::unique_ptr<Value> value = StringUtil::parseJSON(json);
    if (!value)
        return nullptr;
    return protocol::{{domain.domain}}::{{type.id}}::fromValue(value.get(), &errors);
}
    {% 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 (!m_frontendChannel)
        return;
      {% if event.parameters %}
    std::unique_ptr<{{event.name | to_title_case}}Notification> messageData = {{event.name | to_title_case}}Notification::{{"create" | to_method_case}}()
        {% for parameter in event.parameters %}
          {% if not "optional" in parameter %}
        .{{"set" | to_method_case}}{{parameter.name | to_title_case}}({{protocol.resolve_type(parameter).to_pass_type % parameter.name}})
          {% endif %}
        {% endfor %}
        .{{ "build" | to_method_case }}();
        {% for parameter in event.parameters %}
          {% if "optional" in parameter %}
    if ({{parameter.name}}.isJust())
        messageData->{{"set" | to_method_case}}{{parameter.name | to_title_case}}(std::move({{parameter.name}}).takeJust());
          {% endif %}
        {% endfor %}
    m_frontendChannel->sendProtocolNotification(InternalResponse::createNotification("{{domain.domain}}.{{event.name}}", std::move(messageData)));
      {% else %}
    m_frontendChannel->sendProtocolNotification(InternalResponse::createNotification("{{domain.domain}}.{{event.name}}"));
      {% endif %}
}
  {% endfor %}

void Frontend::flush()
{
    m_frontendChannel->flushProtocolNotifications();
}

void Frontend::sendRawNotification(const String& notification)
{
    m_frontendChannel->sendProtocolNotification(InternalRawNotification::create(notification));
}

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

class DispatcherImpl : public protocol::DispatcherBase {
public:
    DispatcherImpl(FrontendChannel* frontendChannel, Backend* backend, bool fallThroughForNotFound)
        : DispatcherBase(frontendChannel)
        , m_backend(backend)
        , m_fallThroughForNotFound(fallThroughForNotFound) {
  {% for command in domain.commands %}
    {% if "redirect" in command %}{% continue %}{% endif %}
    {% if not protocol.generate_command(domain.domain, command.name) %}{% continue %}{% endif %}
        m_dispatchMap["{{domain.domain}}.{{command.name}}"] = &DispatcherImpl::{{command.name}};
  {% endfor %}
    }
    ~DispatcherImpl() override { }
    DispatchResponse::Status dispatch(int callId, const String& method, std::unique_ptr<protocol::DictionaryValue> messageObject) override;

protected:
    using CallHandler = DispatchResponse::Status (DispatcherImpl::*)(int callId, std::unique_ptr<DictionaryValue> messageObject, ErrorSupport* errors);
    using DispatchMap = protocol::HashMap<String, CallHandler>;
    DispatchMap m_dispatchMap;

  {% for command in domain.commands %}
    {% if "redirect" in command %}{% continue %}{% endif %}
    {% if not protocol.generate_command(domain.domain, command.name) %}{% continue %}{% endif %}
    DispatchResponse::Status {{command.name}}(int callId, std::unique_ptr<DictionaryValue> requestMessageObject, ErrorSupport*);
  {% endfor %}

    Backend* m_backend;
    bool m_fallThroughForNotFound;
};

DispatchResponse::Status DispatcherImpl::dispatch(int callId, const String& method, std::unique_ptr<protocol::DictionaryValue> messageObject)
{
    protocol::HashMap<String, CallHandler>::iterator it = m_dispatchMap.find(method);
    if (it == m_dispatchMap.end()) {
        if (m_fallThroughForNotFound)
            return DispatchResponse::kFallThrough;
        reportProtocolError(callId, DispatchResponse::kMethodNotFound, "'" + method + "' wasn't found", nullptr);
        return DispatchResponse::kError;
    }

    protocol::ErrorSupport errors;
    return (this->*(it->second))(callId, std::move(messageObject), &errors);
}

  {% 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 DispatcherBase::Callback {
public:
    {{command_name_title}}CallbackImpl(std::unique_ptr<DispatcherBase::WeakPtr> backendImpl, int callId, int callbackId)
        : DispatcherBase::Callback(std::move(backendImpl), callId, callbackId) { }

    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
    {
        std::unique_ptr<protocol::DictionaryValue> resultObject = DictionaryValue::create();
          {% for parameter in command.returns %}
            {% if "optional" in parameter %}
        if ({{parameter.name}}.isJust())
            resultObject->setValue("{{parameter.name}}", ValueConversions<{{protocol.resolve_type(parameter).raw_type}}>::toValue({{parameter.name}}.fromJust()));
           {% else %}
        resultObject->setValue("{{parameter.name}}", ValueConversions<{{protocol.resolve_type(parameter).raw_type}}>::toValue({{protocol.resolve_type(parameter).to_raw_type % parameter.name}}));
            {% endif %}
          {% endfor %}
        sendIfActive(std::move(resultObject), DispatchResponse::OK());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

    void sendFailure(const DispatchResponse& response) override
    {
        DCHECK(response.status() == DispatchResponse::kError);
        sendIfActive(nullptr, response);
    }
};
    {% endif %}

DispatchResponse::Status DispatcherImpl::{{command.name}}(int callId, std::unique_ptr<DictionaryValue> requestMessageObject, ErrorSupport* errors)
{
    {% if "parameters" in command %}
    // Prepare input parameters.
    protocol::DictionaryValue* object = DictionaryValue::cast(requestMessageObject->get("params"));
    errors->push();
      {% for parameter in command.parameters %}
        {% set parameter_type = protocol.resolve_type(parameter) %}
    protocol::Value* {{parameter.name}}Value = object ? object->get("{{parameter.name}}") : nullptr;
        {% if parameter.optional %}
    Maybe<{{parameter_type.raw_type}}> in_{{parameter.name}};
    if ({{parameter.name}}Value) {
        errors->setName("{{parameter.name}}");
        in_{{parameter.name}} = ValueConversions<{{parameter_type.raw_type}}>::fromValue({{parameter.name}}Value, errors);
    }
        {% else %}
    errors->setName("{{parameter.name}}");
    {{parameter_type.type}} in_{{parameter.name}} = ValueConversions<{{parameter_type.raw_type}}>::fromValue({{parameter.name}}Value, errors);
        {% endif %}
      {% endfor %}
    errors->pop();
    if (errors->hasErrors()) {
        reportProtocolError(callId, DispatchResponse::kInvalidParams, kInvalidParamsString, errors);
        return DispatchResponse::kError;
    }
    {% 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<DispatcherBase::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(in_{{parameter.name}})
        {%- else -%}
        {{protocol.resolve_type(parameter).to_pass_type % ("in_" + 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 "returns" in command %}
    if (response.status() == DispatchResponse::kFallThrough)
        return response.status();
    std::unique_ptr<protocol::DictionaryValue> result = DictionaryValue::create();
    if (response.status() == DispatchResponse::kSuccess) {
        {% for parameter in command.returns %}
          {% if "optional" in parameter %}
        if (out_{{parameter.name}}.isJust())
            result->setValue("{{parameter.name}}", ValueConversions<{{protocol.resolve_type(parameter).raw_type}}>::toValue(out_{{parameter.name}}.fromJust()));
          {% else %}
        result->setValue("{{parameter.name}}", ValueConversions<{{protocol.resolve_type(parameter).raw_type}}>::toValue({{protocol.resolve_type(parameter).to_raw_type % ("out_" + parameter.name)}}));
          {% endif %}
        {% endfor %}
    }
    if (weak->get())
        weak->get()->sendResponse(callId, response, std::move(result));
      {% else %}
    if (weak->get())
        weak->get()->sendResponse(callId, response);
      {% endif %}
    return response.status();
    {% else %}
    std::unique_ptr<DispatcherBase::WeakPtr> weak = weakPtr();
    std::unique_ptr<{{command_name_title}}CallbackImpl> callback(new {{command.name | to_title_case}}CallbackImpl(weakPtr(), callId, nextCallbackId()));
    m_backend->{{command.name | to_method_case}}(
      {%- for property in command.parameters -%}
        {%- if not loop.first -%}, {% endif -%}
        {%- if "optional" in property -%}
        std::move(in_{{property.name}})
        {%- else -%}
        {{protocol.resolve_type(property).to_pass_type % ("in_" + property.name)}}
        {%- endif -%}
      {%- endfor -%}
        {%- if command.parameters -%}, {% endif -%}
        std::move(callback));
    return (weak->get() && weak->get()->lastCallbackFallThrough()) ? DispatchResponse::kFallThrough : DispatchResponse::kAsync;
    {% endif %}
}
  {% endfor %}

// static
void Dispatcher::wire(UberDispatcher* dispatcher, Backend* backend)
{
    dispatcher->registerBackend("{{domain.domain}}", std::unique_ptr<protocol::DispatcherBase>(new DispatcherImpl(dispatcher->channel(), backend, dispatcher->fallThroughForNotFound())));
}

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