/*
 * 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.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.DOM;

/**
 * A panel that arranges two widgets in a single vertical column and allows the
 * user to interactively change the proportion of the height dedicated to each
 * of the two widgets. Widgets contained within a
 * <code>VerticalSplitterPanel</code> will be automatically decorated with
 * scrollbars when necessary.
 * 
 * <p>
 * This widget will <em>only</em> work in quirks mode. If your application is in
 * Standards Mode, use {@link SplitLayoutPanel} instead.
 * </p>
 * 
 * <p>
 * <img class='gallery' src='doc-files/VerticalSplitPanel.png'/>
 * </p>
 * 
 * <h3>CSS Style Rules</h3>
 * <ul>
 * <li>.gwt-VerticalSplitPanel { the panel itself }</li>
 * <li>.gwt-VerticalSplitPanel vsplitter { the splitter }</li>
 * </ul>
 * 
 * @deprecated Use {@link SplitLayoutPanel} instead, but understand that it is
 *             not a drop in replacement for this class. It requires standards
 *             mode, and is most easily used under a {@link RootLayoutPanel} (as
 *             opposed to a {@link RootPanel}
 *
 * @see SplitLayoutPanel
 */
@Deprecated
public final class VerticalSplitPanel extends SplitPanel {
  /**
   * The default resources used by this widget.
   */
  public interface Resources extends ClientBundle {
    /**
     * An image representing the drag thumb.
     */
    @Source("splitPanelThumb.png")
    ImageResource verticalSplitPanelThumb();
  }

  /**
   * Provides a base implementation for splitter layout that relies on CSS
   * positioned layout.
   */
  private static class Impl {
    private static void expandToFitParentHorizontally(Element elem) {
      addAbsolutePositoning(elem);
      elem.getStyle().setProperty("left", "0");
      elem.getStyle().setProperty("right", "0");
    }

    protected VerticalSplitPanel panel;

    public void init(VerticalSplitPanel panel) {
      this.panel = panel;

      panel.getElement().getStyle().setProperty("position", "relative");

      final Element topElem = panel.getElement(TOP);
      final Element bottomElem = panel.getElement(BOTTOM);

      expandToFitParentHorizontally(topElem);
      expandToFitParentHorizontally(bottomElem);
      expandToFitParentHorizontally(panel.getSplitElement());

      expandToFitParentUsingCssOffsets(panel.container);

      // Snap the bottom wrapper to the bottom side.
      bottomElem.getStyle().setProperty("bottom", "0");
    }

    public void onAttach() {
    }

    public void onDetach() {
    }

    public void onSplitterResize(int px) {
      setSplitPosition(px);
    }

    public void setSplitPosition(int px) {
      final Element splitElem = panel.getSplitElement();

      final int rootElemHeight = getOffsetHeight(panel.container);
      final int splitElemHeight = getOffsetHeight(splitElem);

      if (rootElemHeight < splitElemHeight) {
        return;
      }

      int newBottomHeight = rootElemHeight - px - splitElemHeight;
      if (px < 0) {
        px = 0;
        newBottomHeight = rootElemHeight - splitElemHeight;
      } else if (newBottomHeight < 0) {
        px = rootElemHeight - splitElemHeight;
        newBottomHeight = 0;
      }

      updateElements(panel.getElement(TOP), splitElem,
          panel.getElement(BOTTOM), px, px + splitElemHeight, newBottomHeight);
    }

    /**
     * @param topElem
     * @param splitElem
     * @param bottomElem
     * @param topHeight
     * @param bottomTop
     * @param bottomHeight
     */
    protected void updateElements(Element topElem, Element splitElem,
        Element bottomElem, int topHeight, int bottomTop, int bottomHeight) {
      setHeight(topElem, topHeight + "px");

      setTop(splitElem, topHeight + "px");

      setTop(bottomElem, bottomTop + "px");

      // bottom's height is handled by CSS.
    }
  }

  /**
   * Constant makes for readable calls to {@link #getElement(int)} and
   * {@link #getWidget(int)}.
   */
  private static final int TOP = 0;

  /**
   * Constant makes for readable calls to {@link #getElement(int)} and
   * {@link #getWidget(int)}.
   */
  private static final int BOTTOM = 1;

  // Captures the height of the top container when drag resizing starts.
  private int initialTopHeight = 0;

  // Captures the offset of a user's mouse pointer during drag resizing.
  private int initialThumbPos = 0;

  // A style-free element to serve as the root container.
  private final Element container;

