/*
 * Copyright 2009 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.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;

/**
 * A panel that adds user-positioned splitters between each of its child
 * widgets.
 *
 * <p>
 * This panel is used in the same way as {@link DockLayoutPanel}, except that
 * its children's sizes are always specified in {@link Unit#PX} units, and each
 * pair of child widgets has a splitter between them that the user can drag.
 * </p>
 *
 * <p>
 * This widget will <em>only</em> work in standards mode, which requires that
 * the HTML page in which it is run have an explicit &lt;!DOCTYPE&gt;
 * declaration.
 * </p>
 *
 * <h3>CSS Style Rules</h3>
 * <ul class='css'>
 * <li>.gwt-SplitLayoutPanel { the panel itself }</li>
 * <li>.gwt-SplitLayoutPanel .gwt-SplitLayoutPanel-HDragger { horizontal dragger
 * }</li>
 * <li>.gwt-SplitLayoutPanel .gwt-SplitLayoutPanel-VDragger { vertical dragger }
 * </li>
 * </ul>
 *
 * <p>
 * <h3>Example</h3>
 * {@example com.google.gwt.examples.SplitLayoutPanelExample}
 * </p>
 */
public class SplitLayoutPanel extends DockLayoutPanel {

  class HSplitter extends Splitter {
    public HSplitter(Widget target, boolean reverse) {
      super(target, reverse);
      getElement().getStyle().setPropertyPx("width", splitterSize);
      setStyleName("gwt-SplitLayoutPanel-HDragger");
    }

    @Override
    protected int getAbsolutePosition() {
      return getAbsoluteLeft();
    }

    @Override
    protected double getCenterSize() {
      return getCenterWidth();
    }

    @Override
    protected int getEventPosition(Event event) {
      return event.getClientX();
    }

    @Override
    protected int getTargetPosition() {
      return target.getAbsoluteLeft();
    }

    @Override
    protected int getTargetSize() {
      return target.getOffsetWidth();
    }
  }

  abstract class Splitter extends Widget {
    protected final Widget target;

    private int offset;
    private boolean mouseDown;
    private ScheduledCommand layoutCommand;

    private final boolean reverse;
    private int minSize;

    private double centerSize, syncedCenterSize;

    public Splitter(Widget target, boolean reverse) {
      this.target = target;
      this.reverse = reverse;

      setElement(Document.get().createDivElement());
      sinkEvents(Event.ONMOUSEDOWN | Event.ONMOUSEUP | Event.ONMOUSEMOVE
          | Event.ONDBLCLICK);
    }

    @Override
    public void onBrowserEvent(Event event) {
      switch (event.getTypeInt()) {
        case Event.ONMOUSEDOWN:
          mouseDown = true;

          /*
           * Resize glassElem to take up the entire scrollable window area,
           * which is the greater of the scroll size and the client size.
           */
          int width = Math.max(Window.getClientWidth(),
              Document.get().getScrollWidth());
          int height = Math.max(Window.getClientHeight(),
              Document.get().getScrollHeight());
          glassElem.getStyle().setHeight(height, Unit.PX);
          glassElem.getStyle().setWidth(width, Unit.PX);
          Document.get().getBody().appendChild(glassElem);

          offset = getEventPosition(event) - getAbsolutePosition();
          Event.setCapture(getElement());
          event.preventDefault();
          break;

        case Event.ONMOUSEUP:
          mouseDown = false;

          glassElem.removeFromParent();

          Event.releaseCapture(getElement());
          event.preventDefault();
          break;

        case Event.ONMOUSEMOVE:
          if (mouseDown) {
            int size;
            if (reverse) {
              size = getTargetPosition() + getTargetSize()
                  - getEventPosition(event) - offset;
            } else {
              size = getEventPosition(event) - getTargetPosition() - offset;
            }
            setAssociatedWidgetSize(size);
            event.preventDefault();
          }
          break;
      }
    }

    public void setMinSize(int minSize) {
      this.minSize = minSize;
      LayoutData layout = (LayoutData) target.getLayoutData();

      // Try resetting the associated widget's size, which will enforce the new
      // minSize value.
      setAssociatedWidgetSize((int) layout.size);
    }

    protected abstract int getAbsolutePosition();

    protected abstract double getCenterSize();

    protected abstract int getEventPosition(Event event);

    protected abstract int getTargetPosition();

    protected abstract int getTargetSize();

    private double getMaxSize() {
      // To avoid seeing stale center size values due to deferred layout
      // updates, maintain our own copy up to date and resync when the
      // DockLayoutPanel value changes.
      double newCenterSize = getCenterSize();
      if (syncedCenterSize != newCenterSize) {
        syncedCenterSize = newCenterSize;
        centerSize = newCenterSize;
      }

      return Math.max(((LayoutData) target.getLayoutData()).size + centerSize,
                0);
    }

