/*
 * Copyright 2008 Google Inc.
 * 
 * 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.
 */
package com.google.gwt.dom.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;

abstract class DOMImpl {

  static final DOMImpl impl = GWT.create(DOMImpl.class);

  /**
   * Fast helper method to convert small doubles to 32-bit int.
   *
   * <p>Note: you should be aware that this uses JavaScript rounding and thus
   * does NOT provide the same semantics as <code>int b = (int) someDouble;</code>.
   * In particular, if x is outside the range [-2^31,2^31), then toInt32(x) would return a value
   * equivalent to x modulo 2^32, whereas (int) x would evaluate to either MIN_INT or MAX_INT.
   */
  protected static native int toInt32(double val) /*-{
    return val | 0;
  }-*/;

  public native void buttonClick(ButtonElement button) /*-{
    button.click();
  }-*/;

  public native ButtonElement createButtonElement(Document doc, String type) /*-{
    var e = doc.createElement("BUTTON");
    e.type = type;
    return e;
  }-*/;

  public native InputElement createCheckInputElement(Document doc) /*-{
    var e = doc.createElement("INPUT");
    e.type = 'checkbox';
    e.value = 'on';
    return e;
  }-*/;

  public native Element createElement(Document doc, String tag) /*-{
    return doc.createElement(tag);
  }-*/;

  public abstract NativeEvent createHtmlEvent(Document doc, String type,
      boolean canBubble, boolean cancelable);

  public native InputElement createInputElement(Document doc, String type) /*-{
    var e = doc.createElement("INPUT");
    e.type = type;
    return e;
  }-*/;

  public abstract InputElement createInputRadioElement(Document doc, String name);

  public abstract NativeEvent createKeyCodeEvent(Document document,
      String type, boolean ctrlKey, boolean altKey, boolean shiftKey,
      boolean metaKey, int keyCode);

  @Deprecated
  public abstract NativeEvent createKeyEvent(Document doc, String type,
      boolean canBubble, boolean cancelable, boolean ctrlKey, boolean altKey,
      boolean shiftKey, boolean metaKey, int keyCode, int charCode);

  public abstract NativeEvent createKeyPressEvent(Document document,
      boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey,
      int charCode);

  public abstract NativeEvent createMouseEvent(Document doc, String type,
      boolean canBubble, boolean cancelable, int detail, int screenX,
      int screenY, int clientX, int clientY, boolean ctrlKey, boolean altKey,
      boolean shiftKey, boolean metaKey, int button, Element relatedTarget);

  public ScriptElement createScriptElement(Document doc, String source) {
    ScriptElement elem = (ScriptElement) createElement(doc, "script");
    elem.setText(source);
    return elem;
  }

  public native void cssClearOpacity(Style style) /*-{
    style.opacity = '';
  }-*/;

  public String cssFloatPropertyName() {
    return "cssFloat";
  }

  public native void cssSetOpacity(Style style, double value) /*-{
    style.opacity = value;
  }-*/;

  public abstract void dispatchEvent(Element target, NativeEvent evt);

  public native boolean eventGetAltKey(NativeEvent evt) /*-{
    return !!evt.altKey;
  }-*/;

  public native int eventGetButton(NativeEvent evt) /*-{
    return evt.button | 0;
  }-*/;

  public abstract int eventGetCharCode(NativeEvent evt);

  public int eventGetClientX(NativeEvent evt) {
    return toInt32(eventGetSubPixelClientX(evt));
  }

  public int eventGetClientY(NativeEvent evt) {
    return toInt32(eventGetSubPixelClientY(evt));
  }

  public native boolean eventGetCtrlKey(NativeEvent evt) /*-{
    return !!evt.ctrlKey;
  }-*/;

  public native EventTarget eventGetCurrentTarget(NativeEvent event) /*-{
    return event.currentTarget;
  }-*/;

  public final native int eventGetKeyCode(NativeEvent evt) /*-{
    return evt.keyCode | 0;
  }-*/;

  public native boolean eventGetMetaKey(NativeEvent evt) /*-{
    return !!evt.metaKey;
  }-*/;

  public abstract int eventGetMouseWheelVelocityY(NativeEvent evt);

  public abstract EventTarget eventGetRelatedTarget(NativeEvent nativeEvent);

  public native double eventGetRotation(NativeEvent evt) /*-{
    return evt.rotation;
  }-*/;

  public native double eventGetScale(NativeEvent evt) /*-{
    return evt.scale;
  }-*/;

  public int eventGetScreenX(NativeEvent evt) {
    return toInt32(eventGetSubPixelScreenX(evt));
  }

  public int eventGetScreenY(NativeEvent evt) {
    return toInt32(eventGetSubPixelScreenY(evt));
  }

  public native boolean eventGetShiftKey(NativeEvent evt) /*-{
    return !!evt.shiftKey;
  }-*/;

  public abstract EventTarget eventGetTarget(NativeEvent evt);

  public final native String eventGetType(NativeEvent evt) /*-{
    return evt.type;
  }-*/;

  public abstract void eventPreventDefault(NativeEvent evt);

