/*
 * 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.dom.client.Style.TextAlign;
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;
import com.google.gwt.user.client.Timer;

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

  /**
   * Provides an implementation for IE8 that relies on 100% length in CSS.
   */
  @SuppressWarnings("unused")
  // will be used by IE8 permutation
  private static class ImplIE8 extends Impl {

    private static void expandToFitParentHorizontally(Element elem) {
      addAbsolutePositoning(elem);
      setLeft(elem, "0");
      setWidth(elem, "100%");
    }

    private boolean isResizeInProgress = false;

    private int splitPosition;

    private boolean isTopHidden = false, isBottomHidden = false;

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

      final Element elem = panel.getElement();

      // Prevents inherited text-align settings from interfering with the
      // panel's layout.
      elem.getStyle().setTextAlign(TextAlign.LEFT);
      elem.getStyle().setProperty("position", "relative");

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

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

      expandToFitParentUsingPercentages(panel.container);
    }

    @Override
    public void onAttach() {
      addResizeListener(panel.container);
      onResize();
    }

    @Override
    public void onDetach() {
      panel.container.setPropertyString("onresize", null);
    }

    @Override
    public void onSplitterResize(int px) {
      /*
       * IE6/7 has event priority issues that will prevent the repaints from
       * happening quickly enough causing the interaction to seem unresponsive.
       * The following is simply a poor man's mouse event coalescing.
       */
      final int resizeUpdatePeriod = 20; // ms
      if (!isResizeInProgress) {
        isResizeInProgress = true;
        new Timer() {
          @Override
          public void run() {
            setSplitPosition(splitPosition);
            isResizeInProgress = false;
          }
        }.schedule(resizeUpdatePeriod);
      }
      splitPosition = px;
    }

    @Override
    protected void updateElements(Element topElem, Element splitElem,
        Element bottomElem, int topHeight, int bottomTop, int bottomHeight) {
      /*
       * IE6/7 has a quirk where a zero height element with non-zero height
       * children will expand larger than 100%. To prevent this, the width is
       * explicitly set to zero when height is zero.
       */
      if (topHeight == 0) {
        setWidth(topElem, "0px");
        isTopHidden = true;
      } else if (isTopHidden) {
        setWidth(topElem, "100%");
        isTopHidden = false;
      }

      if (bottomHeight == 0) {
        setWidth(bottomElem, "0px");
        isBottomHidden = true;
      } else if (isBottomHidden) {
        setWidth(bottomElem, "100%");
        isBottomHidden = false;
      }

      super.updateElements(topElem, splitElem, bottomElem, topHeight,
          bottomTop, bottomHeight);

      // IE6/7 cannot update properly with CSS alone.
      setHeight(bottomElem, bottomHeight + "px");
    }

    private native void addResizeListener(Element container) /*-{
      var self = this;
      container.onresize = $entry(function() {
        self.@com.google.gwt.user.client.ui.VerticalSplitPanel$ImplIE8::onResize()();
      });
    }-*/;

    private void onResize() {
      setSplitPosition(getOffsetHeight(panel.getElement(TOP)));
    }
  }

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