#!/usr/bin/python
#
# Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
"""Generates sdk/lib/_blink/dartium/_blink_dartium.dart file."""

import os
from sets import Set
from generator import AnalyzeOperation, AnalyzeConstructor

# This is list of all methods with native c++ implementations
# If performing a dartium merge, the best practice is to comment out this list,
# ensure everything runs, and then uncomment this list which might possibly
# introduce breaking changes due to changes to these method signatures.
_js_custom_members = Set([
    'Document.createElement',
    'Element.id',
    'Element.tagName',
    'Element.className',
    'Element.setAttribute',
    'Element.getAttribute',
    # Consider adding this method so there is a fast path to access only
    # element children.
    # 'NonDocumentTypeChildNode.nextElementSibling',
    'Node.appendChild',  # actually not removed, just native implementation.
    'Node.cloneNode',
    'Node.insertBefore',
    'Node.lastChild',
    'Node.firstChild',
    'Node.parentElement',
    'Node.parentNode',
    'Node.childNodes',
    'Node.removeChild',
    'Node.contains',
    'Node.nextSibling',
    'Node.previousSibling',
    'ChildNode.remove',
    'Document.createTextNode',
    'Window.location',
    'Location.href',
    'Location.hash',
    'Node.querySelector',
    'HTMLElement.hidden',
    'HTMLElement.style',
    'Element.attributes',
    'Window.innerWidth',
    'NodeList.length',
    'NodeList.item',
    'ParentNode.children',
    'ParentNode.firstElementChild',
    'ParentNode.lastElementChild',
    'Event.target',
    'MouseEvent.clientY',
    'MouseEvent.clientX',
    'Node.nodeType',
    'Node.textContent',
    'HTMLCollection.length',
    'HTMLCollection.item',
    'Node.lastElementChild',
    'Node.firstElementChild',
    'HTMLElement_tabIndex',
    'Element.clientWidth',
    'Element.clientHeight',
    'Document.body',
    'Element.removeAttribute',
    'Element.getBoundingClientRect',
    'CSSStyleDeclaration.getPropertyValue',
    'CSSStyleDeclaration.setProperty',
    'CSSStyleDeclaration.__propertyQuery__',

    # TODO(jacobr): consider implementing these methods as well as they show
    # up in benchmarks for some sample applications.
    #'Document.createEvent',
    #'Document.initEvent',
    #'EventTarget.dispatchEvent',
])

# Uncomment out this line  to short circuited native methods and run all of
# dart:html through JS interop except for createElement which is slightly more
# tightly natively wired.
# _js_custom_members = Set([])

# Expose built-in methods support by an instance that is not shown in the IDL.
_additional_methods = {
    # Support propertyIsEnumerable (available on all objects only needed by
    # CSSStyleDeclaration decides if style property is supported (handling
    # camelcase and inject hyphens between camelcase).
    # Format of dictionary is 'operation name', arguments, returns value (True or False)
    'CSSStyleDeclaration': ('propertyIsEnumerable', 1, True),
}

HEADER = """/* Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
 * for details. All rights reserved. Use of this source code is governed by a
 * BSD-style license that can be found in the LICENSE file.
 *
 * DO NOT EDIT
 * Auto-generated _blink library.
 */
library dart.dom._blink;

import 'dart:async';
import 'dart:js' as js;
import 'dart:html' show DomException;
import 'dart:_internal' as internal;
// This is a place to put custom renames if we need them.
final resolverMap = {
};

dynamic resolver(String s) {
"""

END_RESOLVER = """
  // Failed to find it, check for custom renames
  dynamic obj = resolverMap[s];
  if (obj != null) return obj;
  throw("No such interface exposed in blink: ${s}");
}

"""

