/*
 * 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.safehtml.shared.SafeHtml;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;

/**
 * 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 quirks mode. If your application is in
 * Standards Mode, use {@link StackLayoutPanel} instead.
 * </p>
 *
 * <p>
 * <img class='gallery' src='doc-files/StackPanel.png'/>
 * </p>
 * <h3>CSS Style Rules</h3>
 * <ul class='css'>
 * <li>.gwt-StackPanel { the panel itself }</li>
 * <li>.gwt-StackPanel .gwt-StackPanelItem { unselected items }</li>
 * <li>.gwt-StackPanel .gwt-StackPanelItem-selected { selected items }</li>
 * <li>.gwt-StackPanel .gwt-StackPanelContent { the wrapper around the contents
 * of the item }</li>
 * </ul>
 * <p>
 * <h3>Example</h3>
 * {@example com.google.gwt.examples.StackPanelExample}
 * </p>
 *
 * @see StackLayoutPanel
 */
public class StackPanel extends ComplexPanel implements InsertPanel.ForIsWidget {

  private static final String DEFAULT_STYLENAME = "gwt-StackPanel";
  private static final String DEFAULT_ITEM_STYLENAME = DEFAULT_STYLENAME
      + "Item";

  private Element body;
  private int visibleStack = -1;

  /**
   * Creates an empty stack panel.
   */
  public StackPanel() {
    Element table = DOM.createTable();
    setElement(table);

    body = DOM.createTBody();
    DOM.appendChild(table, body);
    table.setPropertyInt("cellSpacing", 0);
    table.setPropertyInt("cellPadding", 0);

    DOM.sinkEvents(table, Event.ONCLICK);
    setStyleName(DEFAULT_STYLENAME);
  }

  @Override
  public void add(Widget w) {
    insert(w, getWidgetCount());
  }

  /**
   * Adds a new child with the given widget and header.
   *
   * @param w the widget to be added
   * @param stackText the header text associated with this widget
   */
  public void add(Widget w, String stackText) {
    add(w, stackText, false);
  }

  /**
   * Adds a new child with the given widget and header, optionally interpreting
   * the header as HTML.
   *
   * @param w the widget to be added
   * @param stackHtml the header html associated with this widget
   */
  public void add(Widget w, SafeHtml stackHtml) {
    add(w, stackHtml.asString(), true);
  }

  /**
   * Adds a new child with the given widget and header, optionally interpreting
   * the header as HTML.
   *
   * @param w the widget to be added
   * @param stackText the header text associated with this widget
   * @param asHTML <code>true</code> to treat the specified text as HTML
   */
  public void add(Widget w, String stackText, boolean asHTML) {
    add(w);
    setStackText(getWidgetCount() - 1, stackText, asHTML);
  }

  /**
   * Gets the currently selected child index.
   *
   * @return selected child
   */
  public int getSelectedIndex() {
    return visibleStack;
  }

  public void insert(IsWidget w, int beforeIndex) {
    insert(asWidgetOrNull(w), beforeIndex);
  }

  public void insert(Widget w, int beforeIndex) {
    // header
    Element trh = DOM.createTR();
    Element tdh = DOM.createTD();
    DOM.appendChild(trh, tdh);
    DOM.appendChild(tdh, createHeaderElem());

    // body
    Element trb = DOM.createTR();
    Element tdb = DOM.createTD();
    DOM.appendChild(trb, tdb);

    // DOM indices are 2x logical indices; 2 dom elements per stack item
    beforeIndex = adjustIndex(w, beforeIndex);
    int effectiveIndex = beforeIndex * 2;

    // this ordering puts the body below the header
    DOM.insertChild(body, trb, effectiveIndex);
    DOM.insertChild(body, trh, effectiveIndex);

    // header styling
    setStyleName(tdh, DEFAULT_ITEM_STYLENAME, true);
    tdh.setPropertyInt("__owner", hashCode());
    tdh.setPropertyString("height", "1px");

    // body styling
    setStyleName(tdb, DEFAULT_STYLENAME + "Content", true);
    tdb.setPropertyString("height", "100%");
    tdb.setPropertyString("vAlign", "top");

    // Now that the DOM is connected, call insert (this ensures that onLoad() is
    // not fired until the child widget is attached to the DOM).
    insert(w, tdb, beforeIndex, false);

    // Update indices of all elements to the right.
    updateIndicesFrom(beforeIndex);

    // Correct visible stack for new location.
    if (visibleStack == -1) {
      showStack(0);
    } else {
      setStackVisible(beforeIndex, false);
      if (visibleStack >= beforeIndex) {
        ++visibleStack;
      }
      // Reshow the stack to apply style names
      setStackVisible(visibleStack, true);
    }
  }

