// Copyright (c) 2013, 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.

/**
 * Custom DOM elements.
 *
 * This library provides access to the Polymer project's
 * [Custom Elements]
 * (http://www.polymer-project.org/platform/custom-elements.html)
 * API, which lets you define your own elements. With custom elements, you
 * associate code with custom tag names, and then use those custom tag names
 * as you would any standard tag. For more information, see the
 * [Polymer.dart homepage](https://www.dartlang.org/polymer-dart/) and its
 * [custom element example]
 * (https://www.dartlang.org/polymer-dart/#custom-elements).
 */
library custom_element;

import 'dart:html';
import 'dart:async';

/**
 * *Deprecated* -- do not use. Extend [HtmlElement] and use
 * [document.register] instead. If running on a browser without native
 * document.register, you can add the polyfill script to your page:
 *
 *     <script src="packages/custom_element/custom-elements.debug.js"></script>
 *
 * You can also use "custom-elements.min.js" for the minified version.
 */
// This is only used by Dart Web UI.
class CustomElement implements Element {
  /** The web component element wrapped by this class. */
  Element _host;
  List _shadowRoots;

  /**
   * Shadow roots generated by dwc for each custom element, indexed by the
   * custom element tag name.
   */
  Map<String, dynamic> _generatedRoots = {};

  /**
   * Temporary property until components extend [Element]. An element can
   * only be associated with one host, and it is an error to use a web component
   * without an associated host element.
   */
  Element get host {
    if (_host == null) throw new StateError('host element has not been set.');
    return _host;
  }

  set host(Element value) {
    if (value == null) {
      throw new ArgumentError('host must not be null.');
    }
    // TODO(jmesserly): xtag used to return "null" if unset, now it checks for
    // "this". Temporarily allow both.
    var xtag = value.xtag;
    if (xtag != null && xtag != value) {
      throw new ArgumentError('host must not have its xtag property set.');
    }
    if (_host != null) {
      throw new StateError('host can only be set once.');
    }

    value.xtag = this;
    _host = value;
  }

  /**
   * **Note**: This is an implementation helper and should not need to be called
   * from your code.
   *
   * Creates the [ShadowRoot] backing this component.
   */
  createShadowRoot([String componentName]) {
    var root = host.createShadowRoot();
    if (componentName != null) {
      _generatedRoots[componentName] = root;
    }
    return root;
  }

  getShadowRoot(String componentName) => _generatedRoots[componentName];

  /**
   * Invoked when this component gets created.
   * Note that [root] will be a [ShadowRoot] if the browser supports Shadow DOM.
   */
  void created() {}
  // Added for analyzer warnings
  @deprecated
  void createdCallback() {}

  /** Invoked when this component gets inserted in the DOM tree. */
  void inserted() {}
  @deprecated
  void enteredView() {}
  @deprecated
  void attached() {}

  /** Invoked when this component is removed from the DOM tree. */
  void removed() {}
  @deprecated
  void leftView() {}
  @deprecated
  void detached() {}

  /** Invoked when any attribute of the component is modified. */
  void attributeChanged(String name, String oldValue, String newValue) =>
      host.attributeChanged(name, oldValue, newValue);

  // TODO(efortuna): Update these when we decide what to do with these
  // properties.
  @deprecated
  String getAttribute(String name) =>
      host.getAttribute(name);

  @deprecated
  String getAttributeNS(String namespaceUri, String localName) =>
      host.getAttributeNS(namespaceUri, localName);

  @deprecated
  void setAttributeNS(
      String namespaceUri, String localName, String value) {
    host.setAttributeNS(namespaceUri, localName, value);
  }

  @deprecated
  void setAttribute(String name, String value) =>
      host.setAttribute(name, value);

  @deprecated
  List<Node> get childNodes => host.childNodes;

  // TODO(jmesserly): this forwarding is temporary until Dart supports
  // subclassing Elements.
  // TODO(jmesserly): we were missing the setter for title, are other things
  // missing setters?

  List<Node> get nodes => host.nodes;

  set nodes(Iterable<Node> value) { host.nodes = value; }

  /**
   * Replaces this node with another node.
   */
  Node replaceWith(Node otherNode) => host.replaceWith(otherNode);

  /**
   * Removes this node from the DOM.
   */
  void remove() => host.remove();

  Node get nextNode => host.nextNode;

  String get nodeName => host.nodeName;

  Document get ownerDocument => host.ownerDocument;

  Node get previousNode => host.previousNode;

  String get text => host.text;

  set text(String v) { host.text = v; }

  bool contains(Node other) => host.contains(other);

  bool hasChildNodes() => host.hasChildNodes();

  Node insertBefore(Node newChild, Node refChild) =>
    host.insertBefore(newChild, refChild);

  Node insertAllBefore(Iterable<Node> newChild, Node refChild) =>
    host.insertAllBefore(newChild, refChild);

  Map<String, String> get attributes => host.attributes;
  set attributes(Map<String, String> value) {
    host.attributes = value;
  }

  List<Element> get elements => host.children;

  set elements(List<Element> value) {
    host.children = value;
  }

  String get baseUri => host.baseUri;