    private void setAssociatedWidgetSize(double size) {
      double maxSize = getMaxSize();
      if (size > maxSize) {
        size = maxSize;
      }

      if (size < minSize) {
        size = minSize;
      }

      LayoutData layout = (LayoutData) target.getLayoutData();
      if (size == layout.size) {
        return;
      }

      // Adjust our view until the deferred layout gets scheduled.
      centerSize += layout.size - size;
      layout.size = size;

      // Defer actually updating the layout, so that if we receive many
      // mouse events before layout/paint occurs, we'll only update once.
      if (layoutCommand == null) {
        layoutCommand = new Command() {
          public void execute() {
            layoutCommand = null;
            forceLayout();
          }
        };
        Scheduler.get().scheduleDeferred(layoutCommand);
      }
    }
  }

  class VSplitter extends Splitter {
    public VSplitter(Widget target, boolean reverse) {
      super(target, reverse);
      getElement().getStyle().setPropertyPx("height", splitterSize);
      setStyleName("gwt-SplitLayoutPanel-VDragger");
    }

    @Override
    protected int getAbsolutePosition() {
      return getAbsoluteTop();
    }

    @Override
    protected double getCenterSize() {
      return getCenterHeight();
    }

    @Override
    protected int getEventPosition(Event event) {
      return event.getClientY();
    }

    @Override
    protected int getTargetPosition() {
      return target.getAbsoluteTop();
    }

    @Override
    protected int getTargetSize() {
      return target.getOffsetHeight();
    }
  }

  private static final int DEFAULT_SPLITTER_SIZE = 8;

  /**
   * The element that masks the screen so we can catch mouse events over
   * iframes.
   */
  private static Element glassElem = null;

  private final int splitterSize;

  /**
   * Construct a new {@link SplitLayoutPanel} with the default splitter size of
   * 8px.
   */
  public SplitLayoutPanel() {
    this(DEFAULT_SPLITTER_SIZE);
  }

  /**
   * Construct a new {@link SplitLayoutPanel} with the specified splitter size
   * in pixels.
   *
   * @param splitterSize the size of the splitter in pixels
   */
  public SplitLayoutPanel(int splitterSize) {
    super(Unit.PX);
    this.splitterSize = splitterSize;
    setStyleName("gwt-SplitLayoutPanel");

    if (glassElem == null) {
      glassElem = Document.get().createDivElement();
      glassElem.getStyle().setPosition(Position.ABSOLUTE);
      glassElem.getStyle().setTop(0, Unit.PX);
      glassElem.getStyle().setLeft(0, Unit.PX);
      glassElem.getStyle().setMargin(0, Unit.PX);
      glassElem.getStyle().setPadding(0, Unit.PX);
      glassElem.getStyle().setBorderWidth(0, Unit.PX);

      // 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().setOpacity(0.0);
    }
  }

  /**
   * Return the size of the splitter in pixels.
   *
   * @return the splitter size
   */
  public int getSplitterSize() {
    return splitterSize;
  }

  @Override
  public void insert(Widget child, Direction direction, double size, Widget before) {
    super.insert(child, direction, size, before);
    if (direction != Direction.CENTER) {
      insertSplitter(child, before);
    }
  }

  @Override
  public boolean remove(Widget child) {
    assert !(child instanceof Splitter) : "Splitters may not be directly removed";

    int idx = getWidgetIndex(child);
    if (super.remove(child)) {
      // Remove the associated splitter, if any.
      // Now that the widget is removed, idx is the index of the splitter.
      if (idx < getWidgetCount()) {
        // Call super.remove(), or we'll end up recursing.
        super.remove(getWidget(idx));
      }
      return true;
    }
    return false;
  }

  /**
   * Sets the minimum allowable size for the given widget.
   *
   * <p>
   * Its associated splitter cannot be dragged to a position that would make it
   * smaller than this size. This method has no effect for the
   * {@link DockLayoutPanel.Direction#CENTER} widget.
   * </p>
   *
   * @param child the child whose minimum size will be set
   * @param minSize the minimum size for this widget
   */
  public void setWidgetMinSize(Widget child, int minSize) {
    assertIsChild(child);
    Splitter splitter = getAssociatedSplitter(child);
    // The splitter is null for the center element.
    if (splitter != null) {
      splitter.setMinSize(minSize);
    }
  }

  private Splitter getAssociatedSplitter(Widget child) {
    // If a widget has a next sibling, it must be a splitter, because the only
    // widget that *isn't* followed by a splitter must be the CENTER, which has
    // no associated splitter.
    int idx = getWidgetIndex(child);
    if (idx > -1 && idx < getWidgetCount() - 1) {
      Widget splitter = getWidget(idx + 1);
      assert splitter instanceof Splitter : "Expected child widget to be splitter";
      return (Splitter) splitter;
    }
    return null;
  }

  private void insertSplitter(Widget widget, Widget before) {
    assert getChildren().size() > 0 : "Can't add a splitter before any children";

    LayoutData layout = (LayoutData) widget.getLayoutData();
    Splitter splitter = null;
    switch (getResolvedDirection(layout.direction)) {
      case WEST:
        splitter = new HSplitter(widget, false);
        break;
      case EAST:
        splitter = new HSplitter(widget, true);
        break;
      case NORTH:
        splitter = new VSplitter(widget, false);
        break;
      case SOUTH:
        splitter = new VSplitter(widget, true);
        break;
      default:
        assert false : "Unexpected direction";
    }

    super.insert(splitter, layout.direction, splitterSize, before);
  }
}
