/*
 * 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.animation.client.Animation;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.HasCloseHandlers;
import com.google.gwt.event.logical.shared.HasOpenHandlers;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.resources.client.ImageResource.ImageOptions;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;

import java.util.Iterator;

/**
 * A widget that consists of a header and a content panel that discloses the
 * content when a user clicks on the header.
 * 
 * <h3>CSS Style Rules</h3> 
 * <dl class="css"> 
 * <dt>.gwt-DisclosurePanel 
 * <dd>the panel's primary style 
 * <dt>.gwt-DisclosurePanel-open 
 * <dd> dependent style set when panel is open 
 * <dt>.gwt-DisclosurePanel-closed 
 * <dd> dependent style set when panel is closed
 * </dl>
 * <p>
 * <img class='gallery' src='doc-files/DisclosurePanel.png'/>
 * </p>
 * 
 * <p>
 * The header and content sections can be easily selected using css with a child
 * selector:<br/>
 * .gwt-DisclosurePanel-open .header { ... }
 * </p>
 * <h3>Use in UiBinder Templates</h3>
 * <p>
 * DisclosurePanel elements in  
 * {@link com.google.gwt.uibinder.client.UiBinder UiBinder} templates can 
 * have one widget child and one of two types of header elements. A 
 * &lt;g:header> element can hold text (not 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 header is not a runtime object, 
 * and so cannot have a <code>ui:field</code> attribute.) 
 * <p>
 * For example:<pre>
 * &lt;g:DisclosurePanel>
 *   &lt;g:header>Text header&lt;/g:header>
 *   &lt;g:Label>Widget body&lt;/g:Label>
 * &lt;/g:DisclosurePanel>
 *
 * &lt;g:DisclosurePanel>
 *   &lt;g:customHeader>
 *     &lt;g:Label>Widget header&lt;/g:Label>
 *   &lt;/g:customHeader>
 *   &lt;g:Label>Widget body&lt;/g:Label>
 * &lt;/g:DisclosurePanel>
 * </pre>
 */
