/*
 * Copyright 2009 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.JavaScriptObject;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.Event;

/**
 * Trident layout engine implementation of
 * {@link com.google.gwt.user.client.impl.DOMImpl}.
 */
public abstract class DOMImplTrident extends DOMImpl {
  private static JavaScriptObject callDispatchEvent;

  private static JavaScriptObject callDispatchDblClickEvent;

  private static JavaScriptObject callDispatchOnLoadEvent;

  private static JavaScriptObject callDispatchUnhandledEvent;

  /**
   * Let every GWT app on the page preview the current event. If any app cancels
   * the event, the event will be canceled for all apps.
   * 
   * @return <code>false</code> to cancel the event
   */
  private static native boolean previewEventImpl() /*-{
    var isCancelled = false; 
    for (var i = 0; i < $wnd.__gwt_globalEventArray.length; i++) {
      if (!$wnd.__gwt_globalEventArray[i]()) {
        isCancelled = true;
      }
    }
    return !isCancelled;
  }-*/;

  @Override
  public native Element eventGetFromElement(Event evt) /*-{
    // Prefer 'relatedTarget' if it's set (see createMouseEvent(), which
    // explicitly sets relatedTarget when synthesizing mouse events).
    return evt.relatedTarget || evt.fromElement;
  }-*/;

  @Override
  public native Element eventGetToElement(Event evt) /*-{
    // Prefer 'relatedTarget' if it's set (see createMouseEvent(), which
    // explicitly sets relatedTarget when synthesizing mouse events).
    return evt.relatedTarget || evt.toElement;
  }-*/;

  @Override
  public native Element getChild(Element elem, int index) /*-{
    return elem.children[index];
  }-*/;

  @Override
  public native int getChildCount(Element elem) /*-{
    return elem.children.length;
  }-*/;

  @Override
  public native int getChildIndex(Element parent, Element child) /*-{
    var count = parent.children.length;
    for (var i = 0; i < count; ++i) {
      if (child === parent.children[i]) {
        return i;
      }
    }
    return -1;
  }-*/;

  @Override
  public native void initEventSystem() /*-{
    // All GWT apps on the page register themselves with the globalEventArray
    // so that the first app to handle an event can allow all apps on the page
    // to preview it. See issue 3892 for more details.
    //
    // Apps cannot just mark the event as they visit it for a few reasons.
    // First, window level event handlers fire last in IE, so the first app to
    // cancel the event will be the last to see it. Second, window events do
    // not support arbitrary attributes, and the only writable field is the
    // returnValue, which has another use. Finally, window events are not
    // comparable (ex. a=event; b=event; a!=b), so we cannot keep a list of
    // events that have already been previewed by the current app.
    if ($wnd.__gwt_globalEventArray == null) {
      $wnd.__gwt_globalEventArray = new Array();
    }
    $wnd.__gwt_globalEventArray[$wnd.__gwt_globalEventArray.length] = $entry(function() {
      return @com.google.gwt.user.client.DOM::previewEvent(Lcom/google/gwt/user/client/Event;)($wnd.event);
    });

    var dispatchEvent = $entry(function() {
      // IE doesn't define event.currentTarget, so we squirrel it away here. It
      // also seems that IE won't allow you to add expandos to the event object,
      // so we have to store it in a global. This is ok because only one event
      // can actually be dispatched at a time.
      var oldEventTarget = @com.google.gwt.dom.client.DOMImplTrident::currentEventTarget;
      @com.google.gwt.dom.client.DOMImplTrident::currentEventTarget = this;

      // The first GWT app on the page to handle the event allows all apps to
      // preview it before continuing or cancelling, which is consistent with
      // other browsers.
      if ($wnd.event.returnValue == null) {
        $wnd.event.returnValue = true;
        if (!@com.google.gwt.user.client.impl.DOMImplTrident::previewEventImpl()()) {
          @com.google.gwt.dom.client.DOMImplTrident::currentEventTarget = oldEventTarget;
          return;
        }
      }

      var getEventListener = @com.google.gwt.user.client.impl.DOMImpl::getEventListener(*);

      var listener, curElem = this;
      while (curElem && !(listener = getEventListener(curElem))) {
        curElem = curElem.parentElement;
      }

      if (listener) {
        @com.google.gwt.user.client.DOM::dispatchEvent(Lcom/google/gwt/user/client/Event;Lcom/google/gwt/dom/client/Element;Lcom/google/gwt/user/client/EventListener;)($wnd.event, curElem, listener);
      }

      @com.google.gwt.dom.client.DOMImplTrident::currentEventTarget = oldEventTarget;
    });

    var dispatchDblClickEvent = $entry(function() {
      var newEvent = $doc.createEventObject();
      // Synthesize a click event if one hasn't already been synthesized.
      // Issue 4027: fireEvent is undefined on disabled input elements.
      if ($wnd.event.returnValue == null && $wnd.event.srcElement.fireEvent) {
        $wnd.event.srcElement.fireEvent('onclick', newEvent);
      }
      if (this.__eventBits & 2) {
        dispatchEvent.call(this);
      } else if ($wnd.event.returnValue == null) {
        // Ensure that we preview the event even if we aren't handling it.
        $wnd.event.returnValue = true;
        @com.google.gwt.user.client.impl.DOMImplTrident::previewEventImpl()();
      }
    });

    var dispatchUnhandledEvent = $entry(function() {
      this.__gwtLastUnhandledEvent = $wnd.event.type;
      dispatchEvent.call(this);
    });

    // Hook the above functions on the current window object, and
    // create a caller function for each one that indirects via
    // the global object. Make sure that the caller function has
    // no direct reference to the GWT program.
    var moduleName = @com.google.gwt.core.client.GWT::getModuleName()().replace(/\./g,'_');

    $wnd['__gwt_dispatchEvent_' + moduleName] = dispatchEvent;
    @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent = new Function('w',
      'return function() { w.__gwt_dispatchEvent_' + moduleName + '.call(this) }')($wnd);

    $wnd['__gwt_dispatchDblClickEvent_' + moduleName] = dispatchDblClickEvent;
    @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchDblClickEvent = new Function('w',
      'return function() { w.__gwt_dispatchDblClickEvent_' + moduleName + '.call(this)}')($wnd);

    $wnd['__gwt_dispatchUnhandledEvent_' + moduleName] = dispatchUnhandledEvent;
    @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchUnhandledEvent = new Function('w',
      'return function() { w.__gwt_dispatchUnhandledEvent_' + moduleName + '.call(this)}')($wnd);

    @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchOnLoadEvent = new Function('w',
      'return function() { w.__gwt_dispatchUnhandledEvent_' + moduleName + '.call(w.event.srcElement)}')($wnd);

    // We need to create these delegate functions to fix up the 'this' context.
    // Normally, 'this' is the firing element, but this is only true for
    // 'onclick = ...' event handlers, not for handlers setup via attachEvent().
    var bodyDispatcher = $entry(function() { dispatchEvent.call($doc.body); });
    var bodyDblClickDispatcher = $entry(function() { dispatchDblClickEvent.call($doc.body); });

    $doc.body.attachEvent('onclick', bodyDispatcher);
    $doc.body.attachEvent('onmousedown', bodyDispatcher);
    $doc.body.attachEvent('onmouseup', bodyDispatcher);
    $doc.body.attachEvent('onmousemove', bodyDispatcher);
    $doc.body.attachEvent('onmousewheel', bodyDispatcher);
    $doc.body.attachEvent('onkeydown', bodyDispatcher);
    $doc.body.attachEvent('onkeypress', bodyDispatcher);
    $doc.body.attachEvent('onkeyup', bodyDispatcher);
    $doc.body.attachEvent('onfocus', bodyDispatcher);
    $doc.body.attachEvent('onblur', bodyDispatcher);
    $doc.body.attachEvent('ondblclick', bodyDblClickDispatcher);
    $doc.body.attachEvent('oncontextmenu', bodyDispatcher);
  }-*/;

