/*
 * 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.aria.client.Roles;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasAllKeyHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
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 com.google.gwt.safehtml.shared.annotations.IsSafeHtml;
import com.google.gwt.safehtml.shared.annotations.SuppressIsSafeHtmlCastCheck;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;

/**
 * A horizontal bar of folder-style tabs, most commonly used as part of a
 * {@link com.google.gwt.user.client.ui.TabPanel}.
 * <p>
 * <img class='gallery' src='doc-files/TabBar.png'/>
 * </p>
 * <h3>CSS Style Rules</h3>
 * <ul class='css'>
 * <li>.gwt-TabBar { the tab bar itself }</li>
 * <li>.gwt-TabBar .gwt-TabBarFirst { the left edge of the bar }</li>
 * <li>.gwt-TabBar .gwt-TabBarFirst-wrapper { table cell around the left edge }
 * </li>
 * <li>.gwt-TabBar .gwt-TabBarRest { the right edge of the bar }</li>
 * <li>.gwt-TabBar .gwt-TabBarRest-wrapper { table cell around the right edge }
 * </li>
 * <li>.gwt-TabBar .gwt-TabBarItem { unselected tabs }</li>
 * <li>.gwt-TabBar .gwt-TabBarItem-disabled { disabled tabs }</li>
 * <li>.gwt-TabBar .gwt-TabBarItem-wrapper { table cell around tab }</li>
 * <li>.gwt-TabBar .gwt-TabBarItem-wrapper-disabled { table cell around disabled tab }</li>
 * <li>.gwt-TabBar .gwt-TabBarItem-selected { additional style for selected }</li>
 * <p>
 * <h3>Example</h3>
 * {@example com.google.gwt.examples.TabBarExample}
 * </p>
 */
