/*
 * 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.ui;

import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.DomEvent;
import com.google.gwt.event.logical.shared.AttachEvent;
import com.google.gwt.event.logical.shared.AttachEvent.Handler;
import com.google.gwt.event.logical.shared.HasAttachHandlers;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;

/**
 * The base class for the majority of user-interface objects. Widget adds
 * support for receiving events from the browser and being added directly to
 * {@link com.google.gwt.user.client.ui.Panel panels}.
 */
public class Widget extends UIObject implements EventListener, HasAttachHandlers,
    IsWidget {

  /**
   * This convenience method makes a null-safe call to
   * {@link IsWidget#asWidget()}.
   *
   * @return the widget aspect, or <code>null</code> if w is null
   */
  public static Widget asWidgetOrNull(IsWidget w) {
    return w == null ? null : w.asWidget();
  }
  /**
   * A bit-map of the events that should be sunk when the widget is attached to
   * the DOM. (We delay the sinking of events to improve startup performance.)
   * When the widget is attached, this is set to -1
   * <p>
   * Package protected to allow Composite to see it.
   */
  int eventsToSink;
  private boolean attached;
  private HandlerManager handlerManager;
  private Object layoutData;
  private Widget parent;

  public HandlerRegistration addAttachHandler(Handler handler) {
    return addHandler(handler, AttachEvent.getType());
  }

  /**
   * For <a href=
   * "http://code.google.com/p/google-web-toolkit/wiki/UnderstandingMemoryLeaks"
   * >browsers which do not leak</a>, adds a native event handler to the widget.
   * Note that, unlike the
   * {@link #addDomHandler(EventHandler, com.google.gwt.event.dom.client.DomEvent.Type)}
   * implementation, there is no need to attach the widget to the DOM in order
   * to cause the event handlers to be attached.
   *
   * @param <H> the type of handler to add
   * @param type the event key
   * @param handler the handler
   * @return {@link HandlerRegistration} used to remove the handler
   */
  public final <H extends EventHandler> HandlerRegistration addBitlessDomHandler(
      final H handler, DomEvent.Type<H> type) {
    assert handler != null : "handler must not be null";
    assert type != null : "type must not be null";
    sinkBitlessEvent(type.getName());
    return ensureHandlers().addHandler(type, handler);
  }

  /**
   * Adds a native event handler to the widget and sinks the corresponding
   * native event. If you do not want to sink the native event, use the generic
   * addHandler method instead.
   *
   * @param <H> the type of handler to add
   * @param type the event key
   * @param handler the handler
   * @return {@link HandlerRegistration} used to remove the handler
   */
  public final <H extends EventHandler> HandlerRegistration addDomHandler(
      final H handler, DomEvent.Type<H> type) {
    assert handler != null : "handler must not be null";
    assert type != null : "type must not be null";
    int typeInt = Event.getTypeInt(type.getName());
    if (typeInt == -1) {
      sinkBitlessEvent(type.getName());
    } else {
      sinkEvents(typeInt);
    }
    return ensureHandlers().addHandler(type, handler);
  }

  /**
   * Adds this handler to the widget.
   *
   * @param <H> the type of handler to add
   * @param type the event type
   * @param handler the handler
   * @return {@link HandlerRegistration} used to remove the handler
   */
  public final <H extends EventHandler> HandlerRegistration addHandler(
      final H handler, GwtEvent.Type<H> type) {
    return ensureHandlers().addHandler(type, handler);
  }

  public Widget asWidget() {
    return this;
  }

  public void fireEvent(GwtEvent<?> event) {
    if (handlerManager != null) {
      handlerManager.fireEvent(event);
    }
  }

  /**
   * Gets the panel-defined layout data associated with this widget.
   *
   * @return the widget's layout data
   * @see #setLayoutData
   */
  public Object getLayoutData() {
    return layoutData;
  }

  /**
   * Gets this widget's parent panel.
   *
   * @return the widget's parent panel
   */
  public Widget getParent() {
    return parent;
  }

  /**
   * Determines whether this widget is currently attached to the browser's
   * document (i.e., there is an unbroken chain of widgets between this widget
   * and the underlying browser document).
   *
   * @return <code>true</code> if the widget is attached
   */
  public boolean isAttached() {
    return attached;
  }

  public void onBrowserEvent(Event event) {
    switch (DOM.eventGetType(event)) {
      case Event.ONMOUSEOVER:
        // Only fire the mouse over event if it's coming from outside this
        // widget.
      case Event.ONMOUSEOUT:
        // Only fire the mouse out event if it's leaving this
        // widget.
        Element related = event.getRelatedEventTarget().cast();
        if (related != null && getElement().isOrHasChild(related)) {
          return;
        }
        break;
    }
    DomEvent.fireNativeEvent(event, this, this.getElement());
  }

  /**
   * Removes this widget from its parent widget, if one exists.
   *
   * <p>
   * If it has no parent, this method does nothing. If it is a "root" widget
   * (meaning it's been added to the detach list via
   * {@link RootPanel#detachOnWindowClose(Widget)}), it will be removed from the
   * detached immediately. This makes it possible for Composites and Panels to
   * adopt root widgets.
   * </p>
   *
   * @throws IllegalStateException if this widget's parent does not support
   *           removal (e.g. {@link Composite})
   */
  public void removeFromParent() {
    if (parent == null) {
      // If the widget had no parent, check to see if it was in the detach list
      // and remove it if necessary.
      if (RootPanel.isInDetachList(this)) {
        RootPanel.detachNow(this);
      }
    } else if (parent instanceof HasWidgets) {
      ((HasWidgets) parent).remove(this);
    } else if (parent != null) {
      throw new IllegalStateException(
          "This widget's parent does not implement HasWidgets");
    }
  }

  /**
   * Sets the panel-defined layout data associated with this widget. Only the
   * panel that currently contains a widget should ever set this value. It
   * serves as a place to store layout bookkeeping data associated with a
   * widget.
   *
   * @param layoutData the widget's layout data
   */
  public void setLayoutData(Object layoutData) {
    this.layoutData = layoutData;
  }

  /**
   * Overridden to defer the call to super.sinkEvents until the first time this
   * widget is attached to the dom, as a performance enhancement. Subclasses
   * wishing to customize sinkEvents can preserve this deferred sink behavior by
   * putting their implementation behind a check of
   * <code>isOrWasAttached()</code>:
   *
   * <pre>
   * {@literal @}Override
   * public void sinkEvents(int eventBitsToAdd) {
   *   if (isOrWasAttached()) {
   *     /{@literal *} customized sink code goes here {@literal *}/
   *   } else {
   *     super.sinkEvents(eventBitsToAdd);
   *  }
   *} </pre>
   */
  @Override
  public void sinkEvents(int eventBitsToAdd) {
    if (isOrWasAttached()) {
      super.sinkEvents(eventBitsToAdd);
    } else {
      eventsToSink |= eventBitsToAdd;
    }
  }

  @Override
  public void unsinkEvents(int eventBitsToRemove) {
    if (isOrWasAttached()) {
      super.unsinkEvents(eventBitsToRemove);
    } else {
      eventsToSink &= ~eventBitsToRemove;
    }
  }

  /**
   * Creates the {@link HandlerManager} used by this Widget. You can override
   * this method to create a custom {@link HandlerManager}.
   *
   * @return the {@link HandlerManager} you want to use
   */
  protected HandlerManager createHandlerManager() {
    return new HandlerManager(this);
  }

  /**
   * Fires an event on a child widget. Used to delegate the handling of an event
   * from one widget to another.
   *
   * @param event the event
   * @param target fire the event on the given target
   */
  protected void delegateEvent(Widget target, GwtEvent<?> event) {
    target.fireEvent(event);
  }

  /**
   * If a widget contains one or more child widgets that are not in the logical
   * widget hierarchy (the child is physically connected only on the DOM level),
   * it must override this method and call {@link #onAttach()} for each of its
   * child widgets.
   *
   * @see #onAttach()
   */
  protected void doAttachChildren() {
  }

  /**
   * If a widget contains one or more child widgets that are not in the logical
   * widget hierarchy (the child is physically connected only on the DOM level),
   * it must override this method and call {@link #onDetach()} for each of its
   * child widgets.
   *
   * @see #onDetach()
   */
  protected void doDetachChildren() {
  }

  /**
   * Gets the number of handlers listening to the event type.
   *
   * @param type the event type
   * @return the number of registered handlers
   */
  protected int getHandlerCount(GwtEvent.Type<?> type) {
    return handlerManager == null ? 0 : handlerManager.getHandlerCount(type);
  }

  /**
   * Has this widget ever been attached?
   *
   * @return true if this widget ever been attached to the DOM, false otherwise
   */
  protected final boolean isOrWasAttached() {
    return eventsToSink == -1;
  }

  /**
   * <p>
   * This method is called when a widget is attached to the browser's document.
   * To receive notification after a Widget has been added to the document,
   * override the {@link #onLoad} method or use {@link #addAttachHandler}.
   * </p>
   * <p>
   * It is strongly recommended that you override {@link #onLoad()} or
   * {@link #doAttachChildren()} instead of this method to avoid inconsistencies
   * between logical and physical attachment states.
   * </p>
   * <p>
   * Subclasses that override this method must call
   * <code>super.onAttach()</code> to ensure that the Widget has been attached
   * to its underlying Element.
   * </p>
   *
   * @throws IllegalStateException if this widget is already attached
   * @see #onLoad()
   * @see #doAttachChildren()
   */
  protected void onAttach() {
    if (isAttached()) {
      throw new IllegalStateException(
          "Should only call onAttach when the widget is detached from the browser's document");
    }

    attached = true;

    // Event hookup code
    DOM.setEventListener(getElement(), this);
    int bitsToAdd = eventsToSink;
    eventsToSink = -1;
    if (bitsToAdd > 0) {
      sinkEvents(bitsToAdd);
    }
    doAttachChildren();

    // onLoad() gets called only *after* all of the children are attached and
    // the attached flag is set. This allows widgets to be notified when they
    // are fully attached, and panels when all of their children are attached.
    onLoad();
    AttachEvent.fire(this, true);
  }

  /**
   * <p>
   * This method is called when a widget is detached from the browser's
   * document. To receive notification before a Widget is removed from the
   * document, override the {@link #onUnload} method or use {@link #addAttachHandler}.
   * </p>
   * <p>
   * It is strongly recommended that you override {@link #onUnload()} or
   * {@link #doDetachChildren()} instead of this method to avoid inconsistencies
   * between logical and physical attachment states.
   * </p>
   * <p>
   * Subclasses that override this method must call
   * <code>super.onDetach()</code> to ensure that the Widget has been detached
   * from the underlying Element. Failure to do so will result in application
   * memory leaks due to circular references between DOM Elements and JavaScript
   * objects.
   * </p>
   *
   * @throws IllegalStateException if this widget is already detached
   * @see #onUnload()
   * @see #doDetachChildren()
   */
  protected void onDetach() {
    if (!isAttached()) {
      throw new IllegalStateException(
          "Should only call onDetach when the widget is attached to the browser's document");
    }

    try {
      // onUnload() gets called *before* everything else (the opposite of
      // onLoad()).
      onUnload();
      AttachEvent.fire(this, false);
    } finally {
      // Put this in a finally, just in case onUnload throws an exception.
      try {
        doDetachChildren();
      } finally {
        // Put this in a finally, in case doDetachChildren throws an exception.
        DOM.setEventListener(getElement(), null);
        attached = false;
      }
    }
  }

  /**
   * This method is called immediately after a widget becomes attached to the
   * browser's document.
   */
  protected void onLoad() {
  }

  /**
   * This method is called immediately before a widget will be detached from the
   * browser's document.
   */
  protected void onUnload() {
  }

  /**
   * Ensures the existence of the handler manager.
   *
   * @return the handler manager
   * */
  HandlerManager ensureHandlers() {
    return handlerManager == null ? handlerManager = createHandlerManager()
        : handlerManager;
  }

  HandlerManager getHandlerManager() {
    return handlerManager;
  }

  @Override
  void replaceElement(com.google.gwt.dom.client.Element elem) {
    if (isAttached()) {
      // Remove old event listener to avoid leaking. onDetach will not do this
      // for us, because it is only called when the widget itself is detached
      // from the document.
      DOM.setEventListener(getElement(), null);
    }

    super.replaceElement(elem);

    if (isAttached()) {
      // Hook the event listener back up on the new element. onAttach will not
      // do this for us, because it is only called when the widget itself is
      // attached to the document.
      DOM.setEventListener(getElement(), this);
    }
  }

  /**
   * Sets this widget's parent. This method should only be called by
   * {@link Panel} and {@link Composite}.
   *
   * @param parent the widget's new parent
   * @throws IllegalStateException if <code>parent</code> is non-null and the
   *           widget already has a parent
   */
  void setParent(Widget parent) {
    Widget oldParent = this.parent;
    if (parent == null) {
      try {
        if (oldParent != null && oldParent.isAttached()) {
          onDetach();
          assert !isAttached() : "Failure of " + this.getClass().getName()
              + " to call super.onDetach()";
        }
      } finally {
        // Put this in a finally in case onDetach throws an exception.
        this.parent = null;
      }
    } else {
      if (oldParent != null) {
        throw new IllegalStateException(
            "Cannot set a new parent without first clearing the old parent");
      }
      this.parent = parent;
      if (parent.isAttached()) {
        onAttach();
        assert isAttached() : "Failure of " + this.getClass().getName()
            + " to call super.onAttach()";
      }
    }
  }
}
