{#
 # 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.
 #}

{#
 # Checks if object implements interface.
 #}
{% macro check_if_object_implements_interface() %}
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<{{impl_class}}>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
{%- endmacro %}

{#
 # Function body for operation bindings.
 # Parameters:
 #     operation: The operation context object
 #}
{% macro function_implementation(operation) %}
  v8::Isolate* isolate = info.GetIsolate();
{% if operation.is_static %}
{{ static_function_prologue() }}
{% else %}
  v8::Local<v8::Object> object = info.This();
{{ check_if_object_implements_interface() }}
{{ nonstatic_function_prologue(impl_class) }}
{% endif %}
{% call(arguments_list) extract_arguments(operation) %}
{{ call_cobalt_function(impl_class, operation.type, operation.name,
                         arguments_list, operation.raises_exception,
                         operation.call_with, operation.is_static) }}
{% if operation.type != 'void' %}
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
{% endif %}
{%- endcall %}
{%- endmacro %}

{#
 # Function body for setting an attribute value.
 # Parameters:
 #     attribute: The attribute context object.
 #     impl_class: Cobalt class name of the Cobalt implementation of the
 #         interface on which the attribute is a member.
 #     cobalt_impl_prefix: Variable name prefix of a pointer to a Cobalt
 #         implementation of the interface on which the attribute is a member.
 #}
{% macro set_attribute_implementation(attribute, impl_class,
                                      cobalt_impl_prefix="") %}
{% if attribute.put_forwards %}
  { // Begin scope of {{attribute.type}} forwarded_{{cobalt_impl_prefix}}impl.
    {{attribute.type}} forwarded_{{cobalt_impl_prefix}}impl =
{% if not attribute.is_static %}
       {{cobalt_impl_prefix}}impl->{{attribute.getter_function_name}}();
{% else %}
       {{impl_class}}::{{attribute.getter_function_name}}();
{% endif %}
    if (!forwarded_{{cobalt_impl_prefix}}impl) {
      NOTREACHED();
      return;
    }
    if (!exception_state.is_exception_set()) {
{{ set_attribute_implementation(attribute.put_forwards, attribute.type,
     "forwarded_" + cobalt_impl_prefix) -}}
    }
    return;
  } // End scope of {{attribute.type}} forwarded_{{cobalt_impl_prefix}}impl.
{% else %}
  TypeTraits<{{attribute.type}} >::ConversionType value;
  FromJSValue(isolate, v8_value, {{attribute.conversion_flags}}, &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }
{{ call_cobalt_function(impl_class, "void",
                        attribute.setter_function_name,
                        ["value"], attribute.raises_exception,
                        attribute.call_with, attribute.is_static,
                        cobalt_impl_prefix) }}
  return;
{% endif %} {#- attribute.put_forwards #}
{%- endmacro %}

{#
 # Extract and marshal arguments that will be passed to a function-like call.
 # Parameters:
 #     operation: An IdlOperation object
 # Passed to caller:
 #     A string that can be used as the parameters for a function call. It will
 #     be either empty, or a comma-separated list of variable names.
 #}
{% macro extract_arguments(operation) %}
{% set non_optional_arguments = operation.non_optional_arguments %}
{% set optional_arguments = operation.optional_arguments %}
{% set num_default_arguments = operation.num_default_arguments %}
{% set variadic_argument = operation.variadic_argument %}
{% set has_non_default_optional_arguments =
          operation.has_non_default_optional_arguments %}

{%- if non_optional_arguments|length > 0 %}
  const size_t kMinArguments = {{non_optional_arguments|length}};
  if (info.Length() < kMinArguments) {
    exception_state.SetSimpleException(script::kInvalidNumberOfArguments);
    return;
  }
{% endif -%}

{# Declare variables for all arguments #}
{% for argument in non_optional_arguments %}
{% if loop.first %}
  // Non-optional arguments
{% endif %}
  TypeTraits<{{argument.type}} >::ConversionType {{argument.name}};
{% endfor %}
{% for argument in optional_arguments if argument.default_value %}
{% if loop.first %}
  // Optional arguments with default values
{% endif %}
  TypeTraits<{{argument.type}} >::ConversionType {{argument.name}} =
      {{argument.default_value}};
{% endfor %}
{% for argument in optional_arguments if not argument.default_value %}
{% if loop.first %}
  // Optional arguments
{% endif %}
  TypeTraits<{{argument.type}} >::ConversionType {{argument.name}};
{% endfor %}
{% if variadic_argument %}
  // Variadic argument
  TypeTraits<{{variadic_argument.type}} >::ConversionType {{
      variadic_argument.name}};
{% endif -%}

{% for argument in non_optional_arguments %}
  DCHECK_LT({{loop.index0}}, info.Length());
  v8::Local<v8::Value> non_optional_value{{loop.index0}} = info[{{loop.index0}}];
  FromJSValue(isolate,
              non_optional_value{{loop.index0}},
              {{argument.conversion_flags}},
              &exception_state, &{{argument.name}});
  if (exception_state.is_exception_set()) {
    return;
  }
{% endfor -%}
{% for argument in optional_arguments %}
{% if loop.first %}
  size_t num_set_arguments = {{
      non_optional_arguments|length + num_default_arguments}};
{% endif %}
  if (info.Length() > {{loop.index0 + non_optional_arguments|length}}) {
    v8::Local<v8::Value> optional_value{{loop.index0}} = info[{{loop.index0 + non_optional_arguments|length}}];
    FromJSValue(isolate,
                optional_value{{loop.index0}},
                {{argument.conversion_flags}},
                &exception_state,
                &{{argument.name}});
    if (exception_state.is_exception_set()) {
      return;
    }
{% if not argument.default_value %}
    ++num_set_arguments;
{% endif %}
  }
{% endfor %}
{% if variadic_argument %}

  // Get variadic arguments.
{% if optional_arguments|length %}
  const size_t kLastOptionalArgIndex = {{
      non_optional_arguments|length + optional_arguments|length}};
  if (num_set_arguments == kLastOptionalArgIndex) {
    // If the last optional argument has been set, we will call the overload
    // that takes the variadic argument, possibly with an empty vector in the
    // case that there are no more arguments left.
    ++num_set_arguments;
  }
{% endif %}
  const size_t kFirstVariadicArgIndex = {{operation.arguments|length - 1}};
  if (info.Length() > kFirstVariadicArgIndex) {
    {{variadic_argument.name}}.resize(info.Length() - kFirstVariadicArgIndex);
    for (int i = 0; i + kFirstVariadicArgIndex < info.Length(); ++i) {
      v8::Local<v8::Value> variadic_argument_value{{i}} = info[i + kFirstVariadicArgIndex];
      FromJSValue(isolate,
                  variadic_argument_value{{i}},
                  {{variadic_argument.conversion_flags}},
                  &exception_state,
                  &{{variadic_argument.name}}[i]);
      if (exception_state.is_exception_set()) {
        return;
      }
    }
  }
{% endif -%}

{# Call the implementation function, based on the number of set arguments. #}
{% if has_non_default_optional_arguments %}
  switch (num_set_arguments) {
{% for num_arguments in range(
    non_optional_arguments|length + num_default_arguments,
    operation.arguments|length + 1) %}
{# If no variadic arguments have been set, we still call the function with
   signature that has the variadic argument and pass an empty vector. There is
   no such function signature that takes the optional parameter immediately
   preceeding the variadic argument but does not take the variadic arguments. #}
{% if loop.last or not operation.arguments[num_arguments].is_variadic %}
{% set function_arguments =
      operation.arguments[0:num_arguments]|map(attribute='name')|list %}
    case {{num_arguments}}:
      {
        {{- caller(function_arguments)|indent(8, false) }}
      }
      break;
{% endif %}
{% endfor %}
    default:
      NOTREACHED();
      return;
  }
{% else %} {#- has_non_default_optional_arguments #}
{% set function_arguments = operation.arguments|map(attribute='name')|list %}
  {# whitespace control block #}
  {{-caller(function_arguments)}}
{% endif %}
{% endmacro %}

{#
 # Append extra arguments that should be passed to a cobalt function.
 # Specifically, this will prepend parameters specified on IDLs using the
 # [CallWith=] extended attribute.
 # Parameters:
 #     arguments_list: A list of C++ expressions that represent a sequence of
 #         arguments that will be passed to a function.
 #     context: An IDL object that may have the extended attribute that
 #         we are interested in.
 # Passed to caller:
 #     arguments_list, possibly with extra arguments prepended and appended.
 #}
{% macro add_extra_arguments(arguments_list, raises_exception, call_with) %}
{% if call_with %}
  V8cGlobalEnvironment* callwith_global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
{% do arguments_list.insert(
    0, 'callwith_global_environment->Get%s()'|format(call_with)) %}
{% endif %}
{% do arguments_list.append('&exception_state') if raises_exception %}
{%- endmacro %}

{% macro call_nonvoid_function(return_type, function_name, arguments,
                               impl_class, is_static) %}
  if (!exception_state.is_exception_set()) {
{% if not is_static %}
    ToJSValue(isolate,
              impl->{{function_name}}({{arguments|join(", ")}}),
              &result_value);
{% else %}
    ToJSValue(isolate,
              {{impl_class}}::{{function_name}}({{arguments|join(', ')}}),
              &result_value);
{% endif %}
  }
{%- endmacro %}

{% macro call_void_function(function_name, arguments, impl_class, is_static,
                            cobalt_impl_prefix) %}
{% if not is_static %}
  {{cobalt_impl_prefix}}impl->{{function_name}}({{arguments|join(", ")}});
{% else %}
  {{impl_class}}::{{function_name}}({{arguments|join(', ')}});
{% endif %}
  result_value = v8::Undefined(isolate);
{%- endmacro %}

{% macro get_impl_class_instance(impl_class) %}
  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  {{impl_class}}* impl =
      wrapper_private->wrappable<{{impl_class}}>().get();
{%- endmacro %}

{% macro static_function_prologue() %}
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;
{% endmacro %}

{% macro nonstatic_function_prologue(impl_class) %}
{{ static_function_prologue() }}
{{ get_impl_class_instance(impl_class) }}
{%- endmacro %}

{#
 # Call a function on an instance of a Cobalt platform object.
 #}
{% macro call_cobalt_function(impl_class, cobalt_type, function_name, arguments,
                              raises_exception, call_with, is_static,
                              cobalt_impl_prefix) %}
{{ add_extra_arguments(arguments, raises_exception, call_with) }}
{% if cobalt_type == "void" %}
{{ call_void_function(function_name, arguments, impl_class, is_static,
                      cobalt_impl_prefix) -}}
{% else %}
{{ call_nonvoid_function(cobalt_type, function_name, arguments, impl_class,
                         is_static) -}}
{% endif %}
{% endmacro %}

{#
 # Function body for constructor bindings.
 # Parameters:
 #     constructor: The constructor context object
 #}
{% macro constructor_implementation(constructor) %}
  V8cExceptionState exception_state(isolate);
{% call(arguments_list) extract_arguments(constructor) %}
  if (!info.IsConstructCall()) {
    exception_state.SetSimpleException(script::kTypeError, "Illegal constructor");
    return;
  }
{{ add_extra_arguments(arguments_list, constructor.raises_exception,
                       constructor.call_with) }}
  scoped_refptr<{{impl_class}}> new_object =
      new {{impl_class}}({{arguments_list|join(', ')}});
{% if constructor.raises_exception %}
  // In case that an exception is thrown from constructor.
  if (exception_state.is_exception_set()) {
    return;
  }
{% endif %}
  v8::Local<v8::Value> result_value;
  ToJSValue(isolate, new_object, &result_value);
  DCHECK(result_value->IsObject());
  info.GetReturnValue().Set(result_value);
{%- endcall %}
{%- endmacro %}

{#
 # Function body for overload resolution function.
 # Parameters:
 #     overload_context: The overload context object.
 #     bound_function_prefix: The prefix of the function to be called on
 #         resolution. The overload index will be appended to this.
 #}
{% macro overload_resolution_implementation(
      overload_context, bound_function_prefix) %}
  v8::Isolate* isolate = info.GetIsolate();

  switch(info.Length()) {
{% for length, distinguishing_argument_index, resolution_tests in
       overload_context.overload_resolution_by_length %}
    case({{length}}): {
      // Overload resolution algorithm details found here:
      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
{# In the case there is only one resolution condition, we do not need the arg. #}
{% if resolution_tests|length > 1 %}
      v8::Local<v8::Value> arg = info[{{distinguishing_argument_index}}];
      V8cGlobalEnvironment* global_environment =
          V8cGlobalEnvironment::GetFromIsolate(isolate);
      WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
      v8::Local<v8::Object> object;
      if (arg->IsObject()) {
        object = arg->ToObject();
      }
{% endif %}
{% for test, overload in resolution_tests %}
      if ({{test("arg")}}) {
        {{bound_function_prefix}}{{overload.overload_index}}(
                  info);
        return;
      }
{% endfor %}
      break;
    }
{% endfor %}
  }
  // Invalid number of args
  // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
  // 4. If S is empty, then throw a TypeError.
  V8cExceptionState exception_state(isolate);
  exception_state.SetSimpleException(script::kInvalidNumberOfArguments);
  return;
{%- endmacro %}