  List<Element> get children => host.children;

  set children(List<Element> value) {
    host.children = value;
  }

  Set<String> get classes => host.classes;

  set classes(Iterable<String> value) {
    host.classes = value;
  }

  CssRect get contentEdge => host.contentEdge;
  CssRect get paddingEdge => host.paddingEdge;
  CssRect get borderEdge => host.borderEdge;
  CssRect get marginEdge => host.marginEdge;
  Point get documentOffset => host.documentOffset;
  Point offsetTo(Element parent) => host.offsetTo(parent);

  Map<String, String> getNamespacedAttributes(String namespace) =>
      host.getNamespacedAttributes(namespace);

  CssStyleDeclaration getComputedStyle([String pseudoElement])
    => host.getComputedStyle(pseudoElement);

  Element clone(bool deep) => host.clone(deep);

  Element get parent => host.parent;

  Node get parentNode => host.parentNode;

  String get nodeValue => host.nodeValue;

  Events get on => host.on;

  String get contentEditable => host.contentEditable;
  set contentEditable(String v) { host.contentEditable = v; }

  String get dir => host.dir;
  set dir(String v) { host.dir = v; }

  bool get draggable => host.draggable;
  set draggable(bool v) { host.draggable = v; }

  bool get hidden => host.hidden;
  set hidden(bool v) { host.hidden = v; }

  String get id => host.id;
  set id(String v) { host.id = v; }

  String get innerHtml => host.innerHtml;
  void set innerHtml(String v) {
    host.innerHtml = v;
  }

