/*
 * 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.user.client.impl;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;

/**
 * Base implementation of {@link com.google.gwt.user.client.impl.DOMImpl} shared
 * by those browsers that come a bit closer to supporting a common standard (ie,
 * not legacy IEs).
 */
public abstract class DOMImplStandard extends DOMImpl {

  /**
   * Adds custom bitless event dispatchers to GWT. If no specific event dispatcher supplied for an
   * event, the default dispatcher is used.
   * <p> Example usage:
   * <pre>
   * static {
   *   DOMImplStandard.addBitlessEventDispatchers(getMyCustomDispatchers());
   * }
   *
   * private static native JavaScriptObject getMyCustomDispatchers() /*-{
   *   return {
   *     click: @com.xxx.YYY::myCustomDispatcher(*),
   *     ...
   *   };
   * }-* /;
   * </pre>
   *
   * <p> Note that although this method is public for extensions, it is subject to change in
   * different releases.
   *
   * @param eventMap an object that provides dispatching methods keyed with the name of the event
   */
  public static void addBitlessEventDispatchers(JavaScriptObject eventMap) {
    ensureInit();
    bitlessEventDispatchers.merge(eventMap);
  }

  /**
   * Adds custom capture event dispatchers to GWT.
   * <p> Example usage:
   * <pre>
   * static {
   *   if (isIE10Plus())) {
   *     DOMImplStandard.addCaptureEventDispatchers(getMsPointerCaptureDispatchers());
   *   }
   * }
   *
   * private static native JavaScriptObject getMsPointerCaptureDispatchers() /*-{
   *   return {
   *     MSPointerDown: @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent(*),
   *     MSPointerUp:   @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent(*),
   *     ...
   *   };
   * }-* /;
   * </pre>
   *
   * <p> Note that although this method is public for extensions, it is subject to change in
   * different releases.
   *
   * @param eventMap an object that provides dispatching methods keyed with the name of the event
   */
  public static void addCaptureEventDispatchers(JavaScriptObject eventMap) {
    ensureInit();
    captureEventDispatchers.merge(eventMap);
  }

  private static void ensureInit() {
    if (eventSystemIsInitialized) {
      throw new IllegalStateException("Event system already initialized");
    }

    // Ensure that any default extensions for the browser is registered via
    // static initializers in deferred binding of DOMImpl:
    GWT.create(DOMImpl.class);
  }

  private static Element captureElem;

  private static EventMap bitlessEventDispatchers = getBitlessEventDispatchers();

  private static EventMap captureEventDispatchers = getCaptureEventDispatchers();

  @Deprecated // We no longer want any external JSNI dependencies
  private static JavaScriptObject dispatchEvent;

  @Deprecated // We no longer want any external JSNI dependencies
  private static JavaScriptObject dispatchUnhandledEvent;

  @Override
  public Element eventGetFromElement(Event evt) {
    if (evt.getType().equals(BrowserEvents.MOUSEOVER)) {
      return evt.getRelatedEventTarget().cast();
    }

    if (evt.getType().equals(BrowserEvents.MOUSEOUT)) {
      return evt.getEventTarget().cast();
    }

    return null;
  }

  @Override
  public Element eventGetToElement(Event evt) {
    if (evt.getType().equals(BrowserEvents.MOUSEOVER)) {
      return evt.getEventTarget().cast();
    }

    if (evt.getType().equals(BrowserEvents.MOUSEOUT)) {
      return evt.getRelatedEventTarget().cast();
    }

    return null;
  }

  @Override
  public native Element getChild(Element elem, int index) /*-{
    var count = 0, child = elem.firstChild;
    while (child) {
      if (child.nodeType == 1) {
        if (index == count)
          return child;
        ++count;
      }
      child = child.nextSibling;
    }

    return null;
  }-*/;

  @Override
  public native int getChildCount(Element elem) /*-{
    var count = 0, child = elem.firstChild;
    while (child) {
      if (child.nodeType == 1)
        ++count;
      child = child.nextSibling;
    }
    return count;
  }-*/;