@SuppressWarnings("deprecation")
public final class DisclosurePanel extends Composite implements
    FiresDisclosureEvents, HasWidgets, HasAnimation,
    HasOpenHandlers<DisclosurePanel>, HasCloseHandlers<DisclosurePanel> {
  interface DefaultImages extends ClientBundle {
    @ImageOptions(flipRtl = true)
    ImageResource disclosurePanelClosed();

    ImageResource disclosurePanelOpen();
  }

  private static final DefaultImages DEFAULT_IMAGES = GWT.create(DefaultImages.class);

  /**
   * Used to wrap widgets in the header to provide click support. Effectively
   * wraps the widget in an <code>anchor</code> to get automatic keyboard
   * access.
   */
  private final class ClickableHeader extends SimplePanel {

    private ClickableHeader() {
      // Anchor is used to allow keyboard access.
      super(DOM.createAnchor());
      Element elem = getElement();
      DOM.setElementProperty(elem, "href", "javascript:void(0);");
      // Avoids layout problems from having blocks in inlines.
      DOM.setStyleAttribute(elem, "display", "block");
      sinkEvents(Event.ONCLICK);
      setStyleName(STYLENAME_HEADER);
    }

    @Override
    public void onBrowserEvent(Event event) {
      // no need to call super.
      switch (DOM.eventGetType(event)) {
        case Event.ONCLICK:
          // Prevent link default action.
          DOM.eventPreventDefault(event);
          setOpen(!isOpen);
      }
    }
  }

  /**
   * An {@link Animation} used to open the content.
   */
  private static class ContentAnimation extends Animation {
    /**
     * Whether the item is being opened or closed.
     */
    private boolean opening;

    /**
     * The {@link DisclosurePanel} being affected.
     */
    private DisclosurePanel curPanel;

    /**
     * Open or close the content.
     * 
     * @param panel the panel to open or close
     * @param animate true to animate, false to open instantly
     */
    public void setOpen(DisclosurePanel panel, boolean animate) {
      // Immediately complete previous open
      cancel();

      // Open the new item
      if (animate) {
        curPanel = panel;
        opening = panel.isOpen;
        run(ANIMATION_DURATION);
      } else {
        panel.contentWrapper.setVisible(panel.isOpen);
        if (panel.isOpen) {
          // Special treatment on the visible case to ensure LazyPanel works
          panel.getContent().setVisible(true);
        }
      }
    }

    @Override
    protected void onComplete() {
      if (!opening) {
        curPanel.contentWrapper.setVisible(false);
      }
      DOM.setStyleAttribute(curPanel.contentWrapper.getElement(), "height",
          "auto");
      curPanel = null;
    }

    @Override
    protected void onStart() {
      super.onStart();
      if (opening) {
        curPanel.contentWrapper.setVisible(true);
        // Special treatment on the visible case to ensure LazyPanel works
        curPanel.getContent().setVisible(true);
      }
    }

    @Override
    protected void onUpdate(double progress) {
      int scrollHeight = DOM.getElementPropertyInt(
          curPanel.contentWrapper.getElement(), "scrollHeight");
      int height = (int) (progress * scrollHeight);
      if (!opening) {
        height = scrollHeight - height;
      }
      height = Math.max(height, 1);
      DOM.setStyleAttribute(curPanel.contentWrapper.getElement(), "height",
          height + "px");
      DOM.setStyleAttribute(curPanel.contentWrapper.getElement(), "width",
          "auto");
    }
  }

  /**
   * The default header widget used within a {@link DisclosurePanel}.
   */
  private class DefaultHeader extends Widget implements HasText,
      OpenHandler<DisclosurePanel>, CloseHandler<DisclosurePanel> {

    /**
     * imageTD holds the image for the icon, not null. labelTD holds the text
     * for the label.
     */
    private final Element labelTD;

    private final Image iconImage;
    private final Imager imager;

    private DefaultHeader(final DisclosurePanelImages images, String text) {
      this(new Imager() {
        public Image makeImage() {
          return images.disclosurePanelClosed().createImage();
        }

        public void updateImage(boolean open, Image image) {
          if (open) {
            images.disclosurePanelOpen().applyTo(image);
          } else {
            images.disclosurePanelClosed().applyTo(image);
          }
        }
      }, text);
    }

    private DefaultHeader(Imager imager, String text) {
      this.imager = imager;
      iconImage = imager.makeImage();

      // I do not need any Widgets here, just a DOM structure.
      Element root = DOM.createTable();
      Element tbody = DOM.createTBody();
      Element tr = DOM.createTR();
      final Element imageTD = DOM.createTD();
      labelTD = DOM.createTD();

      setElement(root);

      DOM.appendChild(root, tbody);
      DOM.appendChild(tbody, tr);
      DOM.appendChild(tr, imageTD);
      DOM.appendChild(tr, labelTD);

      // set image TD to be same width as image.
      DOM.setElementProperty(imageTD, "align", "center");
      DOM.setElementProperty(imageTD, "valign", "middle");
      DOM.setStyleAttribute(imageTD, "width", iconImage.getWidth() + "px");

      DOM.appendChild(imageTD, iconImage.getElement());

      setText(text);

      addOpenHandler(this);
      addCloseHandler(this);
      setStyle();
    }

    private DefaultHeader(final ImageResource openImage,
        final ImageResource closedImage, String text) {
      this(new Imager() {
        public Image makeImage() {
          return new Image(closedImage);
        }

        public void updateImage(boolean open, Image image) {
          if (open) {
            image.setResource(openImage);
          } else {
            image.setResource(closedImage);
          }
        }
      }, text);
    }

    public final String getText() {
      return DOM.getInnerText(labelTD);
    }

    public final void onClose(CloseEvent<DisclosurePanel> event) {
      setStyle();
    }

    public final void onOpen(OpenEvent<DisclosurePanel> event) {
      setStyle();
    }

    public final void setText(String text) {
      DOM.setInnerText(labelTD, text);
    }

    private void setStyle() {
      imager.updateImage(isOpen, iconImage);
    }
  }

  private interface Imager {
    Image makeImage();

    void updateImage(boolean open, Image image);
  }

  /**
   * The duration of the animation.
   */
  private static final int ANIMATION_DURATION = 350;

  // Stylename constants.
  private static final String STYLENAME_DEFAULT = "gwt-DisclosurePanel";

  private static final String STYLENAME_SUFFIX_OPEN = "open";

  private static final String STYLENAME_SUFFIX_CLOSED = "closed";

  private static final String STYLENAME_HEADER = "header";

  private static final String STYLENAME_CONTENT = "content";

  /**
   * The {@link Animation} used to open and close the content.
   */
  private static ContentAnimation contentAnimation;

  /**
   * top level widget. The first child will be a reference to {@link #header}.
   * The second child will be a reference to {@link #contentWrapper}.
   */
  private final VerticalPanel mainPanel = new VerticalPanel();

  /**
   * The wrapper around the content widget.
   */
  private final SimplePanel contentWrapper = new SimplePanel();

  /**
   * holds the header widget.
   */
  private final ClickableHeader header = new ClickableHeader();

  private boolean isAnimationEnabled = false;

  private boolean isOpen = false;

  /**
   * Creates an empty DisclosurePanel that is initially closed.
   */
  public DisclosurePanel() {
    initWidget(mainPanel);
    mainPanel.add(header);
    mainPanel.add(contentWrapper);
    DOM.setStyleAttribute(contentWrapper.getElement(), "padding", "0px");
    DOM.setStyleAttribute(contentWrapper.getElement(), "overflow", "hidden");
    setStyleName(STYLENAME_DEFAULT);
    setContentDisplay(false);
  }

  /**
   * Creates a DisclosurePanel with the specified header text, an initial
   * open/close state and a bundle of images to be used in the default header
   * widget.
   * 
   * @param images a bundle that provides disclosure panel specific images
   * @param headerText the text to be displayed in the header
   * @param isOpen the initial open/close state of the content panel
   * 
   * @deprecated use
   *             {@link #DisclosurePanel(ImageResource, ImageResource, String)}
   *             and {@link #setOpen(boolean)}
   */
  @Deprecated
  public DisclosurePanel(DisclosurePanelImages images, String headerText,
      boolean isOpen) {
    this();
    setOpen(isOpen);
    setHeader(new DefaultHeader(images, headerText));
  }

  /**
   * Creates a DisclosurePanel with the specified header text, an initial
   * open/close state and a bundle of images to be used in the default header
   * widget.
   * 
   * @param openImage the open state image resource
   * @param closedImage the closed state image resource
   * @param headerText the text to be displayed in the header
   */
  public DisclosurePanel(ImageResource openImage, ImageResource closedImage,
      String headerText) {
    this();
    setHeader(new DefaultHeader(openImage, closedImage, headerText));
  }

  /**
   * Creates a DisclosurePanel that will be initially closed using the specified
   * text in the header.
   * 
   * @param headerText the text to be displayed in the header
   */
  public DisclosurePanel(String headerText) {
    this(DEFAULT_IMAGES.disclosurePanelOpen(),
        DEFAULT_IMAGES.disclosurePanelClosed(), headerText);
  }

  /**
   * Creates a DisclosurePanel with the specified header text and an initial
   * open/close state.
   * 
   * @param headerText the text to be displayed in the header
   * @param isOpen the initial open/close state of the content panel
   * @deprecated use {@link #DisclosurePanel(String)} and
   *             {@link #setOpen(boolean)}
   */
  @Deprecated
  public DisclosurePanel(String headerText, boolean isOpen) {
    this(DEFAULT_IMAGES.disclosurePanelOpen(),
        DEFAULT_IMAGES.disclosurePanelClosed(), headerText);
    this.setOpen(isOpen);
  }

  /**
   * Creates a DisclosurePanel that will be initially closed using a widget as
   * the header.
   * 
   * @param header the widget to be used as a header
   * @deprecated use {@link #DisclosurePanel()} and {@link #setHeader(Widget)}
   */
  public DisclosurePanel(Widget header) {
    this();
    setHeader(header);
  }

  /**
   * Creates a DisclosurePanel using a widget as the header and an initial
   * open/close state.
   * 
   * @param header the widget to be used as a header
   * @param isOpen the initial open/close state of the content panel
   * @deprecated use {@link #DisclosurePanel()}, {@link #setOpen(boolean)} and
   *             {@link #setHeader(Widget)} instead
   */
  @Deprecated
  public DisclosurePanel(Widget header, boolean isOpen) {
    this();
    setHeader(header);
    setOpen(isOpen);
  }

  public void add(Widget w) {
    if (this.getContent() == null) {
      setContent(w);
    } else {
      throw new IllegalStateException(
          "A DisclosurePanel can only contain two Widgets.");
    }
  }

  public HandlerRegistration addCloseHandler(
      CloseHandler<DisclosurePanel> handler) {
    return addHandler(handler, CloseEvent.getType());
  }

  /**
   * Attaches an event handler to the panel to receive {@link DisclosureEvent}
   * notification.
   * 
   * @param handler the handler to be added (should not be null)
   * @deprecated Use {@link DisclosurePanel#addOpenHandler(OpenHandler)} and
   *             {@link DisclosurePanel#addCloseHandler(CloseHandler)} instead
   */
  @Deprecated
  public void addEventHandler(final DisclosureHandler handler) {
    ListenerWrapper.WrappedOldDisclosureHandler.add(this, handler);
  }

  public HandlerRegistration addOpenHandler(OpenHandler<DisclosurePanel> handler) {
    return addHandler(handler, OpenEvent.getType());
  }

  public void clear() {
    setContent(null);
  }

  /**
   * Gets the widget that was previously set in {@link #setContent(Widget)}.
   * 
   * @return the panel's current content widget
   */
  public Widget getContent() {
    return contentWrapper.getWidget();
  }

  /**
   * Gets the widget that is currently being used as a header.
   * 
   * @return the widget currently being used as a header
   */
  public Widget getHeader() {
    return header.getWidget();
  }

  /**
   * Gets a {@link HasText} instance to provide access to the headers's text, if
   * the header widget does provide such access.
   * 
   * @return a reference to the header widget if it implements {@link HasText},
   *         <code>null</code> otherwise
   */
  public HasText getHeaderTextAccessor() {
    Widget widget = header.getWidget();
    return (widget instanceof HasText) ? (HasText) widget : null;
  }

  public boolean isAnimationEnabled() {
    return isAnimationEnabled;
  }

  /**
   * Determines whether the panel is open.
   * 
   * @return <code>true</code> if panel is in open state
   */
  public boolean isOpen() {
    return isOpen;
  }

  public Iterator<Widget> iterator() {
    return WidgetIterators.createWidgetIterator(this,
        new Widget[] {getContent()});
  }

  public boolean remove(Widget w) {
    if (w == getContent()) {
      setContent(null);
      return true;
    }
    return false;
  }

  /**
   * Removes an event handler from the panel.
   * 
   * @param handler the handler to be removed
   * @deprecated Use the {@link HandlerRegistration#removeHandler} method on the
   *             object returned by an add*Handler method instead
   */
  @Deprecated
  public void removeEventHandler(DisclosureHandler handler) {
    ListenerWrapper.WrappedOldDisclosureHandler.remove(this, handler);
  }

  public void setAnimationEnabled(boolean enable) {
    isAnimationEnabled = enable;
  }

  /**
   * Sets the content widget which can be opened and closed by this panel. If
   * there is a preexisting content widget, it will be detached.
   * 
   * @param content the widget to be used as the content panel
   */
  public void setContent(Widget content) {
    final Widget currentContent = getContent();

    // Remove existing content widget.
    if (currentContent != null) {
      contentWrapper.setWidget(null);
      currentContent.removeStyleName(STYLENAME_CONTENT);
    }

    // Add new content widget if != null.
    if (content != null) {
      contentWrapper.setWidget(content);
      content.addStyleName(STYLENAME_CONTENT);
      setContentDisplay(false);
    }
  }

  /**
   * Sets the widget used as the header for the panel.
   * 
   * @param headerWidget the widget to be used as the header
   */
  public void setHeader(Widget headerWidget) {
    header.setWidget(headerWidget);
  }

  /**
   * Changes the visible state of this <code>DisclosurePanel</code>.
   * 
   * @param isOpen <code>true</code> to open the panel, <code>false</code> to
   *          close
   */
  public void setOpen(boolean isOpen) {
    if (this.isOpen != isOpen) {
      this.isOpen = isOpen;
      setContentDisplay(true);
      fireEvent();
    }
  }

  /**
   * <b>Affected Elements:</b>
   * <ul>
   * <li>-header = the clickable header.</li>
   * </ul>
   * 
   * @see UIObject#onEnsureDebugId(String)
   */
  @Override
  protected void onEnsureDebugId(String baseID) {
    super.onEnsureDebugId(baseID);
    header.ensureDebugId(baseID + "-header");
  }

  private void fireEvent() {
    if (isOpen) {
      OpenEvent.fire(this, this);
    } else {
      CloseEvent.fire(this, this);
    }
  }

  private void setContentDisplay(boolean animate) {
    if (isOpen) {
      removeStyleDependentName(STYLENAME_SUFFIX_CLOSED);
      addStyleDependentName(STYLENAME_SUFFIX_OPEN);
    } else {
      removeStyleDependentName(STYLENAME_SUFFIX_OPEN);
      addStyleDependentName(STYLENAME_SUFFIX_CLOSED);
    }

    if (getContent() != null) {
      if (contentAnimation == null) {
        contentAnimation = new ContentAnimation();
      }
      contentAnimation.setOpen(this, animate && isAnimationEnabled);
    }
  }
}
