// 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 %}
  {% if protocol.is_imported_dependency(name) %}
#include {{format_domain_include(config.protocol.package, name)}}
  {% endif %}
{% 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 not protocol.generate_type(domain.domain, type.id) %}{% continue %}{% endif %}
    {% if type.type == "object" %}
      {% if "properties" in type %}
class {{type.id}};
      {% else %}
using {{type.id}} = Object;
      {% endif %}
    {% elif type.type != "array" %}
using {{type.id}} = {{protocol.resolve_type(type).type}};
    {% endif %}
  {% endfor %}
  {% 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 %}
{{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 protocol.generate_type(domain.domain, type.id) %}{% continue %}{% endif %}
    {% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %}

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,
    {% for property in type.properties|rejectattr("optional") %}
            {{property.name | to_title_case}}Set = 1 << {{loop.index}},
    {% 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)
