// 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.

#ifndef {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_h
#define {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_h

{% if config.protocol.export_header %}
#include {{format_include(config.protocol.export_header)}}
{% endif %}
#include {{format_include(config.protocol.package, "Protocol")}}
// For each imported domain we generate a ValueConversions struct instead of a full domain definition
// and include Domain::API version from there.
{% for name in domain.dependencies %}
#include {{format_include(config.protocol.package, name)}}
{% endfor %}
{% if protocol.is_exported_domain(domain.domain) %}
#include {{format_include(config.exported.package, domain.domain)}}
{% endif %}

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

// ------------- Forward and enum declarations.
  {% for type in domain.types %}
    {% if type.type == "object" %}
      {% if "properties" in type %}
// {{type.description}}
class {{type.id}};
      {% else %}
// {{type.description}}
using {{type.id}} = Object;
      {% endif %}
    {% elif type.type != "array" %}
// {{type.description}}
using {{type.id}} = {{protocol.resolve_type(type).type}};
    {% endif %}
  {% endfor %}
  {% for type in domain.types %}
    {% if "enum" in type %}

namespace {{type.id}}Enum {
      {% for literal in type.enum %}
{{config.protocol.export_macro}} extern const char* {{ literal | dash_to_camelcase}};
      {% endfor %}
} // namespace {{type.id}}Enum
    {% endif %}
  {% endfor %}
  {% 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 %}
{{config.protocol.export_macro}} extern const char* {{literal | dash_to_camelcase}};
        {% endfor %}
} // {{param.name | to_title_case}}Enum
} // {{command.name | to_title_case }}
      {% endif %}
    {% endfor %}
  {% endfor %}

// ------------- Type and builder declarations.
  {% for type in domain.types %}
    {% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %}

// {{type.description}}
class {{config.protocol.export_macro}} {{type.id}} : public Serializable{% if protocol.is_exported(domain.domain, type.id) %}, public API::{{type.id}}{% endif %}{
    PROTOCOL_DISALLOW_COPY({{type.id}});
public:
    static std::unique_ptr<{{type.id}}> fromValue(protocol::Value* value, ErrorSupport* errors);

    ~{{type.id}}() override { }
    {% for property in type.properties %}
      {% set property_type = protocol.resolve_type(property) %}
      {% set property_name = property.name | to_title_case %}
      {% set property_field = "m_" + property.name %}
      {% if "enum" in property %}

    struct {{config.protocol.export_macro}} {{property_name}}Enum {
        {% for literal in property.enum %}
        static const char* {{literal | dash_to_camelcase}};
        {% endfor %}
    }; // {{property_name}}Enum
      {% endif %}

      {% if property.optional %}
    bool {{"has" | to_method_case}}{{property_name}}() { return {{property_field}}.isJust(); }
    {{property_type.raw_return_type}} {{"get" | to_method_case}}{{property_name}}({{property_type.raw_pass_type}} defaultValue) { return {{property_field}}.isJust() ? {{property_field}}.fromJust() : defaultValue; }
      {% else %}
    {{property_type.raw_return_type}} {{"get" | to_method_case}}{{property_name}}() { return {{property_type.to_raw_type % property_field}}; }
      {% endif %}
    void {{"set" | to_method_case}}{{property_name}}({{property_type.pass_type}} value) { {{property_field}} = {{property_type.to_rvalue % "value"}}; }
    {% endfor %}

    std::unique_ptr<protocol::DictionaryValue> toValue() const;
    String serialize() override { return toValue()->serialize(); }
    std::unique_ptr<{{type.id}}> clone() const;
    {% if protocol.is_exported(domain.domain, type.id) %}
    {{config.exported.string_out}} toJSONString() const override;
    {% endif %}

    template<int STATE>
    class {{type.id}}Builder {
    public:
        enum {
            NoFieldsSet = 0,
    {% set count = 0 %}
    {% for property in type.properties %}
      {% if not(property.optional) %}
        {# "count = count + 1" does not work with our version of jinja, use the loop index instead. #}
        {% set count = loop.index + 1 %}
          {{property.name | to_title_case}}Set = 1 << {{count}},
      {% endif %}
    {% endfor %}
            AllFieldsSet = (
    {%- for property in type.properties %}
      {% if not(property.optional) %}{{property.name | to_title_case}}Set | {%endif %}
    {% endfor %}0)};

    {% for property in type.properties %}
      {% set property_type = protocol.resolve_type(property) %}
      {% set property_name = property.name | to_title_case %}

      {% if property.optional %}
        {{type.id}}Builder<STATE>& {{"set" | to_method_case}}{{property_name}}({{property_type.pass_type}} value)
        {
            m_result->{{"set" | to_method_case}}{{property_name}}({{property_type.to_rvalue % "value"}});
            return *this;
        }
      {% else %}
        {{type.id}}Builder<STATE | {{property_name}}Set>& {{"set" | to_method_case}}{{property_name}}({{property_type.pass_type}} value)
        {
            static_assert(!(STATE & {{property_name}}Set), "property {{property.name}} should not be set yet");
            m_result->{{"set" | to_method_case}}{{property_name}}({{property_type.to_rvalue % "value"}});
            return castState<{{property_name}}Set>();
        }
      {% endif %}
    {% endfor %}