  @Override
  public native int getChildIndex(Element parent, Element toFind) /*-{
    var count = 0, child = parent.firstChild;
    while (child) {
      if (child === toFind) {
        return count;
      }
      if (child.nodeType == 1) {
        ++count;
      }
      child = child.nextSibling;
    }
    return -1;
  }-*/;

  @Override
  public native void insertChild(Element parent, Element toAdd, int index) /*-{
    var count = 0, child = parent.firstChild, before = null;
    while (child) {
      if (child.nodeType == 1) {
        if (count == index) {
          before = child;
          break;
        }
        ++count;
      }
      child = child.nextSibling;
    }

    parent.insertBefore(toAdd, before);
  }-*/;

  @Override
  public void releaseCapture(Element elem) {
    maybeInitializeEventSystem();
    if (captureElem == elem) {
      captureElem = null;
    }
  }

  @Override
  public void setCapture(Element elem) {
    maybeInitializeEventSystem();
    captureElem = elem;
  }

  @Override
  public void sinkBitlessEvent(Element elem, String eventTypeName) {
    maybeInitializeEventSystem();
    sinkBitlessEventImpl(elem, eventTypeName);
  }

  @Override
  public void sinkEvents(Element elem, int bits) {
    maybeInitializeEventSystem();
    sinkEventsImpl(elem, bits);
  }

  @Override
  protected native void initEventSystem() /*-{
    // Ensure $entry for bitfull event dispatchers
    @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent =
        $entry(@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent(*));

    @com.google.gwt.user.client.impl.DOMImplStandard::dispatchUnhandledEvent =
        $entry(@com.google.gwt.user.client.impl.DOMImplStandard::dispatchUnhandledEvent(*));

    var foreach = @com.google.gwt.user.client.impl.EventMap::foreach(*);

    // Ensure $entry for bitless event dispatchers
    var bitlessEvents = @com.google.gwt.user.client.impl.DOMImplStandard::bitlessEventDispatchers;
    foreach(bitlessEvents, function(e, fn) { bitlessEvents[e] = $entry(fn); });

    // Ensure $entry for capture event dispatchers
    var captureEvents = @com.google.gwt.user.client.impl.DOMImplStandard::captureEventDispatchers;
    foreach(captureEvents, function(e, fn) { captureEvents[e] = $entry(fn); });

    // Add capture event listeners
    foreach(captureEvents, function(e, fn) { $wnd.addEventListener(e, fn, true); });
  }-*/;

  @Override
  protected native void disposeEventSystem() /*-{
    var foreach = @com.google.gwt.user.client.impl.EventMap::foreach(*);

    // Remove capture event listeners
    foreach(captureEvents, function(e, fn) { $wnd.removeEventListener(e, fn, true); });
  }-*/;

  protected native void sinkBitlessEventImpl(Element elem, String eventTypeName) /*-{
    var dispatchMap = @com.google.gwt.user.client.impl.DOMImplStandard::bitlessEventDispatchers;
    var dispatcher = dispatchMap[eventTypeName] || dispatchMap['_default_'];
    elem.addEventListener(eventTypeName, dispatcher, false);
  }-*/;