BLINK_UTILS = """
// _Utils native entry points
class Blink_Utils {
  static window() native "Utils_window";

  static forwardingPrint(message) native "Utils_forwardingPrint";

  static spawnDomUri(uri) native "Utils_spawnDomUri";

  static void spawnDomHelper(Function f, int replyTo) native "Utils_spawnDomHelper";

  static register(document, tag, customType, extendsTagName) native "Utils_register";

  // Below code sets up VMLibraryHooks for resolvePackageUri.
  static Uri resolvePackageUri(Uri packageUri) native "Utils_resolvePackageUri";
  static Future<Uri> _resolvePackageUriFuture(Uri packageUri) async {
      return resolvePackageUri(packageUri);
  }
  static void _setupHooks() {
    internal.VMLibraryHooks.resolvePackageUriFuture = _resolvePackageUriFuture;
  }

  // Defines an interceptor if there is an appropriate JavaScript prototype to define it on.
  // In any case, returns a typed JS wrapper compatible with dart:html and the new
  // typed JS Interop.
  static defineInterceptorCustomElement(jsObject, Type type) native "Utils_defineInterceptorCustomElement";
  static defineInterceptor(jsObject, Type type) native "Utils_defineInterceptor";
  static setInstanceInterceptor(o, Type type, {bool customElement: false}) native "Utils_setInstanceInterceptor";
  static setInstanceInterceptorCustomUpgrade(o) native "Utils_setInstanceInterceptorCustomUpgrade";

  // This method will throw if the element isn't actually a real Element.
  static initializeCustomElement(element) native "Utils_initializeCustomElement";
}

class Blink_DOMStringMap {
  // _DOMStringMap native entry  points
  static containsKey(_DOMStringMap, key) native "DOMStringMap_containsKey_Callback";

  static item(_DOMStringMap, key) native "DOMStringMap_item_Callback";

  static setItem(_DOMStringMap, key, value) native "DOMStringMap_setItem_Callback";

  static remove(_DOMStringMap, key) native "DOMStringMap_remove_Callback";

  static get_keys(_DOMStringMap) native "DOMStringMap_getKeys_Callback";
}

// Calls through JsNative but returns DomException instead of error strings.
class Stats {
  Stats(this.name) {
    counts = new Map<String, int>();
  }

  String name;
  Map<String, int> counts;
  clear() {
    counts.clear();
  }

  track(String v) {
    counts[v] = counts.putIfAbsent(v, ()=> 0) + 1;
  }
  toString() {
    StringBuffer sb = new StringBuffer();
    sb.write('================');
    sb.write('$name ${counts.length}');
    var keys = counts.keys.toList();
    keys.sort((a,b) => counts[b].compareTo(counts[a]));
    for (var key in keys) {
      print("$key => ${counts[key]}");
    }
    sb.write('---------------');
    sb.write('================');
    return sb;
  }
}

bool TRACK_STATS = true;
dumpStats() {
  print("------------ STATS ----------------");
  print(Blink_JsNative_DomException.getPropertyStats.toString()); 
  print(Blink_JsNative_DomException.setPropertyStats.toString());
  print(Blink_JsNative_DomException.callMethodStats.toString());
  print(Blink_JsNative_DomException.constructorStats.toString());
  print("-----------------------------------");
}

clearStats() {
  Blink_JsNative_DomException.getPropertyStats.clear();
  Blink_JsNative_DomException.setPropertyStats.clear();
  Blink_JsNative_DomException.callMethodStats.clear();  
  Blink_JsNative_DomException.constructorStats.clear();  
}

class Blink_JsNative_DomException {
  static var getPropertyStats = new Stats('get property');
  static var setPropertyStats = new Stats('set property');
  static var callMethodStats = new Stats('call method');
  static var constructorStats = new Stats('constructor');

  static var constructors = new Map<String, dynamic>();

  static getProperty(o, String name) {
    try {
      if (TRACK_STATS) getPropertyStats.track(name);
      return js.JsNative.getProperty(o, name);
    } catch (e) {
      // Re-throw any errors (returned as a string) as a DomException.
      throw new DomException.jsInterop(e);
    }
  }

  static propertyQuery(o, String name) {
    try {
      if (TRACK_STATS) getPropertyStats.track('__propertyQuery__');
      return js.JsNative.getProperty(o, name);
    } catch (e) {
      // Re-throw any errors (returned as a string) as a DomException.
      throw new DomException.jsInterop(e);
    }
  }

  static callConstructor0(String name) {
    try {
      if (TRACK_STATS) constructorStats.track(name);
      var constructor = constructors.putIfAbsent(name, () => js.context[name]);
      return js.JsNative.callConstructor0(constructor);
    } catch (e) {
      // Re-throw any errors (returned as a string) as a DomException.
      throw new DomException.jsInterop(e);
    }
  }

  static callConstructor(String name, List args) {
    try {
      if (TRACK_STATS) constructorStats.track(name);
      var constructor = constructors.putIfAbsent(name, () => js.context[name]);
      return js.JsNative.callConstructor(constructor, args);
    } catch (e) {
      // Re-throw any errors (returned as a string) as a DomException.
      throw new DomException.jsInterop(e);
    }
  }

  static setProperty(o, String name, value) {
    try {
      if (TRACK_STATS) setPropertyStats.track(name);
      return js.JsNative.setProperty(o, name, value);
    } catch (e) {
      // Re-throw any errors (returned as a string) as a DomException.
      throw new DomException.jsInterop(e);
    }
  }

  static callMethod(o, String method, List args) {
    try {
      if (TRACK_STATS) callMethodStats.track(method);
      return js.JsNative.callMethod(o, method, args);
    } catch (e) {
      // Re-throw any errors (returned as a string) as a DomException.
      throw new DomException.jsInterop(e);
    }
  }
}"""

