{#
 # Copyright 2016 The Cobalt Authors. 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() %}
  const JSClass* proto_class =
      {{binding_class}}::PrototypeClass(context);
  if (proto_class == JS_GetClass(object)) {
    // Simply returns true if the object is this class's prototype object.
    // There is no need to return any value due to the object is not a platform
    // object. The execution reaches here when Object.getOwnPropertyDescriptor
    // gets called on native object prototypes.
    return true;
  }

  MozjsGlobalEnvironment* global_environment =
      static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context));
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<{{impl_class}}>())) {
    MozjsExceptionState exception(context);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return false;
  }
{%- endmacro %}

{#
 # Function body for operation bindings.
 # Parameters:
 #     operation: The operation context object
 #}
{% macro function_implementation(operation) %}
  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
{% if operation.is_static %}
{{ static_function_prologue() }}
{% else %}
  // Compute the 'this' value.
  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
  // 'this' should be an object.
  JS::RootedObject object(context);
  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
    return false;
  }
  if (!JS_ValueToObject(context, this_value, &object)) {
    NOTREACHED();
    return false;
  }
{{ 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()) {
    args.rval().set(result_value);
  }
{% endif %}
  return !exception_state.is_exception_set();
{%- 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 false;
    }
    if (!exception_state.is_exception_set()) {
{{ set_attribute_implementation(attribute.put_forwards, attribute.type,
     "forwarded_" + cobalt_impl_prefix) -}}
    }
    return !exception_state.is_exception_set();
  } // End scope of {{attribute.type}} forwarded_{{cobalt_impl_prefix}}impl.
{% else %}
  TypeTraits<{{attribute.type}} >::ConversionType value;
  if (args.length() != 1) {
    NOTREACHED();
    return false;
  }
  FromJSValue(context, args[0], {{attribute.conversion_flags}}, &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return false;
  }
{{ call_cobalt_function(impl_class, "void",
                        attribute.setter_function_name,
                        ["value"], attribute.raises_exception,
                        attribute.call_with, attribute.is_static,
                        cobalt_impl_prefix) }}
  return !exception_state.is_exception_set();
{% 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 (args.length() < kMinArguments) {
    exception_state.SetSimpleException(script::kInvalidNumberOfArguments);
    return false;
  }
{% 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}}, args.length());
  JS::RootedValue non_optional_value{{loop.index0}}(
      context, args[{{loop.index0}}]);
  FromJSValue(context,
              non_optional_value{{loop.index0}},
              {{argument.conversion_flags}},
              &exception_state, &{{argument.name}});
  if (exception_state.is_exception_set()) {
    return false;
  }
{% endfor -%}
{% for argument in optional_arguments %}
{% if loop.first %}
  size_t num_set_arguments = {{
      non_optional_arguments|length + num_default_arguments}};
{% endif %}
  if (args.length() > {{loop.index0 + non_optional_arguments|length}}) {
    JS::RootedValue optional_value{{loop.index0}}(
        context, args[{{loop.index0 + non_optional_arguments|length}}]);
{% if argument.default_value %}
    if (!optional_value{{loop.index0}}.isUndefined()) {
{% else %}
    {
{% endif %}
      FromJSValue(context,
                  optional_value{{loop.index0}},
                  {{argument.conversion_flags}},
                  &exception_state,
                  &{{argument.name}});
    }
    if (exception_state.is_exception_set()) {
      return false;
    }
{% 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 (args.length() > kFirstVariadicArgIndex) {
    {{variadic_argument.name}}.resize(args.length() - kFirstVariadicArgIndex);
    for (int i = 0; i + kFirstVariadicArgIndex < args.length(); ++i) {
      JS::RootedValue variadic_argument_value{{i}}(
          context, args[i + kFirstVariadicArgIndex]);
      FromJSValue(context,
                  variadic_argument_value{{i}},
                  {{variadic_argument.conversion_flags}},
                  &exception_state,
                  &{{variadic_argument.name}}[i]);
      if (exception_state.is_exception_set()) {
        return false;
      }
    }
  }
{% 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 false;
  }
{% 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 %}
  MozjsGlobalEnvironment* callwith_global_environment =
      static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context));
{% 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(context,
              impl->{{function_name}}({{arguments|join(", ")}}),
              &result_value);
{% else %}
    ToJSValue(context,
              {{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.set(JS::UndefinedHandleValue);
{%- endmacro %}

{% macro get_impl_class_instance(impl_class) %}
  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromObject(context, object);
  {{impl_class}}* impl =
      wrapper_private->wrappable<{{impl_class}}>().get();
{%- endmacro %}

{% macro static_function_prologue() %}
  MozjsExceptionState exception_state(context);
  JS::RootedValue result_value(context);
{% 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) %}
  MozjsExceptionState exception_state(context);
  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
{% call(arguments_list) extract_arguments(constructor) %}
{{ 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 false;
  }
{% endif %}
  JS::RootedValue result_value(context);
  ToJSValue(context, new_object, &result_value);
  DCHECK(result_value.isObject());
  args.rval().setObject(result_value.toObject());
  return true;
{%- 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) %}
  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
  switch(argc) {
{% 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 don't need the arg. #}
{% if resolution_tests|length > 1 %}
      JS::RootedValue arg(context, args[{{distinguishing_argument_index}}]);
      MozjsGlobalEnvironment* global_environment =
          static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context));
      WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
      JS::RootedObject object(context);
      if (arg.isObject()) {
        object = JS::RootedObject(context, &arg.toObject());
      }
{% endif %}
{% for test, overload in resolution_tests %}
      if ({{test("arg")}}) {
        return {{bound_function_prefix}}{{overload.overload_index}}(
                  context, argc, vp);
      }
{% 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.
  MozjsExceptionState exception_state(context);
  exception_state.SetSimpleException(script::kInvalidNumberOfArguments);
  return false;
{%- endmacro %}
