/*
 * 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.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 java.util.Iterator;

/**
 * A panel that represents a tabbed set of pages, each of which contains another
 * widget. Its child widgets are shown as the user selects the various tabs
 * associated with them. The tabs can contain arbitrary HTML.
 *
 * <p>
 * This widget will <em>only</em> work in quirks mode. If your application is in
 * Standards Mode, use {@link TabLayoutPanel} instead.
 * </p>
 *
 * <p>
 * <img class='gallery' src='doc-files/TabPanel.png'/>
 * </p>
 *
 * <p>
 * Note that this widget is not a panel per se, but rather a
 * {@link com.google.gwt.user.client.ui.Composite} that aggregates a
 * {@link com.google.gwt.user.client.ui.TabBar} and a
 * {@link com.google.gwt.user.client.ui.DeckPanel}. It does, however, implement
 * {@link com.google.gwt.user.client.ui.HasWidgets}.
 * </p>
 *
 * <h3>CSS Style Rules</h3>
 * <ul class='css'>
 * <li>.gwt-TabPanel { the tab panel itself }</li>
 * <li>.gwt-TabPanelBottom { the bottom section of the tab panel
 * (the deck containing the widget) }</li>
 * </ul>
 *
 * <p>
 * <h3>Example</h3>
 * {@example com.google.gwt.examples.TabPanelExample}
 * </p>
 *
 * @see TabLayoutPanel
 */