  private final Impl impl = GWT.create(Impl.class);

  private String lastSplitPosition;

  public VerticalSplitPanel() {
    this(GWT.<Resources> create(Resources.class));
  }

  /**
   * Creates an empty vertical split panel.
   * @deprecated replaced by {@link #VerticalSplitPanel(Resources)}
   */
  @Deprecated
  public VerticalSplitPanel(VerticalSplitPanelImages images) {
    this(images.verticalSplitPanelThumb());
  }

  public VerticalSplitPanel(Resources resources) {
    this(AbstractImagePrototype.create(resources.verticalSplitPanelThumb()));
  }

  private VerticalSplitPanel(AbstractImagePrototype thumbImage) {
    super(DOM.createDiv(), DOM.createDiv(), preventBoxStyles(DOM.createDiv()),
        preventBoxStyles(DOM.createDiv()));

    container = preventBoxStyles(DOM.createDiv());

    buildDOM(thumbImage);

    setStyleName("gwt-VerticalSplitPanel");

    impl.init(this);

    setSplitPosition("50%");
  }

  /**
   * Gets the widget in the bottom of the panel.
   * 
   * @return the widget, <code>null</code> if there is not one
   */
  public Widget getBottomWidget() {
    return getWidget(BOTTOM);
  }

  /**
   * Gets the widget in the top of the panel.
   * 
   * @return the widget, <code>null</code> if there is not one
   */
  public Widget getTopWidget() {
    return getWidget(TOP);
  }

  /**
   * Sets the widget in the bottom of the panel.
   * 
   * @param w the widget
   */
  public void setBottomWidget(Widget w) {
    setWidget(BOTTOM, w);
  }

  @Override
  public void setHeight(String height) {
    super.setHeight(height);
  }

  @Override
  public void setSplitPosition(String pos) {
    lastSplitPosition = pos;
    final Element topElem = getElement(TOP);
    setHeight(topElem, pos);
    impl.setSplitPosition(getOffsetHeight(topElem));
  }

  /**
   * Sets the widget in the top of the panel.
   * 
   * @param w the widget
   */
  public void setTopWidget(Widget w) {
    setWidget(TOP, w);
  }

  /**
   * <b>Affected Elements:</b>
   * <ul>
   * <li>-splitter = the container containing the splitter element.</li>
   * <li>-top = the container above the splitter.</li>
   * <li>-bottom = the container below the splitter.</li>
   * </ul>
   * 
   * @see UIObject#onEnsureDebugId(String)
   */
  @Override
  protected void onEnsureDebugId(String baseID) {
    super.onEnsureDebugId(baseID);
    ensureDebugId(getElement(TOP), baseID, "top");
    ensureDebugId(getElement(BOTTOM), baseID, "bottom");
  }

  @Override
  protected void onLoad() {
    impl.onAttach();

    /*
     * Set the position realizing it might not work until after layout runs.
     * This first call is simply to try to avoid a jitter effect if possible.
     */
    setSplitPosition(lastSplitPosition);
    Scheduler.get().scheduleDeferred(new ScheduledCommand() {
      public void execute() {
        setSplitPosition(lastSplitPosition);
      }
    });
  }

  @Override
  protected void onUnload() {
    impl.onDetach();
  }

  @Override
  void onSplitterResize(int x, int y) {
    impl.onSplitterResize(initialTopHeight + y - initialThumbPos);
  }

  @Override
  void onSplitterResizeStarted(int x, int y) {
    initialThumbPos = y;
    initialTopHeight = getOffsetHeight(getElement(TOP));
  }

  private void buildDOM(AbstractImagePrototype thumb) {
    final Element topDiv = getElement(TOP);
    final Element bottomDiv = getElement(BOTTOM);
    final Element splitDiv = getSplitElement();

    DOM.appendChild(getElement(), container);

    DOM.appendChild(container, topDiv);
    DOM.appendChild(container, splitDiv);
    DOM.appendChild(container, bottomDiv);

    /*
     * The style name is placed on the table rather than splitElem to allow the
     * splitter to be styled without interfering with layout.
     */
    SafeHtmlBuilder sb = new SafeHtmlBuilder();
    sb.appendHtmlConstant("<div class='vsplitter' style='text-align:center;'>");
    sb.append(thumb.getSafeHtml());
    sb.appendHtmlConstant("</div>");
    splitDiv.setInnerSafeHtml(sb.toSafeHtml());

    addScrolling(topDiv);
    addScrolling(bottomDiv);
  }
}