  @Override
  public void onBrowserEvent(Event event) {
    if (DOM.eventGetType(event) == Event.ONCLICK) {
      Element target = DOM.eventGetTarget(event);
      int index = findDividerIndex(target);
      if (index != -1) {
        showStack(index);
      }
    }
    super.onBrowserEvent(event);
  }

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

  @Override
  public boolean remove(Widget child) {
    return remove(child, getWidgetIndex(child));
  }

  /**
   * Sets the text associated with a child by its index.
   *
   * @param index the index of the child whose text is to be set
   * @param text the text to be associated with it
   */
  public void setStackText(int index, String text) {
    setStackText(index, text, false);
  }

  /**
   * Sets the html associated with a child by its index.
   *
   * @param index the index of the child whose text is to be set
   * @param html the html to be associated with it
   */
  public void setStackText(int index, SafeHtml html) {
    setStackText(index, html.asString(), true);
  }

  /**
   * Sets the text associated with a child by its index.
   *
   * @param index the index of the child whose text is to be set
   * @param text the text to be associated with it
   * @param asHTML <code>true</code> to treat the specified text as HTML
   */
  public void setStackText(int index, String text, boolean asHTML) {
    if (index >= getWidgetCount()) {
      return;
    }

    Element tdWrapper = DOM.getChild(DOM.getChild(body, index * 2), 0);
    Element headerElem = DOM.getFirstChild(tdWrapper);
    if (asHTML) {
      getHeaderTextElem(headerElem).setInnerHTML(text);
    } else {
      getHeaderTextElem(headerElem).setInnerText(text);
    }
  }

  /**
   * Shows the widget at the specified child index.
   *
   * @param index the index of the child to be shown
   */
  public void showStack(int index) {
    if ((index >= getWidgetCount()) || (index < 0) || (index == visibleStack)) {
      return;
    }

    if (visibleStack >= 0) {
      setStackVisible(visibleStack, false);
    }

    visibleStack = index;
    setStackVisible(visibleStack, true);
  }

  /**
   * <b>Affected Elements:</b>
   * <ul>
   * <li>-text# = The element around the header at the specified index.</li>
   * <li>-text-wrapper# = The element around the header at the specified index.</li>
   * <li>-content# = The element around the body at the specified index.</li>
   * </ul>
   *
   * @see UIObject#onEnsureDebugId(String)
   */
  @Override
  protected void onEnsureDebugId(String baseID) {
    super.onEnsureDebugId(baseID);

    int numHeaders = DOM.getChildCount(body) >> 1;
    for (int i = 0; i < numHeaders; i++) {
      Element tdWrapper = DOM.getFirstChild(DOM.getChild(body, 2 * i));
      Element headerElem = DOM.getFirstChild(tdWrapper);
      Element bodyElem = DOM.getFirstChild(DOM.getChild(body, 2 * i + 1));
      ensureDebugId(tdWrapper, baseID, "text-wrapper" + i);
      ensureDebugId(bodyElem, baseID, "content" + i);
      ensureDebugId(getHeaderTextElem(headerElem), baseID, "text" + i);
    }
  }

  /**
   * Returns a header element.
   */
  Element createHeaderElem() {
    return DOM.createDiv();
  }

