/*
 * 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.Duration;
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.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 int snapClosedSize = -1;
    private double centerSize, syncedCenterSize;

    private boolean toggleDisplayAllowed = false;
    private double lastClick = 0;

    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();

          // Handle double-clicks.
          // Fake them since the double-click event aren't fired.
          if (this.toggleDisplayAllowed) {
            double now = Duration.currentTimeMillis();
            if (now - this.lastClick < DOUBLE_CLICK_TIMEOUT) {
              now = 0;
              LayoutData layout = (LayoutData) target.getLayoutData();
              if (layout.size == 0) {
                // Restore the old size.
                setAssociatedWidgetSize(layout.oldSize);
              } else {
                /*
                 * Collapse to size 0. We change the size instead of hiding the
                 * widget because hiding the widget can cause issues if the
                 * widget contains a flash component.
                 */
                layout.oldSize = layout.size;
                setAssociatedWidgetSize(0);
              }
            }
            this.lastClick = now;
          }

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

        case Event.ONMOUSEMOVE:
          if (mouseDown) {
            int size;
            if (reverse) {
              size = getTargetPosition() + getTargetSize() - getSplitterSize()
                  - getEventPosition(event) + offset;
            } else {
              size = getEventPosition(event) - getTargetPosition() - offset;
            }
            ((LayoutData) target.getLayoutData()).hidden = false;
            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);
    }

    public void setSnapClosedSize(int snapClosedSize) {
      this.snapClosedSize = snapClosedSize;
    }

    public void setToggleDisplayAllowed(boolean allowed) {
      this.toggleDisplayAllowed = allowed;
    }

    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 (snapClosedSize > 0 && size < snapClosedSize) {
        size = 0;
      } else 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 ScheduledCommand() {
          @Override
          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;
  private static final int DOUBLE_CLICK_TIMEOUT = 500;

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

  @Override
  public void setWidgetHidden(Widget widget, boolean hidden) {
    super.setWidgetHidden(widget, hidden);
    Splitter splitter = getAssociatedSplitter(widget);
    if (splitter != null) {
      // The splitter is null for the center element.
      super.setWidgetHidden(splitter, hidden);
    }
  }

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

  /**
   * Sets a size below which the slider will close completely. This can be used
   * in conjunction with {@link #setWidgetMinSize} to provide a speed-bump
   * effect where the slider will stick to a preferred minimum size before
   * closing completely.
   *
   * <p>
   * This method has no effect for the {@link DockLayoutPanel.Direction#CENTER}
   * widget.
   * </p>
   *
   * @param child the child whose slider should snap closed
   * @param snapClosedSize the width below which the widget will close or
   *        -1 to disable.
   */
  public void setWidgetSnapClosedSize(Widget child, int snapClosedSize) {
    assertIsChild(child);
    Splitter splitter = getAssociatedSplitter(child);
    // The splitter is null for the center element.
    if (splitter != null) {
      splitter.setSnapClosedSize(snapClosedSize);
    }
  }

  /**
   * Sets whether or not double-clicking on the splitter should toggle the
   * display of the widget.
   *
   * @param child the child whose display toggling will be allowed or not.
   * @param allowed whether or not display toggling is allowed for this widget
   */
  public void setWidgetToggleDisplayAllowed(Widget child, boolean allowed) {
    assertIsChild(child);
    Splitter splitter = getAssociatedSplitter(child);
    // The splitter is null for the center element.
    if (splitter != null) {
      splitter.setToggleDisplayAllowed(allowed);
    }
  }

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