  protected native void sinkEventsImpl(Element elem, int bits) /*-{
    var chMask = (elem.__eventBits || 0) ^ bits;
    elem.__eventBits = bits;
    if (!chMask) return;

    if (chMask & 0x00001) elem.onclick       = (bits & 0x00001) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x00002) elem.ondblclick    = (bits & 0x00002) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x00004) elem.onmousedown   = (bits & 0x00004) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x00008) elem.onmouseup     = (bits & 0x00008) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x00010) elem.onmouseover   = (bits & 0x00010) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x00020) elem.onmouseout    = (bits & 0x00020) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x00040) elem.onmousemove   = (bits & 0x00040) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x00080) elem.onkeydown     = (bits & 0x00080) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x00100) elem.onkeypress    = (bits & 0x00100) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x00200) elem.onkeyup       = (bits & 0x00200) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x00400) elem.onchange      = (bits & 0x00400) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x00800) elem.onfocus       = (bits & 0x00800) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x01000) elem.onblur        = (bits & 0x01000) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x02000) elem.onlosecapture = (bits & 0x02000) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x04000) elem.onscroll      = (bits & 0x04000) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x08000) elem.onload        = (bits & 0x08000) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchUnhandledEvent : null;
    if (chMask & 0x10000) elem.onerror       = (bits & 0x10000) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x20000) elem.onmousewheel  = (bits & 0x20000) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x40000) elem.oncontextmenu = (bits & 0x40000) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x80000) elem.onpaste       = (bits & 0x80000) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x100000) elem.ontouchstart = (bits & 0x100000) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x200000) elem.ontouchmove  = (bits & 0x200000) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x400000) elem.ontouchend   = (bits & 0x400000) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x800000) elem.ontouchcancel= (bits & 0x800000) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x1000000) elem.ongesturestart  =(bits & 0x1000000) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x2000000) elem.ongesturechange =(bits & 0x2000000) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
    if (chMask & 0x4000000) elem.ongestureend    = (bits & 0x4000000) ?
        @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
  }-*/;

  private static void dispatchEvent(Event evt) {
    Element element = getFirstAncestorWithListener(evt);
    if (element == null) {
      return;
    }
    DOM.dispatchEvent(evt, element.getNodeType() != 1 ? null : element, getEventListener(element));
  }

  private static Element getFirstAncestorWithListener(Event evt) {
    Element curElem = evt.getCurrentEventTarget().cast();
    while (curElem != null && getEventListener(curElem) == null) {
      curElem = curElem.getParentNode().cast();
    }
    return curElem;
  }

  private static void dispatchDragEvent(Event evt) {
    // Some drag events must call preventDefault to prevent native text selection.
    evt.preventDefault();
    dispatchEvent(evt);
  }

  private static void dispatchUnhandledEvent(Event evt) {
    Element element = evt.getCurrentEventTarget().cast();
    element.setPropertyString("__gwtLastUnhandledEvent", evt.getType());
    dispatchEvent(evt);
  }

  private static void dispatchCapturedEvent(Event evt) {
    DOM.previewEvent(evt);
  }

  private static void dispatchCapturedMouseEvent(Event evt) {
    boolean cancelled = !DOM.previewEvent(evt);
    if (cancelled || captureElem == null) {
      return;
    }
    if (DOM.dispatchEvent(evt, captureElem)) {
      evt.stopPropagation();
    }
  }

  private static native EventMap getBitlessEventDispatchers() /*-{
    return {
      _default_: @com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent(*),
      dragenter: @com.google.gwt.user.client.impl.DOMImplStandard::dispatchDragEvent(*),
      dragover:  @com.google.gwt.user.client.impl.DOMImplStandard::dispatchDragEvent(*),
    };
  }-*/;

  private static native EventMap getCaptureEventDispatchers() /*-{
    return {
      // Mouse events
      click:      @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent(*),
      dblclick:   @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent(*),
      mousedown:  @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent(*),
      mouseup:    @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent(*),
      mousemove:  @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent(*),
      mouseover:  @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent(*),
      mouseout:   @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent(*),
      mousewheel: @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent(*),

      // Keyboard events
      keydown:    @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedEvent(*),
      keyup:      @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedEvent(*),
      keypress:   @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedEvent(*),

      // Touch events
      touchstart:   @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent(*),
      touchend:     @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent(*),
      touchmove:    @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent(*),
      touchcancel:  @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent(*),
      gesturestart: @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent(*),
      gestureend:   @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent(*),
      gesturechange:@com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent(*),
    };
  }-*/;
}