  public native void eventSetKeyCode(NativeEvent evt, char key) /*-{
    evt.keyCode = key;
  }-*/;

  public native void eventStopPropagation(NativeEvent evt) /*-{
    evt.stopPropagation();
  }-*/;

  public abstract String eventToString(NativeEvent evt);

  public int getAbsoluteLeft(Element elem) {
    return toInt32(getSubPixelAbsoluteLeft(elem));
  }

  public int getAbsoluteTop(Element elem) {
    return toInt32(getSubPixelAbsoluteTop(elem));
  }

  public native String getAttribute(Element elem, String name) /*-{
    return elem.getAttribute(name) || '';
  }-*/;

  public native int getBodyOffsetLeft(Document doc) /*-{
    return 0;
  }-*/;

  public native int getBodyOffsetTop(Document doc) /*-{
    return 0;
  }-*/;

  public native JsArray<Touch> getChangedTouches(NativeEvent evt) /*-{
    return evt.changedTouches;
  }-*/;

  public native Element getFirstChildElement(Element elem) /*-{
    var child = elem.firstChild;
    while (child && child.nodeType != 1)
      child = child.nextSibling;
    return child;
  }-*/;

  public native String getInnerHTML(Element elem) /*-{
    return elem.innerHTML;
  }-*/;

  public native String getInnerText(Element node) /*-{
    // To mimic IE's 'innerText' property in the W3C DOM, we need to recursively
    // concatenate all child text nodes (depth first).
    var text = '', child = node.firstChild;
    while (child) {
      // 1 == Element node
      if (child.nodeType == 1) {
        text += this.@com.google.gwt.dom.client.DOMImpl::getInnerText(Lcom/google/gwt/dom/client/Element;)(child);
      } else if (child.nodeValue) {
        text += child.nodeValue;
      }
      child = child.nextSibling;
    }
    return text;
  }-*/;

  public native Element getNextSiblingElement(Element elem) /*-{
    var sib = elem.nextSibling;
    while (sib && sib.nodeType != 1)
      sib = sib.nextSibling;
    return sib;
  }-*/;

  public native int getNodeType(Node node) /*-{
    return node.nodeType;
  }-*/;

  /**
   * Returns a numeric style property (such as zIndex) that may need to be
   * coerced to a string.
   */
  public String getNumericStyleProperty(Style style, String name) {
    return getStyleProperty(style, name);
  }

  public native Element getParentElement(Node node) /*-{
    var parent = node.parentNode;
    if (!parent || parent.nodeType != 1) {
      parent = null;
    }
    return parent;
  }-*/;

  public native Element getPreviousSiblingElement(Element elem) /*-{
    var sib = elem.previousSibling;
    while (sib && sib.nodeType != 1)
      sib = sib.previousSibling;
    return sib;
  }-*/;

  public int getScrollLeft(Document doc) {
    return ensureDocumentScrollingElement(doc).getScrollLeft();
  }

  public int getScrollLeft(Element elem) {
    return toInt32(getSubPixelScrollLeft(elem));
  }

  public int getScrollTop(Document doc) {
    return ensureDocumentScrollingElement(doc).getScrollTop();
  }

  public native String getStyleProperty(Style style, String name) /*-{
    return style[name];
  }-*/;

  public native int getTabIndex(Element elem) /*-{
    return elem.tabIndex;
  }-*/;

  public native String getTagName(Element elem) /*-{
    return elem.tagName;
  }-*/;

  public native JsArray<Touch> getTargetTouches(NativeEvent evt) /*-{
    return evt.targetTouches;
  }-*/;

  public native JsArray<Touch> getTouches(NativeEvent evt) /*-{
    return evt.touches;
  }-*/;

  public native boolean hasAttribute(Element elem, String name) /*-{
    return elem.hasAttribute(name);
  }-*/;

  public abstract boolean isOrHasChild(Node parent, Node child);

  public native void scrollIntoView(Element elem) /*-{
    var left = elem.offsetLeft, top = elem.offsetTop;
    var width = elem.offsetWidth, height = elem.offsetHeight;

    if (elem.parentNode != elem.offsetParent) {
      left -= elem.parentNode.offsetLeft;
      top -= elem.parentNode.offsetTop;
    }

    var cur = elem.parentNode;
    while (cur && (cur.nodeType == 1)) {
      if (left < cur.scrollLeft) {
        cur.scrollLeft = left;
      }
      if (left + width > cur.scrollLeft + cur.clientWidth) {
        cur.scrollLeft = (left + width) - cur.clientWidth;
      }
      if (top < cur.scrollTop) {
        cur.scrollTop = top;
      }
      if (top + height > cur.scrollTop + cur.clientHeight) {
        cur.scrollTop = (top + height) - cur.clientHeight;
      }

      var offsetLeft = cur.offsetLeft, offsetTop = cur.offsetTop;
      if (cur.parentNode != cur.offsetParent) {
        offsetLeft -= cur.parentNode.offsetLeft;
        offsetTop -= cur.parentNode.offsetTop;
      }

      left += offsetLeft - cur.scrollLeft;
      top += offsetTop - cur.scrollTop;
      cur = cur.parentNode;
    }
  }-*/;

