/*
 * 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.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Overflow;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.touch.client.TouchScroller;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;

/**
 * A simple panel that wraps its contents in a scrollable area.
 */
@SuppressWarnings("deprecation")
public class ScrollPanel extends SimplePanel implements SourcesScrollEvents,
    RequiresResize, ProvidesResize, HasScrolling {

  private final Element containerElem;
  private final Element scrollableElem;

  /**
   * The scroller used to support touch events.
   */
  private TouchScroller touchScroller;

  /**
   * Creates an empty scroll panel.
   */
  public ScrollPanel() {
    this.scrollableElem = getElement();
    this.containerElem = Document.get().createDivElement();
    scrollableElem.appendChild(containerElem);
    initialize();
  }

  /**
   * Creates a new scroll panel with the given child widget.
   * 
   * @param child the widget to be wrapped by the scroll panel
   */
  public ScrollPanel(Widget child) {
    this();
    setWidget(child);
  }

  /**
   * Creates an empty scroll panel using the specified root, scrollable, and
   * container elements.
   * 
   * @param root the root element of the Widget
   * @param scrollable the scrollable element, which can be the same as the root
   *          element
   * @param container the container element that holds the child
   */
  protected ScrollPanel(Element root, Element scrollable, Element container) {
    super(root);
    this.scrollableElem = scrollable;
    this.containerElem = container;
    initialize();
  }

  public HandlerRegistration addScrollHandler(ScrollHandler handler) {
    /*
     * Sink the event on the scrollable element, which may not be the root
     * element.
     */
    Event.sinkEvents(getScrollableElement(), Event.ONSCROLL);
    return addHandler(handler, ScrollEvent.getType());
  }

  /**
   * @deprecated Use {@link #addScrollHandler} instead
   */
  @Deprecated
  public void addScrollListener(ScrollListener listener) {
    ListenerWrapper.WrappedScrollListener.add(this, listener);
  }

  /**
   * Ensures that the specified item is visible, by adjusting the panel's scroll
   * position.
   * 
   * @param item the item whose visibility is to be ensured
   */
  public void ensureVisible(UIObject item) {
    Element scroll = getScrollableElement();
    Element element = item.getElement();
    ensureVisibleImpl(scroll, element);
  }

  /**
   * Gets the horizontal scroll position.
   * 
   * @return the horizontal scroll position, in pixels
   */
  public int getHorizontalScrollPosition() {
    return getScrollableElement().getScrollLeft();
  }

  public int getMaximumHorizontalScrollPosition() {
    return ScrollImpl.get().getMaximumHorizontalScrollPosition(getScrollableElement());
  }

  public int getMaximumVerticalScrollPosition() {
    return getScrollableElement().getScrollHeight() - getScrollableElement().getClientHeight();
  }

  public int getMinimumHorizontalScrollPosition() {
    return ScrollImpl.get().getMinimumHorizontalScrollPosition(getScrollableElement());
  }

  public int getMinimumVerticalScrollPosition() {
    return 0;
  }

  /**
   * Gets the vertical scroll position.
   * 
   * @return the vertical scroll position, in pixels
   * @deprecated as of GWT 2.3, replaced by {@link #getVerticalScrollPosition()}
   */
  @Deprecated
  public int getScrollPosition() {
    return getScrollableElement().getScrollTop();
  }

  public int getVerticalScrollPosition() {
    return getScrollPosition();
  }

  /**
   * Check whether or not touch based scrolling is disabled. This method always
   * returns false on devices that do not support touch scrolling.
   * 
   * @return true if disabled, false if enabled
   */
  public boolean isTouchScrollingDisabled() {
    return touchScroller == null;
  }

  public void onResize() {
    Widget child = getWidget();
    if ((child != null) && (child instanceof RequiresResize)) {
      ((RequiresResize) child).onResize();
    }
  }

  /**
   * @deprecated Use the {@link HandlerRegistration#removeHandler}
   * method on the object returned by {@link #addScrollHandler} instead
   */
  @Deprecated
  public void removeScrollListener(ScrollListener listener) {
    ListenerWrapper.WrappedScrollListener.remove(this, listener);
  }

  /**
   * Scroll to the bottom of this panel.
   */
  public void scrollToBottom() {
    setVerticalScrollPosition(getMaximumVerticalScrollPosition());
  }

  /**
   * Scroll to the far left of this panel.
   */
  public void scrollToLeft() {
    setHorizontalScrollPosition(getMinimumHorizontalScrollPosition());
  }

  /**
   * Scroll to the far right of this panel.
   */
  public void scrollToRight() {
    setHorizontalScrollPosition(getMaximumHorizontalScrollPosition());
  }

  /**
   * Scroll to the top of this panel.
   */
  public void scrollToTop() {
    setVerticalScrollPosition(getMinimumVerticalScrollPosition());
  }

  /**
   * Sets whether this panel always shows its scroll bars, or only when
   * necessary.
   * 
   * @param alwaysShow <code>true</code> to show scroll bars at all times
   */
  public void setAlwaysShowScrollBars(boolean alwaysShow) {
    getScrollableElement().getStyle().setOverflow(alwaysShow ? Overflow.SCROLL : Overflow.AUTO);
  }

  /**
   * Sets the object's height. This height does not include decorations such as
   * border, margin, and padding.
   * 
   * @param height the object's new height, in absolute CSS units (e.g. "10px",
   *          "1em" but not "50%")
   */
  @Override
  public void setHeight(String height) {
    super.setHeight(height);
  }

  /**
   * Sets the horizontal scroll position.
   * 
   * @param position the new horizontal scroll position, in pixels
   */
  public void setHorizontalScrollPosition(int position) {
    getScrollableElement().setScrollLeft(position);
  }

  /**
   * Sets the vertical scroll position.
   * 
   * @param position the new vertical scroll position, in pixels
   * @deprecated as of GWT 2.3, replaced by
   *             {@link #setVerticalScrollPosition(int)}
   */
  @Deprecated
  public void setScrollPosition(int position) {
    getScrollableElement().setScrollTop(position);
  }

  /**
   * Sets the object's size. This size does not include decorations such as
   * border, margin, and padding.
   * 
   * @param width the object's new width, in absolute CSS units (e.g. "10px",
   *          "1em", but not "50%")
   * @param height the object's new height, in absolute CSS units (e.g. "10px",
   *          "1em", but not "50%")
   */
  @Override
  public void setSize(String width, String height) {
    super.setSize(width, height);
  }

  /**
   * Set whether or not touch scrolling is disabled. By default, touch scrolling
   * is enabled on devices that support touch events.
   * 
   * @param isDisabled true to disable, false to enable
   * @return true if touch scrolling is enabled and supported, false if disabled
   *         or not supported
   */
  public boolean setTouchScrollingDisabled(boolean isDisabled) {
    if (isDisabled == isTouchScrollingDisabled()) {
      return isDisabled;
    }

    if (isDisabled) {
      // Detach the touch scroller.
      touchScroller.setTargetWidget(null);
      touchScroller = null;
    } else {
      // Attach a new touch scroller.
      touchScroller = TouchScroller.createIfSupported(this);
    }
    return isTouchScrollingDisabled();
  }

  public void setVerticalScrollPosition(int position) {
    setScrollPosition(position);
  }

  /**
   * Sets the object's width. This width does not include decorations such as
   * border, margin, and padding.
   * 
   * @param width the object's new width, in absolute CSS units (e.g. "10px",
   *          "1em", but not "50%")
   */
  @Override
  public void setWidth(String width) {
    super.setWidth(width);
  }

  @Override
  protected com.google.gwt.user.client.Element getContainerElement() {
    return DOM.asOld(containerElem);
  }

  /**
   * Get the scrollable element. That is the element with its overflow set to
   * 'auto' or 'scroll'.
   * 
   * @return the scrollable element
   */
  protected com.google.gwt.user.client.Element getScrollableElement() {
    return DOM.asOld(scrollableElem);
  }

  @Override
  protected void onAttach() {
    super.onAttach();

    /*
     * Attach the event listener in onAttach instead of onLoad so users cannot
     * accidentally override it. If the scrollable element is the same as the
     * root element, then we set the event listener twice (once in
     * super.onAttach() and once here), which is fine.
     */
    Event.setEventListener(getScrollableElement(), this);
  }

  @Override
  protected void onDetach() {
    /*
     * Detach the event listener in onDetach instead of onUnload so users cannot
     * accidentally override it.
     */
    Event.setEventListener(getScrollableElement(), null);

    super.onDetach();
  }

  private native void ensureVisibleImpl(Element scroll, Element e) /*-{
    if (!e)
      return; 

    var item = e;
    var realOffset = 0;
    while (item && (item != scroll)) {
      realOffset += item.offsetTop;
      item = item.offsetParent;
    }

    scroll.scrollTop = realOffset - scroll.offsetHeight / 2;
  }-*/;

  /**
   * Initialize the widget.
   */
  private void initialize() {
    setAlwaysShowScrollBars(false);

    // Prevent IE standard mode bug when a AbsolutePanel is contained.
    scrollableElem.getStyle().setPosition(Position.RELATIVE);
    containerElem.getStyle().setPosition(Position.RELATIVE);

    // Hack to account for the IE6/7 scrolling bug described here:
    //   http://stackoverflow.com/questions/139000/div-with-overflowauto-and-a-100-wide-table-problem
    scrollableElem.getStyle().setProperty("zoom", "1");
    containerElem.getStyle().setProperty("zoom", "1");

    // Enable touch scrolling.
    setTouchScrollingDisabled(false);

    // Initialize the scrollable element.
    ScrollImpl.get().initialize(scrollableElem, containerElem);
  }
}
