// 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.

// Teaches dart2js about the wrapping that is done by the Shadow DOM polyfill.
(function() {
  var ShadowDOMPolyfill = window.ShadowDOMPolyfill;
  if (!ShadowDOMPolyfill) return;

  if (navigator.userAgent.indexOf('(Dart)') !== -1) {
    console.error("ShadowDOMPolyfill polyfill was loaded in Dartium. This " +
        "will not work. This indicates that Dartium's Chrome version is " +
        "not compatible with this version of web_components.");
  }

  var needsConstructorFix = window.constructor === window.Window;

  // TODO(jmesserly): we need to wrap document somehow (a dart:html hook?)

  // dartNativeDispatchHooksTransformer is described on initHooks() in
  // sdk/lib/_internal/lib/native_helper.dart.
  if (typeof window.dartNativeDispatchHooksTransformer == 'undefined')
    window.dartNativeDispatchHooksTransformer = [];

  window.dartNativeDispatchHooksTransformer.push(function(hooks) {
    var NodeList = ShadowDOMPolyfill.wrappers.NodeList;
    var ShadowRoot = ShadowDOMPolyfill.wrappers.ShadowRoot;
    var unwrapIfNeeded = ShadowDOMPolyfill.unwrapIfNeeded;
    var originalGetTag = hooks.getTag;
    hooks.getTag = function getTag(obj) {
      // TODO(jmesserly): do we still need these?
      if (obj instanceof NodeList) return 'NodeList';
      if (obj instanceof ShadowRoot) return 'ShadowRoot';
      if (MutationRecord && (obj instanceof MutationRecord))
          return 'MutationRecord';
      if (MutationObserver && (obj instanceof MutationObserver))
          return 'MutationObserver';

      // TODO(jmesserly): this prevents incorrect interaction between ShadowDOM
      // and dart:html's <template> polyfill. Essentially, ShadowDOM is
      // polyfilling native template, but our Dart polyfill fails to detect this
      // because the unwrapped node is an HTMLUnknownElement, leading it to
      // think the node has no content.
      if (obj instanceof HTMLTemplateElement) return 'HTMLTemplateElement';

      var unwrapped = unwrapIfNeeded(obj);
      if (unwrapped && (needsConstructorFix || obj !== unwrapped)) {
        // Fix up class names for Firefox, or if using the minified polyfill.
        // dart2js prefers .constructor.name, but there are all kinds of cases
        // where this will give the wrong answer.
        var ctor = obj.constructor
        if (ctor === unwrapped.constructor) {
          var name = ctor._ShadowDOMPolyfill$cacheTag_;
          if (!name) {
            name = originalGetTag(unwrapped);
            ctor._ShadowDOMPolyfill$cacheTag_ = name;
          }
          return name;
        }

        obj = unwrapped;
      }
      return originalGetTag(obj);
    }
  });
})();

// Updates document.registerElement so Dart can see when Javascript custom
// elements are created, and wrap them to provide a Dart friendly API.
(function (doc) {
  var upgraders = {};
  var originalRegisterElement = doc.registerElement;
  if (!originalRegisterElement) {
    throw new Error('document.registerElement is not present.');
  }

  function registerElement(name, options) {
    var proto, extendsOption;
    if (options !== undefined) {
      proto = options.prototype;
    } else {
      proto = Object.create(HTMLElement.prototype);
      options = {protoptype: proto};
    }

    var original = proto.createdCallback;
    var newCallback = function() {
      original.call(this);
      var name = this.getAttribute('is') || this.localName;
      var upgrader = upgraders[name.toLowerCase()];
      if (upgrader) upgrader(this);
    };

    var descriptor = Object.getOwnPropertyDescriptor(proto, 'createdCallback');
    if (!descriptor || descriptor.writable) {
      proto.createdCallback = newCallback;
    } else if (descriptor.configurable) {
      descriptor['value'] = newCallback;
      Object.defineProperty(proto, 'createdCallback', descriptor);
    } else {
      console.error("Couldn't patch prototype to notify Dart when " + name +
          " elements are created. This can be fixed by making the " +
          "createdCallback in " + name + " a configurable property.");
    }
    return originalRegisterElement.call(this, name, options);
  }

  function registerDartTypeUpgrader(name, upgrader) {
    if (!upgrader) return;
    name = name.toLowerCase();
    var existing = upgraders[name];
    if (existing) {
      console.error('Already have a Dart type associated with ' + name);
      return;
    }
    upgraders[name] = upgrader;
  }

  doc._registerDartTypeUpgrader = registerDartTypeUpgrader;
  doc.registerElement = registerElement;
})(document);
