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

import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.event.logical.shared.BeforeSelectionEvent;
import com.google.gwt.event.logical.shared.BeforeSelectionHandler;
import com.google.gwt.event.logical.shared.HasBeforeSelectionHandlers;
import com.google.gwt.event.logical.shared.HasSelectionHandlers;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.safehtml.shared.SafeHtml;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * A panel that stacks its children vertically, displaying only one at a time,
 * with a header for each child which the user can click to display.
 *
 * <p>
 * This widget will <em>only</em> work in standards mode, which requires that
 * the HTML page in which it is run have an explicit &lt;!DOCTYPE&gt;
 * declaration.
 * </p>
 *
 * <h3>CSS Style Rules</h3>
 * <dl>
 * <dt>.gwt-StackLayoutPanel <dd> the panel itself
 * <dt>.gwt-StackLayoutPanel .gwt-StackLayoutPanelHeader <dd> applied to each
 * header widget
 * <dt>.gwt-StackLayoutPanel .gwt-StackLayoutPanelHeader-hovering <dd> applied to each
 * header widget on mouse hover
 * <dt>.gwt-StackLayoutPanel .gwt-StackLayoutPanelContent <dd> applied to each
 * child widget
 * </dl>
 *
 * <p>
 * <h3>Example</h3>
 * {@example com.google.gwt.examples.StackLayoutPanelExample}
 * </p>
 *
 * <h3>Use in UiBinder Templates</h3>
 * <p>
 * A StackLayoutPanel element in a
 * {@link com.google.gwt.uibinder.client.UiBinder UiBinder} template may have a
 * <code>unit</code> attribute with a
 * {@link com.google.gwt.dom.client.Style.Unit Style.Unit} value (it defaults to
 * PX).
 * <p>
 * The children of a StackLayoutPanel element are laid out in &lt;g:stack>
 * elements. Each stack can have one widget child and one of two types of header
 * elements. A &lt;g:header> element can hold html, or a &lt;g:customHeader>
 * element can hold a widget. (Note that the tags of the header elements are not
 * capitalized. This is meant to signal that the head is not a runtime object,
 * and so cannot have a <code>ui:field</code> attribute.)
 * <p>
 * For example:
 *
 * <pre>
 * &lt;g:StackLayoutPanel unit='PX'>
 *  &lt;g:stack>
 *    &lt;g:header size='3'>&lt;b>HTML&lt;/b> header&lt;/g:header>
 *    &lt;g:Label>able&lt;/g:Label>
 *  &lt;/g:stack>
 *  &lt;g:stack>
 *    &lt;g:customHeader size='3'>
 *      &lt;g:Label>Custom header&lt;/g:Label>
 *    &lt;/g:customHeader>
 *    &lt;g:Label>baker&lt;/g:Label>
 *  &lt;/g:stack>
 * &lt;/g:StackLayoutPanel>
 * </pre>
 */