        std::unique_ptr<{{type.id}}> {{"build" | to_method_case}}()
        {
            static_assert(STATE == AllFieldsSet, "state should be AllFieldsSet");
            return std::move(m_result);
        }

    private:
        friend class {{type.id}};
        {{type.id}}Builder() : m_result(new {{type.id}}()) { }

        template<int STEP> {{type.id}}Builder<STATE | STEP>& castState()
        {
            return *reinterpret_cast<{{type.id}}Builder<STATE | STEP>*>(this);
        }

        {{protocol.type_definition(domain.domain + "." + type.id).type}} m_result;
    };

    static {{type.id}}Builder<0> {{"create" | to_method_case}}()
    {
        return {{type.id}}Builder<0>();
    }

private:
    {{type.id}}()
    {
    {% for property in type.properties %}
      {% if not(property.optional) and "default_value" in protocol.resolve_type(property) %}
          m_{{property.name}} = {{protocol.resolve_type(property).default_value}};
      {%endif %}
    {% endfor %}
    }

    {% for property in type.properties %}
      {% if property.optional %}
    Maybe<{{protocol.resolve_type(property).raw_type}}> m_{{property.name}};
      {% else %}
    {{protocol.resolve_type(property).type}} m_{{property.name}};
      {% endif %}
    {% endfor %}
};

  {% endfor %}

// ------------- Backend interface.

class {{config.protocol.export_macro}} Backend {
public:
    virtual ~Backend() { }

  {% for command in domain.commands %}
    {% 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 {{config.protocol.export_macro}} {{command.name | to_title_case}}Callback {
    public:
        virtual 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 -%}
        ) = 0;
        virtual void sendFailure(const DispatchResponse&) = 0;
        virtual void fallThrough() = 0;
        virtual ~{{command.name | to_title_case}}Callback() { }
    };
    {% endif %}
    {%- if not protocol.is_async_command(domain.domain, command.name) %}
    virtual DispatchResponse {{command.name | to_method_case}}(
    {%- else %}
    virtual void {{command.name | to_method_case}}(
    {%- endif %}
    {%- for parameter in command.parameters -%}
      {%- if not loop.first -%}, {% endif -%}
      {%- if "optional" in parameter -%}
        Maybe<{{protocol.resolve_type(parameter).raw_type}}> in_{{parameter.name}}
      {%- else -%}
        {{protocol.resolve_type(parameter).pass_type}} in_{{parameter.name}}
      {%- endif -%}
    {%- endfor -%}
    {%- if protocol.is_async_command(domain.domain, command.name) -%}
      {%- if command.parameters -%}, {% endif -%}
        std::unique_ptr<{{command.name | to_title_case}}Callback> callback
    {%- else -%}
      {%- for parameter in command.returns -%}
        {%- if (not loop.first) or command.parameters -%}, {% endif -%}
        {%- 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 -%}
    ) = 0;
  {% endfor %}

  {% if protocol.generate_disable(domain) %}
    virtual DispatchResponse {{"disable" | to_method_case}}()
    {
        return DispatchResponse::OK();
    }
  {% endif %}
};

// ------------- Frontend interface.

class {{config.protocol.export_macro}} Frontend {
public:
    explicit Frontend(FrontendChannel* frontendChannel) : m_frontendChannel(frontendChannel) { }
  {% for event in domain.events %}
    {% if not protocol.generate_event(domain.domain, event.name) %}{% continue %}{% endif %}
    void {{event.name | to_method_case}}(
    {%- for parameter in event.parameters -%}
      {%- if "optional" in parameter -%}
        Maybe<{{protocol.resolve_type(parameter).raw_type}}> {{parameter.name}} = Maybe<{{protocol.resolve_type(parameter).raw_type}}>()
      {%- else -%}
        {{protocol.resolve_type(parameter).pass_type}} {{parameter.name}}
      {%- endif -%}{%- if not loop.last -%}, {% endif -%}
    {%- endfor -%}
    );
  {% endfor %}

    void flush();
    void sendRawNotification(const String&);
private:
    FrontendChannel* m_frontendChannel;
};

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

class {{config.protocol.export_macro}} Dispatcher {
public:
    static void wire(UberDispatcher*, Backend*);

private:
    Dispatcher() { }
};

// ------------- Metainfo.

class {{config.protocol.export_macro}} Metainfo {
public:
    using BackendClass = Backend;
    using FrontendClass = Frontend;
    using DispatcherClass = Dispatcher;
    static const char domainName[];
    static const char commandPrefix[];
    static const char version[];
};

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

#endif // !defined({{"_".join(config.protocol.namespace)}}_{{domain.domain}}_h)