  @Override
  public native void insertChild(Element parent, Element child, int index) /*-{
    if (index >= parent.children.length)
      parent.appendChild(child);
    else
      parent.insertBefore(child, parent.children[index]);
  }-*/;

  @Override
  public void releaseCapture(Element elem) {
    maybeInitializeEventSystem();
    releaseCaptureImpl(elem);
  }

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

  @Override
  public void sinkBitlessEvent(Element elem, String eventTypeName) {
    // not supported
  }

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

  @Override
  protected void disposeEventSystem() {
    // TODO(cromwellian) support shutdown of event system if possible
  }

  private native void releaseCaptureImpl(Element elem) /*-{
    elem.releaseCapture();
  }-*/;

  private native void setCaptureImpl(Element elem) /*-{
    elem.setCapture();
  }-*/;

  private 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.DOMImplTrident::callDispatchEvent : null;
    // Add a ondblclick handler if onclick is desired to ensure that 
    // a user's double click will result in two onclick events.
    if (chMask & (0x00003)) elem.ondblclick  = (bits & (0x00003)) ?
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchDblClickEvent : null;
    if (chMask & 0x00004) elem.onmousedown   = (bits & 0x00004) ?
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent : null;
    if (chMask & 0x00008) elem.onmouseup     = (bits & 0x00008) ?
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent : null;
    if (chMask & 0x00010) elem.onmouseover   = (bits & 0x00010) ?
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent : null;
    if (chMask & 0x00020) elem.onmouseout    = (bits & 0x00020) ?
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent : null;
    if (chMask & 0x00040) elem.onmousemove   = (bits & 0x00040) ?
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent : null;
    if (chMask & 0x00080) elem.onkeydown     = (bits & 0x00080) ?
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent : null;
    if (chMask & 0x00100) elem.onkeypress    = (bits & 0x00100) ?
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent : null;
    if (chMask & 0x00200) elem.onkeyup       = (bits & 0x00200) ?
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent : null;
    if (chMask & 0x00400) elem.onchange      = (bits & 0x00400) ?
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent : null;
    if (chMask & 0x00800) elem.onfocus       = (bits & 0x00800) ?
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent : null;
    if (chMask & 0x01000) elem.onblur        = (bits & 0x01000) ?
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent : null;
    if (chMask & 0x02000) elem.onlosecapture = (bits & 0x02000) ?
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent : null;
    if (chMask & 0x04000) elem.onscroll      = (bits & 0x04000) ?
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent : null;
    if (chMask & 0x08000) {
      if (elem.nodeName == "IFRAME") {
        if (bits & 0x08000) {
          elem.attachEvent('onload', @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchOnLoadEvent);
        } else {
          elem.detachEvent('onload', @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchOnLoadEvent);
        }
      } else {
       elem.onload = (bits & 0x08000) ?
          @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchUnhandledEvent : null;
      }
    }
    if (chMask & 0x10000) elem.onerror       = (bits & 0x10000) ?
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent : null;
    if (chMask & 0x20000) elem.onmousewheel  = (bits & 0x20000) ? 
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent : null;
    if (chMask & 0x40000) elem.oncontextmenu = (bits & 0x40000) ? 
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent : null;
    if (chMask & 0x80000) elem.onpaste       = (bits & 0x80000) ? 
        @com.google.gwt.user.client.impl.DOMImplTrident::callDispatchEvent : null;
  }-*/;
}