// Cannot do anything about tab panel implementing TabListener until next
// release
@SuppressWarnings("deprecation")
public class TabPanel extends Composite implements TabListener,
    SourcesTabEvents, HasWidgets, HasAnimation, IndexedPanel.ForIsWidget,
    HasBeforeSelectionHandlers<Integer>, HasSelectionHandlers<Integer> {
  /**
   * This extension of DeckPanel overrides the public mutator methods to prevent
   * external callers from adding to the state of the DeckPanel.
   * <p>
   * Removal of Widgets is supported so that WidgetCollection.WidgetIterator
   * operates as expected.
   * </p>
   * <p>
   * We ensure that the DeckPanel cannot become of of sync with its associated
   * TabBar by delegating all mutations to the TabBar to this implementation of
   * DeckPanel.
   * </p>
   */
  private static class TabbedDeckPanel extends DeckPanel {
    private final UnmodifiableTabBar tabBar;

    public TabbedDeckPanel(UnmodifiableTabBar tabBar) {
      this.tabBar = tabBar;
    }

    @Override
    public void add(Widget w) {
      throw new UnsupportedOperationException(
          "Use TabPanel.add() to alter the DeckPanel");
    }

    @Override
    public void clear() {
      throw new UnsupportedOperationException(
          "Use TabPanel.clear() to alter the DeckPanel");
    }

    @Override
    public void insert(Widget w, int beforeIndex) {
      throw new UnsupportedOperationException(
          "Use TabPanel.insert() to alter the DeckPanel");
    }

    @Override
    public boolean remove(Widget w) {
      // Removal of items from the TabBar is delegated to the DeckPanel
      // to ensure consistency
      int idx = getWidgetIndex(w);
      if (idx != -1) {
        tabBar.removeTabProtected(idx);
        return super.remove(w);
      }

      return false;
    }

    protected void insertProtected(Widget w, String tabText, boolean asHTML,
        int beforeIndex) {

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

      tabBar.insertTabProtected(tabText, asHTML, beforeIndex);
      super.insert(w, beforeIndex);
    }

    protected void insertProtected(Widget w, Widget tabWidget, int beforeIndex) {

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

      tabBar.insertTabProtected(tabWidget, beforeIndex);
      super.insert(w, beforeIndex);
    }
  }

  /**
   * This extension of TabPanel overrides the public mutator methods to prevent
   * external callers from modifying the state of the TabBar.
   */
  private class UnmodifiableTabBar extends TabBar {
    @Override
    public void insertTab(String text, boolean asHTML, int beforeIndex) {
      throw new UnsupportedOperationException(
          "Use TabPanel.insert() to alter the TabBar");
    }

    @Override
    public void insertTab(Widget widget, int beforeIndex) {
      throw new UnsupportedOperationException(
          "Use TabPanel.insert() to alter the TabBar");
    }

    public void insertTabProtected(String text, boolean asHTML, int beforeIndex) {
      super.insertTab(text, asHTML, beforeIndex);
    }

    public void insertTabProtected(Widget widget, int beforeIndex) {
      super.insertTab(widget, beforeIndex);
    }

    @Override
    public void removeTab(int index) {
      // It's possible for removeTab() to function correctly, but it's
      // preferable to have only TabbedDeckPanel.remove() be operable,
      // especially since TabBar does not export an Iterator over its values.
      throw new UnsupportedOperationException(
          "Use TabPanel.remove() to alter the TabBar");
    }

    public void removeTabProtected(int index) {
      super.removeTab(index);
    }

    @Override
    protected SimplePanel createTabTextWrapper() {
      return TabPanel.this.createTabTextWrapper();
    }
  }

  private final UnmodifiableTabBar tabBar = new UnmodifiableTabBar();
  private final TabbedDeckPanel deck = new TabbedDeckPanel(tabBar);

  /**
   * Creates an empty tab panel.
   */
  public TabPanel() {
    VerticalPanel panel = new VerticalPanel();
    panel.add(tabBar);
    panel.add(deck);

    panel.setCellHeight(deck, "100%");
    tabBar.setWidth("100%");

    tabBar.addTabListener(this);
    initWidget(panel);
    setStyleName("gwt-TabPanel");
    deck.setStyleName("gwt-TabPanelBottom");
    // Add a11y role "tabpanel"
    Accessibility.setRole(deck.getElement(), Accessibility.ROLE_TABPANEL);
  }

  /**
   * Convenience overload to allow {@link IsWidget} to be used directly.
   */
  public void add(IsWidget w, IsWidget tabWidget) {
    add(asWidgetOrNull(w), asWidgetOrNull(tabWidget));
  }

  /**
   * Convenience overload to allow {@link IsWidget} to be used directly.
   */
  public void add(IsWidget w, String tabText) {
    add(asWidgetOrNull(w), tabText);
  }

  /**
   * Convenience overload to allow {@link IsWidget} to be used directly.
   */
  public void add(IsWidget w, String tabText, boolean asHTML) {
    add(asWidgetOrNull(w), tabText, asHTML);
  }

  public void add(Widget w) {
    throw new UnsupportedOperationException(
        "A tabText parameter must be specified with add().");
  }

  /**
   * Adds a widget to the tab panel. If the Widget is already attached to the
   * TabPanel, it will be moved to the right-most index.
   *
   * @param w the widget to be added
   * @param tabText the text to be shown on its tab
   */
  public void add(Widget w, String tabText) {
    insert(w, tabText, getWidgetCount());
  }

  /**
   * Adds a widget to the tab panel. If the Widget is already attached to the
   * TabPanel, it will be moved to the right-most index.
   *
   * @param w the widget to be added
   * @param tabText the text to be shown on its tab
   * @param asHTML <code>true</code> to treat the specified text as HTML
   */
  public void add(Widget w, String tabText, boolean asHTML) {
    insert(w, tabText, asHTML, getWidgetCount());
  }

  /**
   * Adds a widget to the tab panel. If the Widget is already attached to the
   * TabPanel, it will be moved to the right-most index.
   *
   * @param w the widget to be added
   * @param tabWidget the widget to be shown in the tab
   */
  public void add(Widget w, Widget tabWidget) {
    insert(w, tabWidget, getWidgetCount());
  }

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

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

  /**
   * @deprecated Use {@link #addBeforeSelectionHandler} and {@link
   * #addSelectionHandler} instead
   */
  @Deprecated
  public void addTabListener(TabListener listener) {
    ListenerWrapper.WrappedTabListener.add(this, listener);
  }

  public void clear() {
    while (getWidgetCount() > 0) {
      remove(getWidget(0));
    }
  }

  /**
   * Gets the deck panel within this tab panel. Adding or removing Widgets from
   * the DeckPanel is not supported and will throw
   * UnsupportedOperationExceptions.
   *
   * @return the deck panel
   */
  public DeckPanel getDeckPanel() {
    return deck;
  }

  /**
   * Gets the tab bar within this tab panel. Adding or removing tabs from from
   * the TabBar is not supported and will throw UnsupportedOperationExceptions.
   *
   * @return the tab bar
   */
  public TabBar getTabBar() {
    return tabBar;
  }

  public Widget getWidget(int index) {
    return deck.getWidget(index);
  }

  public int getWidgetCount() {
    return deck.getWidgetCount();
  }

  /**
   * Convenience overload to allow {@link IsWidget} to be used directly.
   */
  public int getWidgetIndex(IsWidget child) {
    return getWidgetIndex(asWidgetOrNull(child));
  }

  public int getWidgetIndex(Widget widget) {
    return deck.getWidgetIndex(widget);
  }

  /**
   * Convenience overload to allow {@link IsWidget} to be used directly.
   */
  public void insert(IsWidget widget, IsWidget tabWidget, int beforeIndex) {
    insert(asWidgetOrNull(widget), asWidgetOrNull(tabWidget), beforeIndex);
  }

  /**
   * Convenience overload to allow {@link IsWidget} to be used directly.
   */
  public void insert(IsWidget widget, String tabText, boolean asHTML,
      int beforeIndex) {
    insert(asWidgetOrNull(widget), tabText, asHTML, beforeIndex);
  }

  /**
   * Convenience overload to allow {@link IsWidget} to be used directly.
   */
  public void insert(IsWidget widget, String tabText, int beforeIndex) {
    insert(asWidgetOrNull(widget), tabText, beforeIndex);
  }

  /**
   * Inserts a widget into the tab panel. If the Widget is already attached to
   * the TabPanel, it will be moved to the requested index.
   *
   * @param widget the widget to be inserted
   * @param tabText the text to be shown on its tab
   * @param asHTML <code>true</code> to treat the specified text as HTML
   * @param beforeIndex the index before which it will be inserted
   */
  public void insert(Widget widget, String tabText, boolean asHTML,
      int beforeIndex) {
    // Delegate updates to the TabBar to our DeckPanel implementation
    deck.insertProtected(widget, tabText, asHTML, beforeIndex);
  }

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

  /**
   * Inserts a widget into the tab panel. If the Widget is already attached to
   * the TabPanel, it will be moved to the requested index.
   *
   * @param widget the widget to be inserted.
   * @param tabWidget the widget to be shown on its tab.
   * @param beforeIndex the index before which it will be inserted.
   */
  public void insert(Widget widget, Widget tabWidget, int beforeIndex) {
    // Delegate updates to the TabBar to our DeckPanel implementation
    deck.insertProtected(widget, tabWidget, beforeIndex);
  }

  public boolean isAnimationEnabled() {
    return deck.isAnimationEnabled();
  }

  public Iterator<Widget> iterator() {
    // The Iterator returned by DeckPanel supports removal and will invoke
    // TabbedDeckPanel.remove(), which is an active function.
    return deck.iterator();
  }

  /**
   * @deprecated Use {@link BeforeSelectionHandler#onBeforeSelection} instead
   */
  @Deprecated
  public boolean onBeforeTabSelected(SourcesTabEvents sender, int tabIndex) {
    BeforeSelectionEvent<Integer> event = BeforeSelectionEvent.fire(this, tabIndex);
    return event == null || !event.isCanceled();
  }

  /**
   * @deprecated Use {@link SelectionHandler#onSelection} instead
   */
  @Deprecated
  public void onTabSelected(SourcesTabEvents sender, int tabIndex) {
    deck.showWidget(tabIndex);
    SelectionEvent.fire(this, tabIndex);
  }

  public boolean remove(int index) {
    // Delegate updates to the TabBar to our DeckPanel implementation
    return deck.remove(index);
  }

  /**
   * Removes the given widget, and its associated tab.
   *
   * @param widget the widget to be removed
   */
  public boolean remove(Widget widget) {
    // Delegate updates to the TabBar to our DeckPanel implementation
    return deck.remove(widget);
  }

  /**
   * @deprecated Use the {@link HandlerRegistration#removeHandler}
   * method on the object returned by and add*Handler method instead
   */
  @Deprecated
  public void removeTabListener(TabListener listener) {
    ListenerWrapper.WrappedTabListener.remove(this, listener);
  }

  /**
   * Programmatically selects the specified tab and fires events.
   *
   * @param index the index of the tab to be selected
   */
  public void selectTab(int index) {
    selectTab(index, true);
  }

  /**
   * Programmatically selects the specified tab.
   *
   * @param index the index of the tab to be selected
   * @param fireEvents true to fire events, false not to
   */
  public void selectTab(int index, boolean fireEvents) {
    tabBar.selectTab(index, fireEvents);
  }

  public void setAnimationEnabled(boolean enable) {
    deck.setAnimationEnabled(enable);
  }

  /**
   * Create a {@link SimplePanel} that will wrap the contents in a tab.
   * Subclasses can use this method to wrap tabs in decorator panels.
   *
   * @return a {@link SimplePanel} to wrap the tab contents, or null to leave
   *         tabs unwrapped
   */
  protected SimplePanel createTabTextWrapper() {
    return null;
  }

  /**
   * <b>Affected Elements:</b>
   * <ul>
   * <li>-bar = The tab bar.</li>
   * <li>-bar-tab# = The element containing the content of the tab itself.</li>
   * <li>-bar-tab-wrapper# = The cell containing the tab at the index.</li>
   * <li>-bottom = The panel beneath the tab bar.</li>
   * </ul>
   *
   * @see UIObject#onEnsureDebugId(String)
   */
  @Override
  protected void onEnsureDebugId(String baseID) {
    super.onEnsureDebugId(baseID);
    tabBar.ensureDebugId(baseID + "-bar");
    deck.ensureDebugId(baseID + "-bottom");
  }
}
