{#
 # Copyright 2017 Google Inc. All Rights Reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
 #     http://www.apache.org/licenses/LICENSE-2.0
 #
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #}
// Copyright {{today.year}} Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// clang-format off

// This file has been auto-generated by {{code_generator}}. DO NOT MODIFY!
// Auto-generated from template: {{template_path}}

#ifndef {{class_name}}_h
#define {{class_name}}_h

{% if conditional %}
#if defined({{conditional}})

{% endif %}
#include <string>

#include "base/optional.h"
#include "cobalt/script/script_value.h"
#include "cobalt/script/sequence.h"
#include "cobalt/script/value_handle.h"
{% for include in includes %}
#include "{{include}}"
{% endfor %}

{% for used_class in forward_declarations %}
{% if used_class.conditional %}
#if defined({{used_class.conditional}})
{% endif %}
using {{used_class.fully_qualified_name}};
{% if used_class.conditional %}
#endif  // defined({{used_class.conditional}})
{% endif %}
{% endfor %}

{% for component in components %}
namespace {{component}} {
{% endfor %}

{% if parent %}
class {{class_name}} : public {{parent}} {
{% else %}
class {{class_name}} {
{% endif %}
 public:
  {{class_name}}() {
{% for member in members %}
{% if not member.default_value %}
    has_{{member.name}}_ = false;
{% endif %}
{% if not member.is_script_value %}
{% if member.default_value %}
    {{member.name}}_ = {{member.default_value}};
{% else %}
    {{member.name}}_ = {{member.type}}();
{% endif %}
{% endif %}
{% endfor %}
  }

{% if parent %}
  {{class_name}}(const {{class_name}}& other)
    : {{parent}}(other) {
{% else %}
  {{class_name}}(const {{class_name}}& other) {
{% endif %}
{% for member in members %}
{% if not member.default_value %}
    has_{{member.name}}_ = other.has_{{member.name}}_;
{% endif %}
{% if not member.is_script_value %}
    {{member.name}}_ = other.{{member.name}}_;
{% else %}
    if (other.{{member.name}}_) {
      {{member.name}}_.reset(
          new script::Handle<{{member.type}}>(
              *other.{{member.name}}_));
    }
{% endif %}
{% endfor %}
  }

  {{class_name}}& operator=(const {{class_name}}& other) {
{% if parent %}
    {{parent}}::operator=(other);
{% endif %}
{% for member in members %}
{% if not member.default_value %}
    has_{{member.name}}_ = other.has_{{member.name}}_;
{% endif %}
{% if not member.is_script_value %}
    {{member.name}}_ = other.{{member.name}}_;
{% else %}
    if (other.{{member.name}}_) {
      {{member.name}}_.reset(
          new script::Handle<{{member.type}}>(
              *other.{{member.name}}_));
    } else {
      {{member.name}}_.reset();
    }
{% endif %}
{% endfor %}
    return *this;
  }

{% for member in members %}
  bool has_{{member.name}}() const {
{% if member.default_value %}
    return true;
{% else %}
    return has_{{member.name}}_;
{% endif %}
  }
  {{member.arg_type}} {{member.name}}() const {
{% if not member.default_value %}
    DCHECK(has_{{member.name}}_);
{% endif %}
{% if member.is_script_value %}
    if (!{{member.name}}_) {
      return NULL;
    }
    return ({{member.name}}_->GetScriptValue());
{% else %}
    return {{member.name}}_;
{% endif %}
  }
  void set_{{member.name}}({{member.arg_type}} value) {
{% if not member.default_value %}
    has_{{member.name}}_ = true;
{% endif %}
{% if member.is_script_value %}
    if (value) {
      {{member.name}}_.reset(
          new script::Handle<{{member.type}}>(*value));
    } else {
      {{member.name}}_.reset();
    }
{% else %}
    {{member.name}}_ = value;
{% endif %}
  }

{% endfor %}

 private:
{% for member in members %}
{% if not member.default_value %}
  bool has_{{member.name}}_;
{% endif %}
{% if member.is_script_value %}
  scoped_ptr<script::Handle<{{member.type}}>> {{member.name}}_;
{% else %}
  {{member.type}} {{member.name}}_;
{% endif %}
{% endfor %}
};

// This ostream override is necessary for MOCK_METHODs commonly used
// in idl test code
inline std::ostream& operator<<(
    std::ostream& stream, const {{components|join('::')}}::{{class_name}}& in) {
  UNREFERENCED_PARAMETER(in);
  stream << "[{{class_name}}]";
  return stream;
}

{% for component in components %}
}  // namespace {{component}}
{% endfor %}

{% if conditional %}
#endif  // defined({{conditional}})

{% endif %}
#endif  // {{class_name}}_h
