{#
 # 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::ScriptValue<{{member.type}}>::StrongReference(
              other.{{member.name}}_->referenced_value()));
    }
{% 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::ScriptValue<{{member.type}}>::StrongReference(
                other.{{member.name}}_->referenced_value()));
    } 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}}_->referenced_value());
{% 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::ScriptValue<{{member.type}}>::StrongReference(*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::ScriptValue<{{member.type}}>::StrongReference> {{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
