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

import java.util.Iterator;

/**
 * Abstract base class for {@link HorizontalSplitPanel} and
 * {@link VerticalSplitPanel}.
 * 
 * @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}
 */
@Deprecated
abstract class SplitPanel extends Panel {
  /**
   * The element that masks the screen so we can catch mouse events over
   * iframes.
   */
  private static Element glassElem = null;

  /**
   * Sets an elements positioning to absolute.
   * 
   * @param elem the element
   */
  static void addAbsolutePositoning(Element elem) {
    elem.getStyle().setProperty("position", "absolute");
  }

  /**
   * Adds clipping to an element.
   * 
   * @param elem the element
   */
  static final void addClipping(final Element elem) {
    elem.getStyle().setProperty("overflow", "hidden");
  }

  /**
   * Adds as-needed scrolling to an element.
   * 
   * @param elem the element
   */
  static final void addScrolling(final Element elem) {
    elem.getStyle().setProperty("overflow", "auto");
  }

  /**
   * Sizes and element to consume the full area of its parent using the CSS
   * properties left, right, top, and bottom. This method is used for all
   * browsers except IE6/7.
   * 
   * @param elem the element
   */
  static final void expandToFitParentUsingCssOffsets(Element elem) {
    final String zeroSize = "0px";

    addAbsolutePositoning(elem);
    setLeft(elem, zeroSize);
    setRight(elem, zeroSize);
    setTop(elem, zeroSize);
    setBottom(elem, zeroSize);
  }

  /**
   * Sizes an element to consume the full areas of its parent using 100% width
   * and height. This method is used on IE6/7 where CSS offsets don't work
   * reliably.
   * 
   * @param elem the element
   */
  static final void expandToFitParentUsingPercentages(Element elem) {
    final String zeroSize = "0px";
    final String fullSize = "100%";

    addAbsolutePositoning(elem);
    setTop(elem, zeroSize);
    setLeft(elem, zeroSize);
    setWidth(elem, fullSize);
    setHeight(elem, fullSize);
  }

  /**
   * Returns the offsetHeight element property.
   * 
   * @param elem the element
   * @return the offsetHeight property
   */
  static final int getOffsetHeight(Element elem) {
    return elem.getPropertyInt("offsetHeight");
  }

  /**
   * Returns the offsetWidth element property.
   * 
   * @param elem the element
   * @return the offsetWidth property
   */
  static final int getOffsetWidth(Element elem) {
    return elem.getPropertyInt("offsetWidth");
  }

  /**
   * Adds zero or none CSS values for padding, margin and border to prevent
   * stylesheet overrides. Returns the element for convenience to support
   * builder pattern.
   * 
   * @param elem the element
   * @return the element
   */
  static final Element preventBoxStyles(final Element elem) {
    DOM.setIntStyleAttribute(elem, "padding", 0);
    DOM.setIntStyleAttribute(elem, "margin", 0);
    elem.getStyle().setProperty("border", "none");
    return elem;
  }

  /**
   * Convenience method to set bottom offset of an element.
   * 
   * @param elem the element
   * @param size a CSS length value for bottom
   */
  static void setBottom(Element elem, String size) {
    elem.getStyle().setProperty("bottom", size);
  }

  /**
   * Sets the elements css class name.
   * 
   * @param elem the element
   * @param className the class name
   */
  static final void setClassname(final Element elem, final String className) {
    elem.setPropertyString("className", className);
  }

  /**
   * Convenience method to set the height of an element.
   * 
   * @param elem the element
   * @param height a CSS length value for the height
   */
  static final void setHeight(Element elem, String height) {
    elem.getStyle().setProperty("height", height);
  }

  /**
   * Convenience method to set the left offset of an element.
   * 
   * @param elem the element
   * @param left a CSS length value for left
   */
  static final void setLeft(Element elem, String left) {
    elem.getStyle().setProperty("left", left);
  }

  /**
   * Convenience method to set the right offset of an element.
   * 
   * @param elem the element
   * @param right a CSS length value for right
   */
  static final void setRight(Element elem, String right) {
    elem.getStyle().setProperty("right", right);
  }

  /**
   * Convenience method to set the top offset of an element.
   * 
   * @param elem the element
   * @param top a CSS length value for top
   */
  static final void setTop(Element elem, String top) {
    elem.getStyle().setProperty("top", top);
  }

  /**
   * Convenience method to set the width of an element.
   * 
   * @param elem the element
   * @param width a CSS length value for the width
   */
  static final void setWidth(Element elem, String width) {
    elem.getStyle().setProperty("width", width);
  }

  // The enclosed widgets.
  private final Widget[] widgets = new Widget[2];

  // The elements containing the widgets.
  private final Element[] elements = new Element[2];

  // The element that acts as the splitter.
  private final Element splitElem;

  // Indicates whether drag resizing is active.
  private boolean isResizing = false;

  /**
   * Initializes the split panel.
   * 
   * @param mainElem the root element for the split panel
   * @param splitElem the element that acts as the splitter
   * @param headElem the element to contain the top or left most widget
   * @param tailElem the element to contain the bottom or right most widget
   */
  SplitPanel(Element mainElem, Element splitElem, Element headElem,
      Element tailElem) {
    setElement(mainElem);
    this.splitElem = splitElem;
    elements[0] = headElem;
    elements[1] = tailElem;
    sinkEvents(Event.MOUSEEVENTS | Event.ONLOSECAPTURE);

    if (glassElem == null) {
      glassElem = DOM.createDiv();
      glassElem.getStyle().setProperty("position", "absolute");
      glassElem.getStyle().setProperty("top", "0px");
      glassElem.getStyle().setProperty("left", "0px");
      glassElem.getStyle().setProperty("margin", "0px");
      glassElem.getStyle().setProperty("padding", "0px");
      glassElem.getStyle().setProperty("border", "0px");

      // We need to set the background color or mouse events will go right
      // through the glassElem. If the SplitPanel contains an iframe, the
      // iframe will capture the event and the slider will stop moving.
      glassElem.getStyle().setProperty("background", "white");
      glassElem.getStyle().setProperty("opacity", "0.0");
      glassElem.getStyle().setProperty("filter", "alpha(opacity=0)");
    }
  }

