// This file is generated by TypeBuilder_h.template.

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

// ------------- Forward and enum declarations.
  {% 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 ::{{config.crdtp.namespace}}::ProtocolObject<{{type.id}}>{% if protocol.is_exported(domain.domain, type.id) %},
    public API::{{type.id}}{% endif %} {
public:
    ~{{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 %}

    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:
    DECLARE_SERIALIZATION_SUPPORT();

    {{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::Success();
    }
  {% endif %}
};

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

class {{config.protocol.export_macro}} Frontend {
public:
  explicit Frontend(FrontendChannel* frontend_channel) : frontend_channel_(frontend_channel) {}
  {% 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(std::unique_ptr<Serializable>);
 private:
  FrontendChannel* frontend_channel_;
};

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