  public native void selectAdd(SelectElement select, OptionElement option,
      OptionElement before) /*-{
    select.add(option, before);
  }-*/;

  public native void selectClear(SelectElement select) /*-{
    select.options.length = 0;
  }-*/;

  public native int selectGetLength(SelectElement select) /*-{
    return select.options.length;
  }-*/;

  public native NodeList<OptionElement> selectGetOptions(SelectElement select) /*-{
    return select.options;
  }-*/;

  public native void selectRemoveOption(SelectElement select, int index) /*-{
    select.remove(index);
  }-*/;

  public native void setDraggable(Element elem, String draggable) /*-{
    elem.draggable = draggable;
  }-*/;

  public native void setInnerText(Element elem, String text) /*-{
    // Remove all children first.
    while (elem.firstChild) {
      elem.removeChild(elem.firstChild);
    }
    // Add a new text node.
    if (text != null) {
      elem.appendChild(elem.ownerDocument.createTextNode(text));
    }
  }-*/;

  public void setScrollLeft(Document doc, int left) {
    ensureDocumentScrollingElement(doc).setScrollLeft(left);
  }

  public native void setScrollLeft(Element elem, int left) /*-{
    elem.scrollLeft = left;
  }-*/;

  public void setScrollTop(Document doc, int top) {
    ensureDocumentScrollingElement(doc).setScrollTop(top);
  }

  public native String toString(Element elem) /*-{
    return elem.outerHTML;
  }-*/;

  private Element ensureDocumentScrollingElement(Document document) {
    // In some case (e.g SVG document and old Webkit browsers), getDocumentScrollingElement can
    // return null. In this case, default to documentElement.
    Element scrollingElement = getDocumentScrollingElement(document);
    return scrollingElement != null ? scrollingElement : document.getDocumentElement();
  }

  Element getDocumentScrollingElement(Document doc)  {
    return doc.getViewportElement();
  }

  public int touchGetClientX(Touch touch) {
    return toInt32(touchGetSubPixelClientX(touch));
  }

  public int touchGetClientY(Touch touch) {
    return toInt32(touchGetSubPixelClientY(touch));
  }

  public native int touchGetIdentifier(Touch touch) /*-{
    return touch.identifier;
  }-*/;

  public int touchGetPageX(Touch touch) {
    return toInt32(touchGetSubPixelPageX(touch));
  }

  public int touchGetPageY(Touch touch) {
    return toInt32(touchGetSubPixelPageY(touch));
  }

  public int touchGetScreenX(Touch touch) {
    return toInt32(touchGetSubPixelScreenX(touch));
  }

  public int touchGetScreenY(Touch touch) {
    return toInt32(touchGetSubPixelScreenY(touch));
  }

  public native EventTarget touchGetTarget(Touch touch) /*-{
    return touch.target;
  }-*/;

  private native double getSubPixelAbsoluteLeft(Element elem) /*-{
    var left = 0;
    var curr = elem;
    // This intentionally excludes body which has a null offsetParent.
    while (curr.offsetParent) {
      left -= curr.scrollLeft;
      curr = curr.parentNode;
    }
    while (elem) {
      left += elem.offsetLeft;
      elem = elem.offsetParent;
    }
    return left;
  }-*/;

  private native double getSubPixelAbsoluteTop(Element elem) /*-{
    var top = 0;
    var curr = elem;
    // This intentionally excludes body which has a null offsetParent.
    while (curr.offsetParent) {
      top -= curr.scrollTop;
      curr = curr.parentNode;
    }
    while (elem) {
      top += elem.offsetTop;
      elem = elem.offsetParent;
    }
    return top;
  }-*/;

  private native double eventGetSubPixelScreenX(NativeEvent evt) /*-{
    return evt.screenX || 0;
  }-*/;

  private native double eventGetSubPixelScreenY(NativeEvent evt) /*-{
    return evt.screenY || 0;
  }-*/;

  private native double getSubPixelScrollLeft(Element elem) /*-{
    return elem.scrollLeft || 0;
  }-*/;

  private native double touchGetSubPixelClientX(Touch touch) /*-{
    return touch.clientX || 0;
  }-*/;

  private native double touchGetSubPixelClientY(Touch touch) /*-{
    return touch.clientY || 0;
  }-*/;

  private native double touchGetSubPixelPageX(Touch touch) /*-{
    return touch.pageX || 0;
  }-*/;

  private native double touchGetSubPixelPageY(Touch touch) /*-{
    return touch.pageY || 0;
  }-*/;

  private native double touchGetSubPixelScreenX(Touch touch) /*-{
    return touch.screenX || 0;
  }-*/;

  private native double touchGetSubPixelScreenY(Touch touch) /*-{
    return touch.screenY || 0;
  }-*/;

  private native double eventGetSubPixelClientX(NativeEvent evt) /*-{
    return evt.clientX || 0;
  }-*/;

  private native double eventGetSubPixelClientY(NativeEvent evt) /*-{
    return evt.clientY || 0;
  }-*/;
}
