// 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 type.exported %}

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<{{resolve_type(property).raw_type}}>::fromValue({{property.name}}Value, errors);
    }
      {% else %}
    errors->setName("{{property.name}}");
    result->m_{{property.name}} = ValueConversions<{{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 %}
      {% if property.optional %}
    if (m_{{property.name}}.isJust())
        result->setValue("{{property.name}}", ValueConversions<{{resolve_type(property).raw_type}}>::toValue(m_{{property.name}}.fromJust()));
      {% else %}
    result->setValue("{{property.name}}", ValueConversions<{{resolve_type(property).raw_type}}>::toValue({{resolve_type(property).to_raw_type % ("m_" + property.name)}}));
      {% endif %}
    {% endfor %}
    return result;
}

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

{{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 param.exported %}

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 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<{{resolve_type(parameter).raw_type}}>
      {%- else -%}
        {{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}}({{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 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 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 %}
    {% if "redirect" in command %}{% continue %}{% endif %}
    {% if not generate_command(domain.domain, command.name) %}{% continue %}{% endif %}
    {% if is_async_command(domain.domain, command.name) %}

class {{command.name | to_title_case}}CallbackImpl : public Backend::{{command.name | to_title_case}}Callback, public DispatcherBase::Callback {
public:
    {{command.name | to_title_case}}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<{{resolve_type(parameter).raw_type}}> {{parameter.name}}
        {%- else -%}
        {{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<{{resolve_type(parameter).raw_type}}>::toValue({{parameter.name}}.fromJust()));
           {% else %}
        resultObject->setValue("{{parameter.name}}", ValueConversions<{{resolve_type(parameter).raw_type}}>::toValue({{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 property in command.parameters %}
    protocol::Value* {{property.name}}Value = object ? object->get("{{property.name}}") : nullptr;
        {% if property.optional %}
    Maybe<{{resolve_type(property).raw_type}}> in_{{property.name}};
    if ({{property.name}}Value) {
        errors->setName("{{property.name}}");
        in_{{property.name}} = ValueConversions<{{resolve_type(property).raw_type}}>::fromValue({{property.name}}Value, errors);
    }
        {% else %}
    errors->setName("{{property.name}}");
    {{resolve_type(property).type}} in_{{property.name}} = ValueConversions<{{resolve_type(property).raw_type}}>::fromValue({{property.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 is_async_command(domain.domain, command.name) %}
    // Declare output parameters.
      {% for property in command.returns %}
        {% if "optional" in property %}
    Maybe<{{resolve_type(property).raw_type}}> out_{{property.name}};
        {% else %}
    {{resolve_type(property).type}} out_{{property.name}};
        {% endif %}
      {% endfor %}
    {% endif %}

    {% if not is_async_command(domain.domain, command.name) %}
    std::unique_ptr<DispatcherBase::WeakPtr> weak = weakPtr();
    DispatchResponse response = 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 -%}
        {{resolve_type(property).to_pass_type % ("in_" + property.name)}}
        {%- endif -%}
      {%- endfor %}
      {%- if "returns" in command %}
        {%- for property in command.returns -%}
          {%- if not loop.first or command.parameters -%}, {% endif -%}
          &out_{{property.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<{{resolve_type(parameter).raw_type}}>::toValue(out_{{parameter.name}}.fromJust()));
          {% else %}
        result->setValue("{{parameter.name}}", ValueConversions<{{resolve_type(parameter).raw_type}}>::toValue({{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<{{command.name | to_title_case}}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 -%}
        {{resolve_type(property).to_pass_type % ("in_" + property.name)}}
        {%- endif -%}
      {%- endfor -%}
        {%- if command.parameters -%}, {% endif -%}
        std::move(callback));
    return 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 %}
