// This file is generated

// Copyright 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 HEADLESS_PUBLIC_DEVTOOLS_DOMAINS_{{domain.domain | camelcase_to_hacker_style | upper}}_H_
#define HEADLESS_PUBLIC_DEVTOOLS_DOMAINS_{{domain.domain | camelcase_to_hacker_style | upper}}_H_

#include "base/callback.h"
#include "base/observer_list.h"
#include "base/values.h"
{% for domain_name in domain.dependencies %}
#include "headless/public/devtools/domains/types_{{domain_name | camelcase_to_hacker_style}}.h"
{% endfor %}
#include "headless/public/headless_export.h"
#include "headless/public/internal/message_dispatcher.h"

{# Macro for defining a member function for a given command. #}
{% macro command_decl(command) %}
  {% set method_name = command.name | sanitize_literal | to_title_case %}
  {% if command.description %}
  // {{ command.description.replace('\n', '\n  // ') }}
  {% endif %}
  void {{method_name}}(std::unique_ptr<{{method_name}}Params> params, base::OnceCallback<void(std::unique_ptr<{{method_name}}Result>)> callback = base::OnceCallback<void(std::unique_ptr<{{method_name}}Result>)>());
  {# Generate convenience methods that take the required parameters directly. #}
  {# Don't generate these for experimental commands. #}
  {% if "parameters" in command and not command.experimental %}
  void {{method_name}}({##}
    {% for parameter in command.parameters -%}
      {% if parameter.get("optional", False) -%}
        {% break %}
      {% endif %}
      {% if not loop.first %}, {% endif %}
{{resolve_type(parameter).pass_type}} {{parameter.name | camelcase_to_hacker_style -}}
    {% endfor %}
    {% if command.get("parameters", []) and not command.parameters[0].get("optional", False) %}, {% endif %}{# -#}
    {% if command.get("returns", []) -%}
      base::OnceCallback<void(std::unique_ptr<{{method_name}}Result>)> callback = base::OnceCallback<void(std::unique_ptr<{{method_name}}Result>)>(){##}
    {% else -%}
      base::OnceClosure callback = base::OnceClosure(){##}
    {% endif %});
    {# If the command has no return value, generate a convenience method that #}
    {# accepts a base::Closure together with the parameters object. #}
    {% if not command.get("returns", []) %}
  void {{method_name}}(std::unique_ptr<{{method_name}}Params> params, base::OnceClosure callback);
    {% endif %}
  {% endif %}
{% endmacro %}

namespace headless {
namespace {{domain.domain | camelcase_to_hacker_style}} {
class HEADLESS_EXPORT ExperimentalDomain;
class HEADLESS_EXPORT ExperimentalObserver;
{% if "events" in domain %}

class HEADLESS_EXPORT ExperimentalObserver {
 public:
  virtual ~ExperimentalObserver() {}
  {% for event in domain.events %}
    {% if event.description %}
  // {{event.description.replace('\n', '\n  // ')}}
    {% endif %}
  virtual void On{{event.name | to_title_case}}(const {{event.name | to_title_case}}Params& params) {}
  {% endfor %}
};

class HEADLESS_EXPORT Observer : public ExperimentalObserver {
 public:
  virtual ~Observer() {}
  {% for event in domain.events %}
    {% if event.description %}
  // {% if event.experimental %}Experimental: {% endif %}{{event.description.replace('\n', '\n  // ')}}
    {% endif %}
  virtual void On{{event.name | to_title_case}}(const {{event.name | to_title_case}}Params& params) {% if event.experimental %}final {% endif %}{}
  {% endfor %}
};
{% endif %}

{% if domain.description %}
// {{domain.description.replace('\n', '\n// ')}}
{% endif %}
class HEADLESS_EXPORT Domain {
 public:
  {% if "events" in domain %}
  // Add or remove an observer. |observer| must be removed before being
  // destroyed.
  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);
  {% endif %}

  // Return the experimental interface for this domain. Note that experimental
  // commands may be changed or removed at any time.
  ExperimentalDomain* GetExperimental();

  {# Generate methods for each command. #}
  {% for command in domain.commands %}
    {# Skip redirected commands. #}
    {% if "redirect" in command %}{% continue %}{% endif %}
    {# Skip experimental commands. #}
    {% if command.experimental %}{% continue %}{% endif %}
{{ command_decl(command) }}
  {% endfor %}
 protected:
  Domain(internal::MessageDispatcher* dispatcher);
  ~Domain();

  {# Generate response handlers for commands that need them. #}
  {% for command in domain.commands %}
    {% if not "returns" in command %}{% continue %}{% endif %}
    {% set method_name = command.name | sanitize_literal | to_title_case %}
  static void Handle{{method_name}}Response(base::OnceCallback<void(std::unique_ptr<{{method_name}}Result>)> callback, const base::Value& response);
  {% endfor %}

  {# Generate event dispatchers. #}
  {% for event in domain.events %}
  void Dispatch{{event.name | to_title_case}}Event(const base::Value& params);
  {% endfor %}

  internal::MessageDispatcher* dispatcher_;  // Not owned.
  {% if "events" in domain %}
  base::ObserverList<ExperimentalObserver> observers_;
  {% endif %}

  {% if "events" in domain %}
 protected:
  void RegisterEventHandlersIfNeeded();

  {% endif %}
 private:
  {% if "events" in domain %}
  bool event_handlers_registered_ = false;

  {% endif %}
  DISALLOW_COPY_AND_ASSIGN(Domain);
};

class ExperimentalDomain : public Domain {
 public:
  ExperimentalDomain(internal::MessageDispatcher* dispatcher);
  ~ExperimentalDomain();

  {% if "events" in domain %}
  // Add or remove an observer. |observer| must be removed before being
  // destroyed.
  void AddObserver(ExperimentalObserver* observer);
  void RemoveObserver(ExperimentalObserver* observer);
  {% endif %}

  {# Generate methods for each experimental command. #}
  {% for command in domain.commands %}
    {# Skip redirected commands. #}
    {% if "redirect" in command %}{% continue %}{% endif %}
    {# Skip non-experimental commands. #}
    {% if not command.experimental %}{% continue %}{% endif %}
{{ command_decl(command) }}
  {% endfor %}

 private:
  DISALLOW_COPY_AND_ASSIGN(ExperimentalDomain);
};

}  // namespace {{domain.domain | camelcase_to_hacker_style}}
}  // namespace headless

#endif  // HEADLESS_PUBLIC_DEVTOOLS_DOMAINS_{{domain.domain | camelcase_to_hacker_style | upper}}_H_