CLASS_DEFINITION = """class Blink%s {
  static final instance = new Blink%s();

"""

CLASS_DEFINITION_EXTENDS = """class Blink%s extends Blink%s {
  static final instance = new Blink%s();

"""

#(interface_name)

#
CONSTRUCTOR_0 = [
    '  constructorCallback_0_()',
    ' => Blink_JsNative_DomException.callConstructor0("%s");\n\n',
    ' native "Blink_Constructor_%s";\n\n'
]

#(argument_count, arguments, interface_name, arguments)
CONSTRUCTOR_ARGS = [
    '  constructorCallback_%s_(%s)',
    ' => Blink_JsNative_DomException.callConstructor("%s", [%s]);\n\n',
    ' native "Blink_Constructor_Args_%s" /* %s */;\n\n'
]

#(attribute_name, attribute_name)
ATTRIBUTE_GETTER = [
    '  %s_Getter_(mthis)',
    ' => Blink_JsNative_DomException.getProperty(mthis /* %s */, "%s");\n\n',
    ' native "Blink_Getter_%s_%s";\n\n'
]

ATTRIBUTE_SETTER = [
    '  %s_Setter_(mthis, __arg_0)',
    ' => Blink_JsNative_DomException.setProperty(mthis /* %s */, "%s", __arg_0);\n\n',
    ' native "Blink_Setter_%s_%s";\n\n'
]

#(operation_name, operationName)
OPERATION_0 = [
    '  %s_Callback_0_(mthis)',
    ' => Blink_JsNative_DomException.callMethod(mthis /* %s */, "%s", []);\n\n',
    ' native "Blink_Operation_0_%s_%s";\n\n'
]

# getter, setter, deleter, propertyQuery code, and propertyIsEnumerable
OPERATION_1 = [
    '  $%s_Callback_1_(mthis, __arg_0)',
    ' => Blink_JsNative_DomException.callMethod(mthis /* %s */, "%s", [__arg_0]);\n\n',
    ' native "Blink_Operation_1_%s_%s";\n\n'
]

OPERATION_2 = [
    '  $%s_Callback_2_(mthis, __arg_0, __arg_1)',
    ' => Blink_JsNative_DomException.callMethod(mthis /* %s */, "%s", [__arg_0, __arg_1]);\n\n',
    ' native "Blink_Operation_2_%s_%s";\n\n'
]

OPERATION_PQ = [
    '  $%s_Callback_1_(mthis, __arg_0)',
    ' => Blink_JsNative_DomException.propertyQuery(mthis, __arg_0); /* %s */ \n\n',
    ' native "Blink_Operation_PQ_%s";\n\n'
]

#(operation_name, argument_count, arguments, operation_name, arguments)
ARGUMENT_NUM = "__arg_%s"
OPERATION_ARGS = [
    '  %s_Callback_%s_(mthis, %s)',
    ' => Blink_JsNative_DomException.callMethod(mthis /* %s */, "%s", [%s]);\n\n',
    ' native "Blink_Operation_%s_%s"; /* %s */\n\n'
]

# get class property to make static call.
CLASS_STATIC = 'Blink_JsNative_DomException.getProperty(js.context, "%s")'

# name, classname_getproperty, name
STATIC_ATTRIBUTE_GETTER = [
    '  %s_Getter_()',
    ' => Blink_JsNative_DomException.getProperty(%s /* %s */, "%s");\n\n',
    ' /* %s */ native "Blink_Static_getter_%s_%s"'
]

# name, classname_getproperty, name
STATIC_OPERATION_0 = [
    '  %s_Callback_0_()',
    ' => Blink_JsNative_DomException.callMethod(%s /* %s */, "%s", []);\n\n',
    ' /* %s */ native "Blink_Static_Operation_0_%s_%s'
]

# name, argsCount, args, classname_getproperty, name, args
STATIC_OPERATION_ARGS = [
    '  %s_Callback_%s_(%s)',
    ' => Blink_JsNative_DomException.callMethod(%s /* %s */, "%s", [%s]);\n\n',
    ' /* %s */ native "Blink_Static_Operations_%s_%s" /* %s */ \n\n'
]

