// 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 domain["has_exports"] %}
#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}} = {{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 %}
    {% set type_def = type_definition(domain.domain + "." + type.id)%}

// {{type.description}}
class {{config.protocol.export_macro}} {{type.id}} : public Serializable{% if type.exported %}, 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 %}
      {% if "enum" in property %}

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

      {% if property.optional %}
    bool {{"has" | to_method_case}}{{property.name | to_title_case}}() { return m_{{property.name}}.isJust(); }
    {{resolve_type(property).raw_return_type}} {{"get" | to_method_case}}{{property.name | to_title_case}}({{resolve_type(property).raw_pass_type}} defaultValue) { return m_{{property.name}}.isJust() ? m_{{property.name}}.fromJust() : defaultValue; }
      {% else %}
    {{resolve_type(property).raw_return_type}} {{"get" | to_method_case}}{{property.name | to_title_case}}() { return {{resolve_type(property).to_raw_type % ("m_" + property.name)}}; }
      {% endif %}
    void {{"set" | to_method_case}}{{property.name | to_title_case}}({{resolve_type(property).pass_type}} value) { m_{{property.name}} = {{resolve_type(property).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 type.exported %}
    {{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) %}
        {% set count = count + 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 %}

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

        {{type_def.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 resolve_type(property) %}
          m_{{property.name}} = {{resolve_type(property).default_value}};
      {%endif %}
    {% endfor %}
    }

    {% for property in type.properties %}
      {% if property.optional %}
    Maybe<{{resolve_type(property).raw_type}}> m_{{property.name}};
      {% else %}
    {{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 generate_command(domain.domain, command.name) %}{% continue %}{% endif %}
    {% if 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<{{resolve_type(parameter).raw_type}}> {{parameter.name}}
        {%- else -%}
                {{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 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<{{resolve_type(parameter).raw_type}}> in_{{parameter.name}}
      {%- else -%}
        {{resolve_type(parameter).pass_type}} in_{{parameter.name}}
      {%- endif -%}
    {%- endfor -%}
    {%- if 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<{{resolve_type(parameter).raw_type}}>* out_{{parameter.name}}
        {%- else -%}
        {{resolve_type(parameter).type}}* out_{{parameter.name}}
        {%- endif -%}
      {%- endfor -%}
    {%- endif -%}
    ) = 0;
  {% endfor %}

  {% if 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 generate_event(domain.domain, event.name) %}{% continue %}{% endif %}
    void {{event.name | to_method_case}}(
    {%- for parameter in event.parameters -%}
      {%- if "optional" in parameter -%}
        Maybe<{{resolve_type(parameter).raw_type}}> {{parameter.name}} = Maybe<{{resolve_type(parameter).raw_type}}>()
      {%- else -%}
        {{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)