  /**
   * Get the element that holds the header text given the header element created
   * by #createHeaderElement.
   *
   * @param headerElem the header element
   * @return the element around the header text
   */
  Element getHeaderTextElem(Element headerElem) {
    return headerElem;
  }

  /**
   * Adds the {@code styleName} on the {@code <tr>} for the header specified by {@code index}.
   *
   * @param index the index of the header row to apply to the style to
   * @param styleName the name of the class to add
   */
  public void addHeaderStyleName(int index, String styleName) {
    if (index >= getWidgetCount()) {
      return;
    }

    Element tr = DOM.getChild(body, index * 2);
    setStyleName(tr, styleName, true /* add */);
  }

  /**
   * Removes the {@code styleName} off the {@code <tr>} for the header specified by {@code index}.
   *
   * @param index the index of the header row to remove the style from
   * @param styleName the name of the class to remove
   */
  public void removeHeaderStyleName(int index, String styleName) {
    if (index >= getWidgetCount()) {
      return;
    }

    Element tr = DOM.getChild(body, index * 2);
    setStyleName(tr, styleName, false /* remove */);
  }

  private int findDividerIndex(Element elem) {
    while (elem != null && elem != getElement()) {
      String expando = elem.getPropertyString("__index");
      if (expando != null) {
        // Make sure it belongs to me!
        int ownerHash = elem.getPropertyInt("__owner");
        if (ownerHash == hashCode()) {
          // Yes, it's mine.
          return Integer.parseInt(expando);
        } else {
          // It must belong to some nested StackPanel.
          return -1;
        }
      }
      elem = DOM.getParent(elem);
    }
    return -1;
  }

  private boolean remove(Widget child, int index) {
    // Make sure to call this before disconnecting the DOM.
    boolean removed = super.remove(child);
    if (removed) {
      // Calculate which internal table elements to remove.
      int rowIndex = 2 * index;
      Element tr = DOM.getChild(body, rowIndex);
      body.removeChild(tr);
      tr = DOM.getChild(body, rowIndex);
      body.removeChild(tr);

      // Correct visible stack for new location.
      if (visibleStack == index) {
        visibleStack = -1;
      } else if (visibleStack > index) {
        --visibleStack;
      }

      // Update indices of all elements to the right.
      updateIndicesFrom(index);
    }
    return removed;
  }

  private void setStackContentVisible(int index, boolean visible) {
    Element tr = DOM.getChild(body, (index * 2) + 1);
    UIObject.setVisible(tr, visible);
    getWidget(index).setVisible(visible);
  }

  private void setStackVisible(int index, boolean visible) {
    // Get the first table row containing the widget's selector item.
    Element tr = DOM.getChild(body, (index * 2));
    if (tr == null) {
      return;
    }

    // Style the stack selector item.
    Element td = DOM.getFirstChild(tr);
    setStyleName(td, DEFAULT_ITEM_STYLENAME + "-selected", visible);

    // Show/hide the contained widget.
    setStackContentVisible(index, visible);

    // Set the style of the next header
    Element trNext = DOM.getChild(body, ((index + 1) * 2));
    if (trNext != null) {
      Element tdNext = DOM.getFirstChild(trNext);
      setStyleName(tdNext, DEFAULT_ITEM_STYLENAME + "-below-selected", visible);
    }
  }

  private void updateIndicesFrom(int beforeIndex) {
    for (int i = beforeIndex, c = getWidgetCount(); i < c; ++i) {
      Element childTR = DOM.getChild(body, i * 2);
      Element childTD = DOM.getFirstChild(childTR);
      childTD.setPropertyInt("__index", i);

      // Update the special style on the first element
      if (beforeIndex == 0) {
        setStyleName(childTD, DEFAULT_ITEM_STYLENAME + "-first", true);
      } else {
        setStyleName(childTD, DEFAULT_ITEM_STYLENAME + "-first", false);
      }
    }
  }

}
