# Copyright 2014 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.

"""Generate template contexts of dictionaries for both v8 bindings and
implementation classes that are used by blink's core/modules.
"""

import operator
from v8_globals import includes
import dart_types
from dart_utilities import DartUtilities


DICTIONARY_H_INCLUDES = frozenset([
    'bindings/core/v8/V8Binding.h',
    'platform/heap/Handle.h',
])

DICTIONARY_CPP_INCLUDES = frozenset([
    'bindings/common/ExceptionState.h',
    # FIXME: Remove this, http://crbug.com/321462
    'bindings/core/v8/Dictionary.h',
])


def setter_name_for_dictionary_member(member):
    return 'set%s' % DartUtilities.capitalize(member.name)


def has_method_name_for_dictionary_member(member):
    return 'has%s' % DartUtilities.capitalize(member.name)


def unwrap_nullable_if_needed(idl_type):
    if idl_type.is_nullable:
        return idl_type.inner_type
    return idl_type


# Context for Dart bindings

def dictionary_context(dictionary):
    includes.clear()
    includes.update(DICTIONARY_CPP_INCLUDES)
    return {
        'cpp_class': DartUtilities.cpp_name(dictionary),
        'header_includes': set(DICTIONARY_H_INCLUDES),
        'members': [member_context(member)
                    for member in sorted(dictionary.members,
                                         key=operator.attrgetter('name'))],
        'dart_class': dart_types.dart_type(dictionary.name),

    }


def member_context(member):
    idl_type = member.idl_type
    idl_type.add_includes_for_type()
    idl_type = unwrap_nullable_if_needed(idl_type)

    def default_values():
        if not member.default_value:
            return None, None
        if member.default_value.is_null:
            return None, 'v8::Null(isolate)'
        cpp_default_value = str(member.default_value)
        v8_default_value = idl_type.cpp_value_to_v8_value(
            cpp_value=cpp_default_value, isolate='isolate',
            creation_context='creationContext')
        return cpp_default_value, v8_default_value

    cpp_default_value, dart_default_value = default_values()

    dart_enum_expression = idl_type.enum_validation_expression
    if dart_enum_expression:
        dart_enum_expression = dart_enum_expression.format(param_name='string')

    return {
        'cpp_default_value': cpp_default_value,
        'cpp_type': idl_type.cpp_type,
        'cpp_value_to_dart_value': idl_type.cpp_value_to_dart_value(
            cpp_value='impl->%s()' % member.name,
            creation_context='creationContext',
            extended_attributes=member.extended_attributes),
        'enum_validation_expression': dart_enum_expression,
        'has_method_name': has_method_name_for_dictionary_member(member),
        'is_object': idl_type.name == 'Object',
        'name': member.name,
        'setter_name': setter_name_for_dictionary_member(member),
        'dart_default_value': dart_default_value,
    }


# Context for implementation classes

def dictionary_impl_context(dictionary, interfaces_info):
    includes.clear()
    header_includes = set(['platform/heap/Handle.h'])
    return {
        'header_includes': header_includes,
        'cpp_class': DartUtilities.cpp_name(dictionary),
        'members': [member_impl_context(member, interfaces_info,
                                        header_includes)
                    for member in dictionary.members],
    }


def member_impl_context(member, interfaces_info, header_includes):
    idl_type = unwrap_nullable_if_needed(member.idl_type)
    is_object = idl_type.name == 'Object'

    def getter_expression():
        if idl_type.impl_should_use_nullable_container:
            return 'm_%s.get()' % member.name
        return 'm_%s' % member.name

    def has_method_expression():
        if idl_type.impl_should_use_nullable_container or idl_type.is_enum or idl_type.is_string_type:
            return '!m_%s.isNull()' % member.name
        elif is_object:
            return '!(m_{0}.isEmpty() || m_{0}.isNull() || m_{0}.isUndefined())'.format(member.name)
        else:
            return 'm_%s' % member.name

    def member_cpp_type():
        member_cpp_type = idl_type.cpp_type_args(used_in_cpp_sequence=True)
        if idl_type.impl_should_use_nullable_container:
            return dart_types.cpp_template_type('Nullable', member_cpp_type)
        return member_cpp_type

    cpp_default_value = None
    if member.default_value and not member.default_value.is_null:
        cpp_default_value = str(member.default_value)

    header_includes.update(idl_type.impl_includes_for_type(interfaces_info))
    return {
        'cpp_default_value': cpp_default_value,
        'getter_expression': getter_expression(),
        'has_method_expression': has_method_expression(),
        'has_method_name': has_method_name_for_dictionary_member(member),
        'is_object': is_object,
        'is_traceable': (idl_type.is_garbage_collected or
                         idl_type.is_will_be_garbage_collected),
        'member_cpp_type': member_cpp_type(),
        'name': member.name,
        'rvalue_cpp_type': idl_type.cpp_type_args(used_as_rvalue_type=True),
        'setter_name': setter_name_for_dictionary_member(member),
    }