public class StackLayoutPanel extends ResizeComposite implements HasWidgets,
    ProvidesResize, IndexedPanel.ForIsWidget,
    HasBeforeSelectionHandlers<Integer>, HasSelectionHandlers<Integer> {

  private class Header extends Composite implements HasClickHandlers {
    public Header(Widget child) {
      initWidget(child);
    }

    public HandlerRegistration addClickHandler(ClickHandler handler) {
      return this.addDomHandler(handler, ClickEvent.getType());
    }

    public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) {
      return this.addDomHandler(handler, MouseOutEvent.getType());
    }

    public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) {
      return this.addDomHandler(handler, MouseOverEvent.getType());
    }
  }

  private static class LayoutData {
    public double headerSize;
    public Header header;
    public Widget widget;

    public LayoutData(Widget widget, Header header, double headerSize) {
      this.widget = widget;
      this.header = header;
      this.headerSize = headerSize;
    }
  }

  private static final String WIDGET_STYLE = "gwt-StackLayoutPanel";
  private static final String CONTENT_STYLE = "gwt-StackLayoutPanelContent";
  private static final String HEADER_STYLE = "gwt-StackLayoutPanelHeader";
  private static final String HEADER_STYLE_HOVERING = "gwt-StackLayoutPanelHeader-hovering";

  private static final int ANIMATION_TIME = 250;

  private LayoutPanel layoutPanel;
  private final Unit unit;
  private final ArrayList<LayoutData> layoutData = new ArrayList<LayoutData>();
  private int selectedIndex = -1;

  /**
   * Creates an empty stack panel.
   *
   * @param unit the unit to be used for layout
   */
  public StackLayoutPanel(Unit unit) {
    this.unit = unit;
    initWidget(layoutPanel = new LayoutPanel());
    setStyleName(WIDGET_STYLE);
  }

  public void add(Widget w) {
    assert false : "Single-argument add() is not supported for this widget";
  }

  /**
   * Adds a child widget to this stack, along with a widget representing the
   * stack header.
   *
   * @param widget the child widget to be added
   * @param header the html to be shown on its header
   * @param headerSize the size of the header widget
   */
  public void add(final Widget widget, SafeHtml header, double headerSize) {
    add(widget, header.asString(), true, headerSize);
  }
  
  /**
   * Adds a child widget to this stack, along with a widget representing the
   * stack header.
   * 
   * @param widget the child widget to be added
   * @param header the text to be shown on its header
   * @param asHtml <code>true</code> to treat the specified text as HTML
   * @param headerSize the size of the header widget
   */
  public void add(final Widget widget, String header, boolean asHtml, double headerSize) {
    insert(widget, header, asHtml, headerSize, getWidgetCount());
  }

  /**
   * Adds a child widget to this stack, along with a widget representing the
   * stack header.
   *
   * @param widget the child widget to be added
   * @param header the text to be shown on its header
   * @param headerSize the size of the header widget
   */
  public void add(final Widget widget, String header, double headerSize) {
    insert(widget, header, headerSize, getWidgetCount());
  }

  /**
   * Adds a child widget to this stack, along with a widget representing the
   * stack header.
   *
   * @param widget the child widget to be added
   * @param header the header widget
   * @param headerSize the size of the header widget
   */
  public void add(final Widget widget, Widget header, double headerSize) {
    insert(widget, header, headerSize, getWidgetCount());
  }

  public HandlerRegistration addBeforeSelectionHandler(
      BeforeSelectionHandler<Integer> handler) {
    return addHandler(handler, BeforeSelectionEvent.getType());
  }

  public HandlerRegistration addSelectionHandler(
      SelectionHandler<Integer> handler) {
    return addHandler(handler, SelectionEvent.getType());
  }

  public void clear() {
    layoutPanel.clear();
    layoutData.clear();
    selectedIndex = -1;
  }

  /**
   * Gets the widget in the stack header at the given index.
   *
   * @param index the index of the stack header to be retrieved
   * @return the header widget
   */
  public Widget getHeaderWidget(int index) {
    checkIndex(index);
    return layoutData.get(index).header.getWidget();
  }

  /**
   * Gets the widget in the stack header associated with the given child widget.
   *
   * @param child the child whose stack header is to be retrieved
   * @return the header widget
   */
  public Widget getHeaderWidget(Widget child) {
    checkChild(child);
    return getHeaderWidget(getWidgetIndex(child));
  }

  /**
   * Gets the currently-selected index.
   *
   * @return the selected index, or <code>-1</code> if none is selected
   */
  public int getVisibleIndex() {
    return selectedIndex;
  }

  /**
   * Gets the currently-selected widget.
   *
   * @return the selected widget, or <code>null</code> if none exist
   */
  public Widget getVisibleWidget() {
    if (selectedIndex == -1) {
      return null;
    }
    return getWidget(selectedIndex);
  }

  public Widget getWidget(int index) {
    return layoutPanel.getWidget(index * 2 + 1);
  }

  public int getWidgetCount() {
    return layoutPanel.getWidgetCount() / 2;
  }

  public int getWidgetIndex(IsWidget child) {
    return getWidgetIndex(asWidgetOrNull(child));
  }

  public int getWidgetIndex(Widget child) {
    int index = layoutPanel.getWidgetIndex(child);
    if (index == -1) {
      return index;
    }
    return (index - 1) / 2;
  }

  /**
   * Inserts a widget into the panel. If the Widget is already attached, it will
   * be moved to the requested index.
   *
   * @param child the widget to be added
   * @param html the safe html to be shown on its header
   * @param headerSize the size of the header widget
   * @param beforeIndex the index before which it will be inserted
   */
  public void insert(Widget child, SafeHtml html, double headerSize, 
      int beforeIndex) {
    insert(child, html.asString(), true, headerSize, beforeIndex);
  }
  
  /**
   * Inserts a widget into the panel. If the Widget is already attached, it will
   * be moved to the requested index.
   * 
   * @param child the widget to be added
   * @param text the text to be shown on its header
   * @param asHtml <code>true</code> to treat the specified text as HTML
   * @param headerSize the size of the header widget
   * @param beforeIndex the index before which it will be inserted
   */
  public void insert(Widget child, String text, boolean asHtml,
      double headerSize, int beforeIndex) {
    HTML contents = new HTML();
    if (asHtml) {
      contents.setHTML(text);
    } else {
      contents.setText(text);
    }
    insert(child, contents, headerSize, beforeIndex);
  }

  /**
   * Inserts a widget into the panel. If the Widget is already attached, it will
   * be moved to the requested index.
   *
   * @param child the widget to be added
   * @param text the text to be shown on its header
   * @param headerSize the size of the header widget
   * @param beforeIndex the index before which it will be inserted
   */
  public void insert(Widget child, String text, double headerSize, int beforeIndex) {
    insert(child, text, false, headerSize, beforeIndex);
  }

  /**
   * Inserts a widget into the panel. If the Widget is already attached, it will
   * be moved to the requested index.
   *
   * @param child the widget to be added
   * @param header the widget to be placed in the associated header
   * @param headerSize the size of the header widget
   * @param beforeIndex the index before which it will be inserted
   */
  public void insert(Widget child, Widget header, double headerSize,
      int beforeIndex) {
    insert(child, new Header(header), headerSize, beforeIndex);
  }

  public Iterator<Widget> iterator() {
    return new Iterator<Widget>() {
      int i = 0, last = -1;

      public boolean hasNext() {
        return i < layoutData.size();
      }

      public Widget next() {
        if (!hasNext()) {
          throw new NoSuchElementException();
        }
        return layoutData.get(last = i++).widget;
      }

      public void remove() {
        if (last < 0) {
          throw new IllegalStateException();
        }

        StackLayoutPanel.this.remove(layoutData.get(last).widget);
        i = last;
        last = -1;
      }
    };
  }

  @Override
  public void onResize() {
    layoutPanel.onResize();
  }

  public boolean remove(int index) {
    return remove(getWidget(index));
  }

  public boolean remove(Widget child) {
    if (child.getParent() != layoutPanel) {
      return false;
    }

    // Find the layoutData associated with this widget and remove it.
    for (int i = 0; i < layoutData.size(); ++i) {
      LayoutData data = layoutData.get(i);
      if (data.widget == child) {
        layoutPanel.remove(data.header);
        layoutPanel.remove(data.widget);

        data.header.removeStyleName(HEADER_STYLE);
        data.widget.removeStyleName(CONTENT_STYLE);

        layoutData.remove(i);

        if (selectedIndex == i) {
          selectedIndex = -1;
          if (layoutData.size() > 0) {
            showWidget(layoutData.get(0).widget);
          }
        }
        return true;
      }
    }

    return false;
  }

  /**
   * Sets a stack header's HTML contents.
   *
   * Use care when setting an object's HTML; it is an easy way to expose
   * script-based security problems. Consider using
   * {@link #setHeaderSafeHtml(int, SafeHtml)} or 
   * {@link #setHeaderText(int, String)} whenever possible.
   *
   * @param index the index of the header whose HTML is to be set
   * @param html the header's new HTML contents
   */
  public void setHeaderHTML(int index, String html) {
    checkIndex(index);
    LayoutData data = layoutData.get(index);

    Widget headerWidget = data.header.getWidget();
    assert headerWidget instanceof HasHTML : "Header widget does not implement HasHTML";
    ((HasHTML) headerWidget).setHTML(html);
  }

  /**
   * Sets a stack header's HTML contents.
   * 
   * @param index the index of the header whose HTML is to be set
   * @param html the header's new HTML contents
   */
  public void setHeaderHTML(int index, SafeHtml html) {
    setHeaderHTML(index, html.asString());
  }
  
  /**
   * Sets a stack header's text contents.
   *
   * @param index the index of the header whose text is to be set
   * @param text the object's new text
   */
  public void setHeaderText(int index, String text) {
    checkIndex(index);
    LayoutData data = layoutData.get(index);

    Widget headerWidget = data.header.getWidget();
    assert headerWidget instanceof HasText : "Header widget does not implement HasText";
    ((HasText) headerWidget).setText(text);
  }

  /**
   * Shows the widget at the specified index and fires events.
   *
   * @param index the index of the child widget to be shown.
   */
  public void showWidget(int index) {
    showWidget(index, true);
  }

  /**
   * Shows the widget at the specified index.
   *
   * @param index the index of the child widget to be shown.
   * @param fireEvents true to fire events, false not to
   */
  public void showWidget(int index, boolean fireEvents) {
    checkIndex(index);
    showWidget(index, ANIMATION_TIME, fireEvents);
  }

  /**
   * Shows the specified widget and fires events.
   *
   * @param child the child widget to be shown.
   */
  public void showWidget(Widget child) {
    showWidget(getWidgetIndex(child));
  }

  /**
   * Shows the specified widget.
   *
   * @param child the child widget to be shown.
   * @param fireEvents true to fire events, false not to
   */
  public void showWidget(Widget child, boolean fireEvents) {
    showWidget(getWidgetIndex(child), ANIMATION_TIME, fireEvents);
  }

  @Override
  protected void onLoad() {
    // When the widget becomes attached, update its layout.
    animate(0);
  }

  private void animate(int duration) {
    // Don't try to animate zero widgets.
    if (layoutData.size() == 0) {
      return;
    }

    double top = 0, bottom = 0;
    int i = 0;
    for (; i < layoutData.size(); ++i) {
      LayoutData data = layoutData.get(i);
      layoutPanel.setWidgetTopHeight(data.header, top, unit, data.headerSize,
          unit);

      top += data.headerSize;

      layoutPanel.setWidgetTopHeight(data.widget, top, unit, 0, unit);

      if (i == selectedIndex) {
        break;
      }
    }

    for (int j = layoutData.size() - 1; j > i; --j) {
      LayoutData data = layoutData.get(j);
      layoutPanel.setWidgetBottomHeight(data.header, bottom, unit,
          data.headerSize, unit);
      layoutPanel.setWidgetBottomHeight(data.widget, bottom, unit, 0, unit);
      bottom += data.headerSize;
    }

    LayoutData data = layoutData.get(selectedIndex);
    layoutPanel.setWidgetTopBottom(data.widget, top, unit, bottom, unit);

    layoutPanel.animate(duration);
  }

  private void checkChild(Widget child) {
    assert layoutPanel.getChildren().contains(child);
  }

  private void checkIndex(int index) {
    assert (index >= 0) && (index < getWidgetCount()) : "Index out of bounds";
  }

  private void insert(final Widget child, final Header header, double headerSize,
      int beforeIndex) {
    assert (beforeIndex >= 0) && (beforeIndex <= getWidgetCount()) : "beforeIndex out of bounds";

    // Check to see if the StackPanel already contains the Widget. If so,
    // remove it and see if we need to shift the position to the left.
    int idx = getWidgetIndex(child);
    if (idx != -1) {
      remove(child);
      if (idx < beforeIndex) {
        beforeIndex--;
      }
    }

    beforeIndex *= 2;
    layoutPanel.insert(child, beforeIndex);
    layoutPanel.insert(header, beforeIndex);

    layoutPanel.setWidgetLeftRight(header, 0, Unit.PX, 0, Unit.PX);
    layoutPanel.setWidgetLeftRight(child, 0, Unit.PX, 0, Unit.PX);

    LayoutData data = new LayoutData(child, header, headerSize);
    layoutData.add(data);

    header.addStyleName(HEADER_STYLE);
    child.addStyleName(CONTENT_STYLE);

    header.addClickHandler(new ClickHandler() {
      public void onClick(ClickEvent event) {
        showWidget(child);
      }
    });

    header.addMouseOutHandler(new MouseOutHandler() {
      public void onMouseOut(MouseOutEvent event) {
        header.removeStyleName(HEADER_STYLE_HOVERING);
      }
    });

    header.addMouseOverHandler(new MouseOverHandler() {
      public void onMouseOver(MouseOverEvent event) {
        header.addStyleName(HEADER_STYLE_HOVERING);
      }
    });

    if (selectedIndex == -1) {
      // If there's no visible widget, display the first one. The layout will
      // be updated onLoad().
      showWidget(0);
    }

    // If the widget is already attached, we must call animate() to update the
    // layout (if it's not yet attached, then onLoad() will do this).
    if (isAttached()) {
      animate(ANIMATION_TIME);
    }
  }

  private void showWidget(int index, final int duration, boolean fireEvents) {
    checkIndex(index);
    if (index == selectedIndex) {
      return;
    }

    // Fire the before selection event, giving the recipients a chance to
    // cancel the selection.
    if (fireEvents) {
      BeforeSelectionEvent<Integer> event = BeforeSelectionEvent.fire(this, index);
      if ((event != null) && event.isCanceled()) {
        return;
      }
    }

    selectedIndex = index;

    if (isAttached()) {
      animate(duration);
    }

    // Fire the selection event.
    if (fireEvents) {
      SelectionEvent.fire(this, index);
    }
  }
}