@SuppressWarnings("deprecation")
public class TabBar extends Composite implements SourcesTabEvents,
    HasBeforeSelectionHandlers<Integer>, HasSelectionHandlers<Integer>,
    ClickListener, KeyboardListener {

  /**
   * Set of characteristic interfaces supported by {@link TabBar} tabs.
   *
   * Note that this set might expand over time, so implement this interface at
   * your own risk.
   */
  public interface Tab extends HasAllKeyHandlers, HasClickHandlers, HasWordWrap {
    /**
     * Check if the underlying widget implements {@link HasWordWrap}.
     *
     * @return true if the widget implements {@link HasWordWrap}
     */
    boolean hasWordWrap();
  }

  /**
   * <code>ClickDelegatePanel</code> decorates any widget with the minimal
   * amount of machinery to receive clicks for delegation to the parent.
   * {@link SourcesClickEvents} is not implemented due to the fact that only a
   * single observer is needed.
   */
  private class ClickDelegatePanel extends Composite implements Tab {
    private SimplePanel focusablePanel;
    private boolean enabled = true;

    ClickDelegatePanel(Widget child) {

      focusablePanel = new SimplePanel(FocusPanel.impl.createFocusable());
      focusablePanel.setWidget(child);
      SimplePanel wrapperWidget = createTabTextWrapper();
      if (wrapperWidget == null) {
        initWidget(focusablePanel);
      } else {
        wrapperWidget.setWidget(focusablePanel);
        initWidget(wrapperWidget);
      }

      sinkEvents(Event.ONCLICK | Event.ONKEYDOWN);
    }

    @Override
    public HandlerRegistration addClickHandler(ClickHandler handler) {
      return addHandler(handler, ClickEvent.getType());
    }

    @Override
    public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) {
      return addHandler(handler, KeyDownEvent.getType());
    }

    @Override
    public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
      return addDomHandler(handler, KeyPressEvent.getType());
    }

    @Override
    public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
      return addDomHandler(handler, KeyUpEvent.getType());
    }

    public SimplePanel getFocusablePanel() {
      return focusablePanel;
    }

    @Override
    public boolean getWordWrap() {
      if (hasWordWrap()) {
        return ((HasWordWrap) focusablePanel.getWidget()).getWordWrap();
      }
      throw new UnsupportedOperationException(
          "Widget does not implement HasWordWrap");
    }

    @Override
    public boolean hasWordWrap() {
      return focusablePanel.getWidget() instanceof HasWordWrap;
    }

    public boolean isEnabled() {
      return enabled;
    }

    @Override
    public void onBrowserEvent(Event event) {
      if (!enabled) {
        return;
      }

      // No need for call to super.
      switch (DOM.eventGetType(event)) {
        case Event.ONCLICK:
          TabBar.this.selectTabByTabWidget(this);
          TabBar.this.onClick(this);
          break;

        case Event.ONKEYDOWN:
          if (((char) event.getKeyCode()) == KeyCodes.KEY_ENTER) {
            TabBar.this.selectTabByTabWidget(this);
          }
          TabBar.this.onKeyDown(this, (char) event.getKeyCode(),
              KeyboardListenerCollection.getKeyboardModifiers(event));
          break;
      }
      super.onBrowserEvent(event);
    }

    public void setEnabled(boolean enabled) {
      this.enabled = enabled;
    }

    @Override
    public void setWordWrap(boolean wrap) {
      if (hasWordWrap()) {
        ((HasWordWrap) focusablePanel.getWidget()).setWordWrap(wrap);
      } else {
        throw new UnsupportedOperationException(
            "Widget does not implement HasWordWrap");
      }
    }
  }

  private static final String STYLENAME_DEFAULT = "gwt-TabBarItem";
  private HorizontalPanel panel = new HorizontalPanel();
  private Widget selectedTab;

  /**
   * Creates an empty tab bar.
   */
  public TabBar() {
    initWidget(panel);
    sinkEvents(Event.ONCLICK);
    setStyleName("gwt-TabBar");

    // Add a11y role "tablist"
    Roles.getTablistRole().set(panel.getElement());

    panel.setVerticalAlignment(HasVerticalAlignment.ALIGN_BOTTOM);

    HTML first = new HTML("&nbsp;", true), rest = new HTML("&nbsp;", true);
    first.setStyleName("gwt-TabBarFirst");
    rest.setStyleName("gwt-TabBarRest");
    first.setHeight("100%");
    rest.setHeight("100%");

    panel.add(first);
    panel.add(rest);
    first.setHeight("100%");
    panel.setCellHeight(first, "100%");
    panel.setCellWidth(rest, "100%");
    setStyleName(first.getElement().getParentElement(),
        "gwt-TabBarFirst-wrapper");
    setStyleName(rest.getElement().getParentElement(), "gwt-TabBarRest-wrapper");
  }

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

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

  /**
   * Adds a new tab with the specified text.
   *
   * @param html the new tab's html
   */
  public void addTab(SafeHtml html) {
    addTab(html.asString(), true);
  }

  /**
   * Adds a new tab with the specified text.
   *
   * @param text the new tab's text
   */
  public void addTab(String text) {
    insertTab(text, getTabCount());
  }

  /**
   * Adds a new tab with the specified text.
   *
   * @param text the new tab's text
   * @param asHTML <code>true</code> to treat the specified text as html
   */
  public void addTab(@IsSafeHtml String text, boolean asHTML) {
    insertTab(text, asHTML, getTabCount());
  }

  /**
   * Adds a new tab with the specified widget.
   *
   * @param widget the new tab's widget
   */
  public void addTab(Widget widget) {
    insertTab(widget, getTabCount());
  }

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

  /**
   * Gets the tab that is currently selected.
   *
   * @return the selected tab
   */
  public int getSelectedTab() {
    if (selectedTab == null) {
      return -1;
    }
    return panel.getWidgetIndex(selectedTab) - 1;
  }

  /**
   * Gets the given tab.
   *
   * This method is final because the Tab interface will expand. Therefore
   * it is highly likely that subclasses which implemented this method would end up
   * breaking.
   *
   * @param index the tab's index
   * @return the tab wrapper
   */
  public final Tab getTab(int index) {
    if (index >= getTabCount()) {
      return null;
    }
    ClickDelegatePanel p = (ClickDelegatePanel) panel.getWidget(index + 1);
    return p;
  }

  /**
   * Gets the number of tabs present.
   *
   * @return the tab count
   */
  public int getTabCount() {
    return panel.getWidgetCount() - 2;
  }

  /**
   * Gets the specified tab's HTML.
   *
   * @param index the index of the tab whose HTML is to be retrieved
   * @return the tab's HTML
   */
  public String getTabHTML(int index) {
    if (index >= getTabCount()) {
      return null;
    }
    ClickDelegatePanel delPanel = (ClickDelegatePanel) panel.getWidget(index + 1);
    SimplePanel focusablePanel = delPanel.getFocusablePanel();
    Widget widget = focusablePanel.getWidget();
    if (widget instanceof HTML) {
      return ((HTML) widget).getHTML();
    } else if (widget instanceof Label) {
      return ((Label) widget).getText();
    } else {
      // This will be a focusable panel holding a user-supplied widget.
      return focusablePanel.getElement().getParentElement().getInnerHTML();
    }
  }

  /**
   * Inserts a new tab at the specified index.
   *
   * @param html the new tab's html
   * @param beforeIndex the index before which this tab will be inserted
   */
  public void insertTab(SafeHtml html, int beforeIndex) {
    insertTab(html.asString(), true, beforeIndex);
  }

  /**
   * Inserts a new tab at the specified index.
   *
   * @param text the new tab's text
   * @param asHTML <code>true</code> to treat the specified text as HTML
   * @param beforeIndex the index before which this tab will be inserted
   */
  public void insertTab(@IsSafeHtml String text, boolean asHTML, int beforeIndex) {
    checkInsertBeforeTabIndex(beforeIndex);

    Label item;
    if (asHTML) {
      item = new HTML(text);
    } else {
      item = new Label(text);
    }

    item.setWordWrap(false);
    insertTabWidget(item, beforeIndex);
  }

  /**
   * Inserts a new tab at the specified index.
   *
   * @param text the new tab's text
   * @param beforeIndex the index before which this tab will be inserted
   */
  @SuppressIsSafeHtmlCastCheck
  public void insertTab(String text, int beforeIndex) {
    insertTab(text, false, beforeIndex);
  }

  /**
   * Inserts a new tab at the specified index.
   *
   * @param widget widget to be used in the new tab
   * @param beforeIndex the index before which this tab will be inserted
   */
  public void insertTab(Widget widget, int beforeIndex) {
    insertTabWidget(widget, beforeIndex);
  }

  /**
   * Check if a tab is enabled or disabled. If disabled, the user cannot select
   * the tab.
   *
   * @param index the index of the tab
   * @return true if the tab is enabled, false if disabled
   */
  public boolean isTabEnabled(int index) {
    assert (index >= 0) && (index < getTabCount()) : "Tab index out of bounds";
    ClickDelegatePanel delPanel = (ClickDelegatePanel) panel.getWidget(index + 1);
    return delPanel.isEnabled();
  }

  /**
   * @deprecated add a {@link BeforeSelectionHandler} instead. Alternatively, if
   * you need to access to the individual tabs, add a click handler to each
   * {@link Tab} element instead.
   */
  @Override
  @Deprecated
  public void onClick(Widget sender) {
  }

  /**
   * @deprecated add a key down handler to the individual {@link Tab} objects
   *  instead.
   */
  @Override
  @Deprecated
  public void onKeyDown(Widget sender, char keyCode, int modifiers) {
  }

  /**
   * @deprecated this method has been doing nothing for the entire last release,
   * if what you wanted to do was to listen to key press events on tabs, add the
   * key press handler to the individual tab wrappers instead.
   */
  @Override
  @Deprecated
  public void onKeyPress(Widget sender, char keyCode, int modifiers) {
  }

  /**
   * @deprecated this method has been doing nothing for the entire last release,
   * if what you wanted to do was to listen to key up events on tabs, add the
   * key up handler to the individual tab wrappers instead.
   *
   */
  @Override
  @Deprecated
  public void onKeyUp(Widget sender, char keyCode, int modifiers) {
  }

  /**
   * Removes the tab at the specified index.
   *
   * @param index the index of the tab to be removed
   */
  public void removeTab(int index) {
    checkTabIndex(index);

    // (index + 1) to account for 'first' placeholder widget.
    Widget toRemove = panel.getWidget(index + 1);
    if (toRemove == selectedTab) {
      selectedTab = null;
    }
    panel.remove(toRemove);
  }

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

  /**
   * Programmatically selects the specified tab and fires events. Use index -1
   * to specify that no tab should be selected.
   *
   * @param index the index of the tab to be selected
   * @return <code>true</code> if successful, <code>false</code> if the change
   * is denied by the {@link BeforeSelectionHandler}.
   */
  public boolean selectTab(int index) {
    return selectTab(index, true);
  }

  /**
   * Programmatically selects the specified tab. Use index -1 to specify that no
   * tab should be selected.
   *
   * @param index the index of the tab to be selected
   * @param fireEvents true to fire events, false not to
   * @return <code>true</code> if successful, <code>false</code> if the change
   * is denied by the {@link BeforeSelectionHandler}.
   */
  public boolean selectTab(int index, boolean fireEvents) {
    checkTabIndex(index);

    if (fireEvents) {
      BeforeSelectionEvent<?> event = BeforeSelectionEvent.fire(this, index);
      if (event != null && event.isCanceled()) {
        return false;
      }
    }

    // Check for -1.
    setSelectionStyle(selectedTab, false);
    if (index == -1) {
      selectedTab = null;
      return true;
    }

    selectedTab = panel.getWidget(index + 1);
    setSelectionStyle(selectedTab, true);
    if (fireEvents) {
      SelectionEvent.fire(this, index);
    }
    return true;
  }

  /**
   * Enable or disable a tab. When disabled, users cannot select the tab.
   *
   * @param index the index of the tab to enable or disable
   * @param enabled true to enable, false to disable
   */
  public void setTabEnabled(int index, boolean enabled) {
    assert (index >= 0) && (index < getTabCount()) : "Tab index out of bounds";

    // Style the wrapper
    ClickDelegatePanel delPanel = (ClickDelegatePanel) panel.getWidget(index + 1);
    delPanel.setEnabled(enabled);
    setStyleName(delPanel.getElement(), "gwt-TabBarItem-disabled", !enabled);
    setStyleName(delPanel.getElement().getParentElement(),
        "gwt-TabBarItem-wrapper-disabled", !enabled);
  }

  /**
   * Sets a tab's contents via HTML.
   *
   * Use care when setting an object's HTML; it is an easy way to expose
   * script-based security problems. Consider using
   * {@link #setTabText(int, String)} or {@link #setTabHTML(int, SafeHtml)}
   * whenever possible.
   *
   * @param index the index of the tab whose HTML is to be set
   * @param html the tab new HTML
   */
  public void setTabHTML(int index, @IsSafeHtml String html) {
    assert (index >= 0) && (index < getTabCount()) : "Tab index out of bounds";

    ClickDelegatePanel delPanel = (ClickDelegatePanel) panel.getWidget(index + 1);
    SimplePanel focusablePanel = delPanel.getFocusablePanel();
    focusablePanel.setWidget(new HTML(html, false));
  }

  /**
   * Sets a tab's contents via safe html.
   *
   * @param index the index of the tab whose HTML is to be set
   * @param html the tab new HTML
   */
  public void setTabHTML(int index, SafeHtml html) {
    setTabHTML(index, html.asString());
  }

  /**
   * Sets a tab's text contents.
   *
   * @param index the index of the tab whose text is to be set
   * @param text the object's new text
   */
  public void setTabText(int index, String text) {
    assert (index >= 0) && (index < getTabCount()) : "Tab index out of bounds";

    ClickDelegatePanel delPanel = (ClickDelegatePanel) panel.getWidget(index + 1);
    SimplePanel focusablePanel = delPanel.getFocusablePanel();

    // It is not safe to check if the current widget is an instanceof Label and
    // reuse it here because HTML is an instanceof Label. Leaving an HTML would
    // throw off the results of getTabHTML(int).
    focusablePanel.setWidget(new Label(text, false));
  }

  /**
   * 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;
  }

  /**
   * Inserts a new tab at the specified index.
   *
   * @param widget widget to be used in the new tab
   * @param beforeIndex the index before which this tab will be inserted
   */
  protected void insertTabWidget(Widget widget, int beforeIndex) {
    checkInsertBeforeTabIndex(beforeIndex);

    ClickDelegatePanel delWidget = new ClickDelegatePanel(widget);
    delWidget.setStyleName(STYLENAME_DEFAULT);

    // Add a11y role "tab"
    SimplePanel focusablePanel = delWidget.getFocusablePanel();
    Roles.getTabRole().set(focusablePanel.getElement());

    panel.insert(delWidget, beforeIndex + 1);

    setStyleName(DOM.getParent(delWidget.getElement()), STYLENAME_DEFAULT
        + "-wrapper", true);
  }

  /**
   * <b>Affected Elements:</b>
   * <ul>
   * <li>-tab# = The element containing the contents of the tab.</li>
   * <li>-tab-wrapper# = The cell containing the tab at the index.</li>
   * </ul>
   *
   * @see UIObject#onEnsureDebugId(String)
   */
  @Override
  protected void onEnsureDebugId(String baseID) {
    super.onEnsureDebugId(baseID);

    int numTabs = getTabCount();
    for (int i = 0; i < numTabs; i++) {
      ClickDelegatePanel delPanel = (ClickDelegatePanel) panel.getWidget(i + 1);
      SimplePanel focusablePanel = delPanel.getFocusablePanel();
      ensureDebugId(focusablePanel.getContainerElement(), baseID, "tab" + i);
      ensureDebugId(DOM.getParent(delPanel.getElement()), baseID, "tab-wrapper"
          + i);
    }
  }

  private void checkInsertBeforeTabIndex(int beforeIndex) {
    if ((beforeIndex < 0) || (beforeIndex > getTabCount())) {
      throw new IndexOutOfBoundsException();
    }
  }

  private void checkTabIndex(int index) {
    if ((index < -1) || (index >= getTabCount())) {
      throw new IndexOutOfBoundsException();
    }
  }

  /**
   * Selects the tab corresponding to the widget for the tab. To be clear the
   * widget for the tab is not the widget INSIDE of the tab; it is the widget
   * used to represent the tab itself.
   *
   * @param tabWidget The widget for the tab to be selected
   * @return true if the tab corresponding to the widget for the tab could
   * located and selected, false otherwise
   */
  private boolean selectTabByTabWidget(Widget tabWidget) {
    int numTabs = panel.getWidgetCount() - 1;

    for (int i = 1; i < numTabs; ++i) {
      if (panel.getWidget(i) == tabWidget) {
        return selectTab(i - 1);
      }
    }

    return false;
  }

  private void setSelectionStyle(Widget item, boolean selected) {
    if (item != null) {
      if (selected) {
        item.addStyleName("gwt-TabBarItem-selected");
        setStyleName(DOM.getParent(item.getElement()),
            "gwt-TabBarItem-wrapper-selected", true);
      } else {
        item.removeStyleName("gwt-TabBarItem-selected");
        setStyleName(DOM.getParent(item.getElement()),
            "gwt-TabBarItem-wrapper-selected", false);
      }
    }
  }
}