  void setInnerHtml(String html,
    {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
    host.setInnerHtml(html, validator: validator, treeSanitizer: treeSanitizer);
  }

  DocumentFragment createFragment(String html,
      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) =>
    host.createFragment(html,
        validator: validator, treeSanitizer: treeSanitizer);

  bool get isContentEditable => host.isContentEditable;

  String get lang => host.lang;
  set lang(String v) { host.lang = v; }

  String get outerHtml => host.outerHtml;

  bool get spellcheck => host.spellcheck;
  set spellcheck(bool v) { host.spellcheck = v; }

  int get tabIndex => host.tabIndex;
  set tabIndex(int i) { host.tabIndex = i; }

  String get title => host.title;

  set title(String value) { host.title = value; }

  bool get translate => host.translate;
  set translate(bool v) { host.translate = v; }

  String get dropzone => host.dropzone;
  set dropzone(String v) { host.dropzone = v; }

  void click() { host.click(); }

  List<Node> getDestinationInsertionPoints() =>
    host.getDestinationInsertionPoints();

  Element insertAdjacentElement(String where, Element element) =>
    host.insertAdjacentElement(where, element);

  void insertAdjacentHtml(String where, String html) {
    host.insertAdjacentHtml(where, html);
  }

  void insertAdjacentText(String where, String text) {
    host.insertAdjacentText(where, text);
  }

  Map<String, String> get dataset => host.dataset;

  set dataset(Map<String, String> value) {
    host.dataset = value;
  }

  Element get nextElementSibling => host.nextElementSibling;

  Element get offsetParent => host.offsetParent;

  Element get previousElementSibling => host.previousElementSibling;

  CssStyleDeclaration get style => host.style;

  String get tagName => host.tagName;

  // Note: we are not polyfilling the shadow root here. This will be fixed when
  // we migrate to the JS Shadow DOM polyfills. You can still use getShadowRoot
  // to retrieve a node that behaves as the shadow root when Shadow DOM is not
  // enabled.
  ShadowRoot get shadowRoot => host.shadowRoot;

  void blur() { host.blur(); }

  void focus() { host.focus(); }

  void scrollByLines(int lines) {
    host.scrollByLines(lines);
  }

  void scrollByPages(int pages) {
    host.scrollByPages(pages);
  }

  void scrollIntoView([ScrollAlignment alignment]) {
    host.scrollIntoView(alignment);
  }

  bool matches(String selectors) => host.matches(selectors);

  bool matchesWithAncestors(String selectors) =>
      host.matchesWithAncestors(selectors);

  @deprecated
  void requestFullScreen(int flags) { requestFullscreen(); }

  void requestFullscreen() { host.requestFullscreen(); }

  void requestPointerLock() { host.requestPointerLock(); }

  Element querySelector(String selectors) => host.querySelector(selectors);

  ElementList querySelectorAll(String selectors) =>
      host.querySelectorAll(selectors);

  @deprecated
  Element query(String selectors) => host.querySelector(selectors);

  @deprecated
  ElementList queryAll(String selectors) => host.querySelectorAll(selectors);

  String get className => host.className;
  set className(String value) { host.className = value; }

  @deprecated
  int get clientHeight => client.height;

  @deprecated
  int get clientLeft => client.left;

  @deprecated
  int get clientTop => client.top;

  @deprecated
  int get clientWidth => client.width;

  Rectangle get client => host.client;

  @deprecated
  int get offsetHeight => offset.height;

  @deprecated
  int get offsetLeft => offset.left;

  @deprecated
  int get offsetTop => offset.top;

  @deprecated
  int get offsetWidth => offset.width;

  Rectangle get offset => host.offset;

  int get scrollHeight => host.scrollHeight;

  int get scrollLeft => host.scrollLeft;

  int get scrollTop => host.scrollTop;

  set scrollLeft(int value) { host.scrollLeft = value; }

  set scrollTop(int value) { host.scrollTop = value; }

  int get scrollWidth => host.scrollWidth;

  Rectangle getBoundingClientRect() => host.getBoundingClientRect();

  List<Rectangle> getClientRects() => host.getClientRects();

  List<Node> getElementsByClassName(String name) =>
      host.getElementsByClassName(name);

  Node get firstChild => host.firstChild;

  Node get lastChild => host.lastChild;

  String get localName => host.localName;

  String get namespaceUri => host.namespaceUri;

  int get nodeType => host.nodeType;

  void addEventListener(String type, EventListener listener,
      [bool useCapture]) {
    host.addEventListener(type, listener, useCapture);
  }

  bool dispatchEvent(Event event) => host.dispatchEvent(event);

  void removeEventListener(String type, EventListener listener,
      [bool useCapture]) {
    host.removeEventListener(type, listener, useCapture);
  }

  get xtag => host.xtag;

  set xtag(value) { host.xtag = value; }

  Node append(Node e) => host.append(e);

  void appendText(String text) => host.appendText(text);

  void appendHtml(String html) => host.appendHtml(html);

  Animation animate(List<Map> keyframes, [num duration]) =>
      host.animate(keyframes, duration);

  // TODO(jmesserly): rename "created" to "onCreated".
  void onCreated() => created();

  Stream<Event> get onAbort => host.onAbort;
  Stream<Event> get onBeforeCopy => host.onBeforeCopy;
  Stream<Event> get onBeforeCut => host.onBeforeCut;
  Stream<Event> get onBeforePaste => host.onBeforePaste;
  Stream<Event> get onBlur => host.onBlur;
  Stream<Event> get onChange => host.onChange;
  Stream<MouseEvent> get onClick => host.onClick;
  Stream<MouseEvent> get onContextMenu => host.onContextMenu;
  Stream<Event> get onCopy => host.onCopy;
  Stream<Event> get onCut => host.onCut;
  Stream<Event> get onDoubleClick => host.onDoubleClick;
  Stream<MouseEvent> get onDrag => host.onDrag;
  Stream<MouseEvent> get onDragEnd => host.onDragEnd;
  Stream<MouseEvent> get onDragEnter => host.onDragEnter;
  Stream<MouseEvent> get onDragLeave => host.onDragLeave;
  Stream<MouseEvent> get onDragOver => host.onDragOver;
  Stream<MouseEvent> get onDragStart => host.onDragStart;
  Stream<MouseEvent> get onDrop => host.onDrop;
  Stream<Event> get onError => host.onError;
  Stream<Event> get onFocus => host.onFocus;
  Stream<Event> get onInput => host.onInput;
  Stream<Event> get onInvalid => host.onInvalid;
  Stream<KeyboardEvent> get onKeyDown => host.onKeyDown;
  Stream<KeyboardEvent> get onKeyPress => host.onKeyPress;
  Stream<KeyboardEvent> get onKeyUp => host.onKeyUp;
  Stream<Event> get onLoad => host.onLoad;
  Stream<MouseEvent> get onMouseDown => host.onMouseDown;
  Stream<MouseEvent> get onMouseEnter => host.onMouseEnter;
  Stream<MouseEvent> get onMouseLeave => host.onMouseLeave;
  Stream<MouseEvent> get onMouseMove => host.onMouseMove;
  Stream<Event> get onFullscreenChange => host.onFullscreenChange;
  Stream<Event> get onFullscreenError => host.onFullscreenError;
  Stream<Event> get onPaste => host.onPaste;
  Stream<Event> get onReset => host.onReset;
  Stream<Event> get onResize => host.onResize;
  Stream<Event> get onScroll => host.onScroll;
  Stream<Event> get onSearch => host.onSearch;
  Stream<Event> get onSelect => host.onSelect;
  Stream<Event> get onSelectStart => host.onSelectStart;
  Stream<Event> get onSubmit => host.onSubmit;
  Stream<MouseEvent> get onMouseOut => host.onMouseOut;
  Stream<MouseEvent> get onMouseOver => host.onMouseOver;
  Stream<MouseEvent> get onMouseUp => host.onMouseUp;
  Stream<TouchEvent> get onTouchCancel => host.onTouchCancel;
  Stream<TouchEvent> get onTouchEnd => host.onTouchEnd;
  Stream<TouchEvent> get onTouchEnter => host.onTouchEnter;
  Stream<TouchEvent> get onTouchLeave => host.onTouchLeave;
  Stream<TouchEvent> get onTouchMove => host.onTouchMove;
  Stream<TouchEvent> get onTouchStart => host.onTouchStart;
  Stream<TransitionEvent> get onTransitionEnd => host.onTransitionEnd;

  // TODO(sigmund): do the normal forwarding when dartbug.com/7919 is fixed.
  Stream<WheelEvent> get onMouseWheel {
    throw new UnsupportedError('onMouseWheel is not supported');
  }
}