CLASS_DEFINITION_END = """}

"""


def ConstantOutputOrder(a, b):
    """Canonical output ordering for constants."""
    return cmp(a.id, b.id)


def generate_parameter_entries(param_infos):
    optional_default_args = 0
    for argument in param_infos:
        if argument.is_optional:
            optional_default_args += 1

    arg_count = len(param_infos)
    min_arg_count = arg_count - optional_default_args
    lb = min_arg_count - 2 if min_arg_count > 2 else 0
    return (lb, arg_count + 1)


constructor_renames = {
    'RTCPeerConnection': 'webkitRTCPeerConnection',
    'SpeechRecognition': 'webkitSpeechRecognition',
}


def rename_constructor(name):
    return constructor_renames[name] if name in constructor_renames else name


def _Find_Match(interface_id, member, member_prefix, candidates):
    member_name = interface_id + '.' + member
    if member_name in candidates:
        return member_name
    member_name = interface_id + '.' + member_prefix + member
    if member_name in candidates:
        return member_name
    member_name = interface_id + '.*'
    if member_name in candidates:
        return member_name


def _Is_Native(interface, member):
    return _Find_Match(interface, member, '', _js_custom_members)


def Select_Stub(template, is_native):
    if is_native:
        return template[0] + template[2]
    else:
        return template[0] + template[1]


def Generate_Blink(output_dir, database, type_registry):
    blink_filename = os.path.join(output_dir, '_blink_dartium.dart')
    blink_file = open(blink_filename, 'w')

    blink_file.write(HEADER)

    interfaces = database.GetInterfaces()
    for interface in interfaces:
        name = interface.id
        resolver_entry = '  if (s == "%s") return Blink%s.instance;\n' % (name,
                                                                          name)
        blink_file.write(resolver_entry)

    blink_file.write(END_RESOLVER)

    for interface in interfaces:
        name = interface.id

        if interface.parents and len(
                interface.parents) > 0 and interface.parents[0].id:
            extends = interface.parents[0].id
            class_def = CLASS_DEFINITION_EXTENDS % (name, extends, name)
        else:
            class_def = CLASS_DEFINITION % (name, name)
        blink_file.write(class_def)

        analyzed_constructors = AnalyzeConstructor(interface)
        if analyzed_constructors:
            _Emit_Blink_Constructors(blink_file, analyzed_constructors)
        elif 'Constructor' in interface.ext_attrs:
            # Zero parameter constructor.
            blink_file.write(
                Select_Stub(CONSTRUCTOR_0, _Is_Native(name, 'constructor')) %
                rename_constructor(name))

        _Process_Attributes(blink_file, interface, interface.attributes)
        _Process_Operations(blink_file, interface, interface.operations, True)

        _Emit_Extra_Operations(blink_file, name)

        secondary_parents = database.TransitiveSecondaryParents(
            interface, False)
        for secondary in secondary_parents:
            _Process_Attributes(blink_file, secondary, secondary.attributes)
            _Process_Operations(blink_file, secondary, secondary.operations,
                                False)

        blink_file.write(CLASS_DEFINITION_END)

    blink_file.write(BLINK_UTILS)

    blink_file.close()


def _Emit_Extra_Operations(blink_file, interface_name):
    if (interface_name in _additional_methods):
        (name, arg_count, return_value) = _additional_methods[interface_name]
        exposed_name = ''.join(['__get', '___', name]) if return_value else name
        blink_file.write(
            Select_Stub(OPERATION_1, False) % (exposed_name, interface_name,
                                               name))


def _Emit_Blink_Constructors(blink_file, analyzed_constructors):
    (arg_min_count, arg_max_count) = generate_parameter_entries(
        analyzed_constructors.param_infos)
    name = analyzed_constructors.js_name
    if not (name):
        name = analyzed_constructors.type_name

    for callback_index in range(arg_min_count, arg_max_count):
        if callback_index == 0:
            blink_file.write(
                Select_Stub(CONSTRUCTOR_0, _Is_Native(name, 'constructor')) %
                (rename_constructor(name)))
        else:
            arguments = []
            for i in range(0, callback_index):
                arguments.append(ARGUMENT_NUM % i)
            argument_list = ', '.join(arguments)
            blink_file.write(
                Select_Stub(CONSTRUCTOR_ARGS, _Is_Native(name, 'constructor')) %
                (callback_index, argument_list, rename_constructor(name),
                 argument_list))