  @Override
  public void add(Widget w) {
    if (getWidget(0) == null) {
      setWidget(0, w);
    } else if (getWidget(1) == null) {
      setWidget(1, w);
    } else {
      throw new IllegalStateException(
          "A Splitter can only contain two Widgets.");
    }
  }

  /**
   * Indicates whether the split panel is being resized.
   * 
   * @return <code>true</code> if the user is dragging the splitter,
   *         <code>false</code> otherwise
   */
  public boolean isResizing() {
    return isResizing;
  }

  public Iterator<Widget> iterator() {
    return WidgetIterators.createWidgetIterator(this, widgets);
  }

  @Override
  public void onBrowserEvent(Event event) {
    switch (DOM.eventGetType(event)) {

      case Event.ONMOUSEDOWN: {
        Element target = DOM.eventGetTarget(event);
        if (splitElem.isOrHasChild(target)) {
          startResizingFrom(event.getClientX() - getAbsoluteLeft(),
              event.getClientY() - getAbsoluteTop());
          DOM.setCapture(getElement());
          event.preventDefault();
        }
        break;
      }

      case Event.ONMOUSEUP: {
        if (isResizing()) {
          // The order of these two lines is important. If we release capture
          // first, then we might trigger an onLoseCapture event before we set
          // isResizing to false.
          stopResizing();
          DOM.releaseCapture(getElement());
        }
        break;
      }

      case Event.ONMOUSEMOVE: {
        if (isResizing()) {
          assert DOM.getCaptureElement() != null;
          onSplitterResize(event.getClientX() - getAbsoluteLeft(),
              event.getClientY() - getAbsoluteTop());
          event.preventDefault();
        }
        break;
      }

      // IE automatically releases capture if the user switches windows, so we
      // need to catch the event and stop resizing.
      case Event.ONLOSECAPTURE: {
        if (isResizing()) {
          stopResizing();
        }
        break;
      }
    }
    super.onBrowserEvent(event);
  }

  @Override
  public boolean remove(Widget widget) {
    if (widgets[0] == widget) {
      setWidget(0, null);
      return true;
    } else if (widgets[1] == widget) {
      setWidget(1, null);
      return true;
    }
    return false;
  }

  /**
   * Moves the position of the splitter.
   * 
   * @param size the new size of the left region in CSS units (e.g. "10px",
   *            "1em")
   */
  public abstract void setSplitPosition(String size);

  /**
   * Gets the content element for the given index.
   * 
   * @param index the index of the element, only 0 and 1 are valid.
   * @return the element
   */
  protected Element getElement(int index) {
    return elements[index];
  }

  /**
   * Gets the element that is acting as the splitter.
   * 
   * @return the element
   */
  protected Element getSplitElement() {
    return splitElem;
  }

  /**
   * Gets one of the contained widgets.
   * 
   * @param index the index of the widget, only 0 and 1 are valid.
   * @return the widget
   */
  protected Widget getWidget(int index) {
    return widgets[index];
  }

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

  /**
   * Sets one of the contained widgets.
   * 
   * @param index the index, only 0 and 1 are valid
   * @param w the widget
   */
  protected final void setWidget(int index, Widget w) {
    Widget oldWidget = widgets[index];

    // Validate.
    if (oldWidget == w) {
      return;
    }

    // Detach the new child.
    if (w != null) {
      w.removeFromParent();
    }

    // Remove the old child.
    if (oldWidget != null) {
      // Orphan old.
      try {
        orphan(oldWidget);
      } finally {
        // Physical detach old.
        elements[index].removeChild(oldWidget.getElement());
        widgets[index] = null;
      }
    }

    // Logical attach new.
    widgets[index] = w;

    if (w != null) {
      // Physical attach new.
      DOM.appendChild(elements[index], w.getElement());

      // Adopt new.
      adopt(w);
    }
  }

  /**
   * Called on each mouse drag event as the user is dragging the splitter.
   * 
   * @param x the x coordinate of the mouse relative to the panel's extent
   * @param y the y coordinate of the mosue relative to the panel's extent
   */
  abstract void onSplitterResize(int x, int y);

  /**
   * Called when the user starts dragging the splitter.
   * 
   * @param x the x coordinate of the mouse relative to the panel's extent
   * @param y the y coordinate of the mouse relative to the panel's extent
   */
  abstract void onSplitterResizeStarted(int x, int y);

  private void startResizingFrom(int x, int y) {
    isResizing = true;
    onSplitterResizeStarted(x, y);

    // Resize glassElem to take up the entire scrollable window area
    int height = RootPanel.getBodyElement().getScrollHeight() - 1;
    int width = RootPanel.getBodyElement().getScrollWidth() - 1;
    glassElem.getStyle().setProperty("height", height + "px");
    glassElem.getStyle().setProperty("width", width + "px");
    RootPanel.getBodyElement().appendChild(glassElem);
  }

  private void stopResizing() {
    isResizing = false;
    RootPanel.getBodyElement().removeChild(glassElem);
  }
}