def _Process_Attributes(blink_file, interface, attributes):
    # Emit an interface's attributes and operations.
    for attribute in sorted(attributes, ConstantOutputOrder):
        name = attribute.id
        is_native = _Is_Native(interface.id, name)
        if attribute.is_read_only:
            if attribute.is_static:
                class_property = CLASS_STATIC % interface.id
                blink_file.write(
                    Select_Stub(STATIC_ATTRIBUTE_GETTER, is_native) %
                    (name, class_property, interface.id, name))
            else:
                blink_file.write(
                    Select_Stub(ATTRIBUTE_GETTER, is_native) %
                    (name, interface.id, name))
        else:
            blink_file.write(
                Select_Stub(ATTRIBUTE_GETTER, is_native) % (name, interface.id,
                                                            name))
            blink_file.write(
                Select_Stub(ATTRIBUTE_SETTER, is_native) % (name, interface.id,
                                                            name))


def _Process_Operations(blink_file,
                        interface,
                        operations,
                        primary_interface=False):
    analyzeOperations = []

    for operation in sorted(operations, ConstantOutputOrder):
        if len(analyzeOperations) == 0:
            analyzeOperations.append(operation)
        else:
            if analyzeOperations[0].id == operation.id:
                # Handle overloads
                analyzeOperations.append(operation)
            else:
                _Emit_Blink_Operation(blink_file, interface, analyzeOperations,
                                      primary_interface)
                analyzeOperations = [operation]
    if len(analyzeOperations) > 0:
        _Emit_Blink_Operation(blink_file, interface, analyzeOperations,
                              primary_interface)


# List of DartName operations to not emit (e.g., For now only WebGL2RenderingContextBase
# has readPixels in both WebGLRenderingContextBase and WebGL2RenderingContextBase.
# Furthermore, readPixels has the exact same number of arguments - in Javascript
# there is no typing so they're the same.
suppressed_operations = {
    'WebGL2RenderingContextBase': ['readPixels2', 'texImage2D2'],
}


def _Suppress_Secondary_Interface_Operation(interface, analyzed):
    if interface.id in suppressed_operations:
        # Should this DartName (name property) be suppressed on this interface?
        return analyzed.name in suppressed_operations[interface.id]
    return False


def _Emit_Blink_Operation(blink_file, interface, analyzeOperations,
                          primary_interface):
    analyzed = AnalyzeOperation(interface, analyzeOperations)

    if not (primary_interface) and _Suppress_Secondary_Interface_Operation(
            interface, analyzed):
        return

    (arg_min_count,
     arg_max_count) = generate_parameter_entries(analyzed.param_infos)
    name = analyzed.js_name

    is_native = _Is_Native(interface.id, name)

    operation = analyzeOperations[0]
    if (name.startswith('__') and \
        ('getter' in operation.specials or \
         'setter' in operation.specials or \
         'deleter' in operation.specials)):
        if name == '__propertyQuery__':
            blink_file.write(
                Select_Stub(OPERATION_PQ, is_native) % (name, interface.id))
        else:
            arg_min_count = arg_max_count
            if arg_max_count == 2:
                blink_file.write(
                    Select_Stub(OPERATION_1, is_native) % (name, interface.id,
                                                           name))
            elif arg_max_count == 3:
                blink_file.write(
                    Select_Stub(OPERATION_2, is_native) % (name, interface.id,
                                                           name))
            else:
                print "FATAL ERROR: _blink emitter operator %s.%s" % (
                    interface.id, name)
                exit

        return

    for callback_index in range(arg_min_count, arg_max_count):
        if callback_index == 0:
            if operation.is_static:
                class_property = CLASS_STATIC % interface.id
                blink_file.write(
                    Select_Stub(STATIC_OPERATION_0, is_native) %
                    (name, class_property, interface.id, name))
            else:
                blink_file.write(
                    Select_Stub(OPERATION_0, is_native) % (name, interface.id,
                                                           name))
        else:
            arguments = []
            for i in range(0, callback_index):
                arguments.append(ARGUMENT_NUM % i)
            argument_list = ', '.join(arguments)
            if operation.is_static:
                class_property = CLASS_STATIC % interface.id
                blink_file.write(
                    Select_Stub(STATIC_OPERATION_ARGS, is_native) %
                    (name, callback_index, argument_list, class_property,
                     interface.id, name, argument_list))
            else:
                blink_file.write(
                    Select_Stub(OPERATION_ARGS, is_native) %
                    (name, callback_index, argument_list, interface.id, name,
                     argument_list))
