/*
 * Copyright 2011 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.Document;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.dom.client.Style.Overflow;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.event.logical.shared.HasResizeHandlers;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.layout.client.Layout;
import com.google.gwt.layout.client.Layout.Layer;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.ui.ResizeLayoutPanel.Impl.Delegate;

/**
 * A simple panel that {@link ProvidesResize} to its one child, but does not
 * {@link RequiresResize}. Use this to embed layout panels in any location
 * within your application.
 */
public class ResizeLayoutPanel extends SimplePanel implements ProvidesResize,
    HasResizeHandlers {

  /**
   * Implementation of resize event.
   */
  abstract static class Impl {
    /**
     * Delegate event handler.
     */
    abstract static interface Delegate {
      /**
       * Called when the element is resized.
       */
      void onResize();
    }

    boolean isAttached;
    Element parent;
    private Delegate delegate;

    /**
     * Initialize the implementation.
     * 
     * @param elem the element to listen for resize
     * @param delegate the {@link Delegate} to inform when resize occurs
     */
    public void init(Element elem, Delegate delegate) {
      this.parent = elem;
      this.delegate = delegate;
    }

    /**
     * Called on attach.
     */
    public void onAttach() {
      isAttached = true;
    }

    /**
     * Called on detach.
     */
    public void onDetach() {
      isAttached = false;
    }

    /**
     * Handle a resize event.
     */
    protected void handleResize() {
      if (isAttached && delegate != null) {
        delegate.onResize();
      }
    }
  }

  /**
   * Implementation of resize event.
   */
  static class ImplStandard extends Impl implements EventListener {
    /**
     * Chrome does not fire an onresize event if the dimensions are too small to
     * render a scrollbar.
     */
    private static final String MIN_SIZE = "20px";

    private Element collapsible;
    private Element collapsibleInner;
    private Element expandable;
    private Element expandableInner;
    private int lastOffsetHeight = -1;
    private int lastOffsetWidth = -1;
    private boolean resettingScrollables;

    @Override
    public void init(Element elem, Delegate delegate) {
      super.init(elem, delegate);

      /*
       * Set the minimum dimensions to ensure that scrollbars are rendered and
       * fire onscroll events.
       */
      elem.getStyle().setProperty("minWidth", MIN_SIZE);
      elem.getStyle().setProperty("minHeight", MIN_SIZE);

      /*
       * Detect expansion. In order to detect an increase in the size of the
       * widget, we create an absolutely positioned, scrollable div with
       * height=width=100%. We then add an inner div that has fixed height and
       * width equal to 100% (converted to pixels) and set scrollLeft/scrollTop
       * to their maximum. When the outer div expands, scrollLeft/scrollTop
       * automatically becomes a smaller number and trigger an onscroll event.
       */
      expandable = Document.get().createDivElement().cast();
      expandable.getStyle().setVisibility(Visibility.HIDDEN);
      expandable.getStyle().setPosition(Position.ABSOLUTE);
      expandable.getStyle().setHeight(100.0, Unit.PCT);
      expandable.getStyle().setWidth(100.0, Unit.PCT);
      expandable.getStyle().setOverflow(Overflow.SCROLL);
      expandable.getStyle().setZIndex(-1);
      elem.appendChild(expandable);
      expandableInner = Document.get().createDivElement().cast();
      expandable.appendChild(expandableInner);
      DOM.sinkEvents(expandable, Event.ONSCROLL);

      /*
       * Detect collapse. In order to detect a decrease in the size of the
       * widget, we create an absolutely positioned, scrollable div with
       * height=width=100%. We then add an inner div that has height=width=200%
       * and max out the scrollTop/scrollLeft. When the height or width
       * decreases, the inner div loses 2px for every 1px that the scrollable
       * div loses, so the scrollTop/scrollLeft decrease and we get an onscroll
       * event.
       */
      collapsible = Document.get().createDivElement().cast();
      collapsible.getStyle().setVisibility(Visibility.HIDDEN);
      collapsible.getStyle().setPosition(Position.ABSOLUTE);
      collapsible.getStyle().setHeight(100.0, Unit.PCT);
      collapsible.getStyle().setWidth(100.0, Unit.PCT);
      collapsible.getStyle().setOverflow(Overflow.SCROLL);
      collapsible.getStyle().setZIndex(-1);
      elem.appendChild(collapsible);
      collapsibleInner = Document.get().createDivElement().cast();
      collapsibleInner.getStyle().setWidth(200, Unit.PCT);
      collapsibleInner.getStyle().setHeight(200, Unit.PCT);
      collapsible.appendChild(collapsibleInner);
      DOM.sinkEvents(collapsible, Event.ONSCROLL);
    }

    @Override
    public void onAttach() {
      super.onAttach();
      DOM.setEventListener(expandable, this);
      DOM.setEventListener(collapsible, this);

      /*
       * Update the scrollables in a deferred command so the browser calculates
       * the offsetHeight/Width correctly.
       */
      Scheduler.get().scheduleDeferred(new ScheduledCommand() {
        public void execute() {
          resetScrollables();
        }
      });
    }

    public void onBrowserEvent(Event event) {
      if (!resettingScrollables && Event.ONSCROLL == event.getTypeInt()) {
        EventTarget eventTarget = event.getEventTarget();
        if (!Element.is(eventTarget)) {
          return;
        }
        Element target = eventTarget.cast();
        if (target == collapsible || target == expandable) {
          handleResize();
        }
      }
    }

    @Override
    public void onDetach() {
      super.onDetach();
      DOM.setEventListener(expandable, null);
      DOM.setEventListener(collapsible, null);
      lastOffsetHeight = -1;
      lastOffsetWidth = -1;
    }

    @Override
    protected void handleResize() {
      if (resetScrollables()) {
        super.handleResize();
      }
    }

    /**
     * Reset the positions of the scrollable elements.
     * 
     * @return true if the size changed, false if not
     */
    private boolean resetScrollables() {
      /*
       * Older versions of safari trigger a synchronous scroll event when we
       * update scrollTop/scrollLeft, so we set a boolean to ignore that event.
       */
      if (resettingScrollables) {
        return false;
      }
      resettingScrollables = true;

      /*
       * Reset expandable element. Scrollbars are not rendered if the div is too
       * small, so we need to set the dimensions of the inner div to a value
       * greater than the offsetWidth/Height.
       */
      int offsetHeight = parent.getOffsetHeight();
      int offsetWidth = parent.getOffsetWidth();
      int height = offsetHeight + 100;
      int width = offsetWidth + 100;
      expandableInner.getStyle().setHeight(height, Unit.PX);
      expandableInner.getStyle().setWidth(width, Unit.PX);
      expandable.setScrollTop(height);
      expandable.setScrollLeft(width);

      // Reset collapsible element.
      collapsible.setScrollTop(collapsible.getScrollHeight() + 100);
      collapsible.setScrollLeft(collapsible.getScrollWidth() + 100);

      if (lastOffsetHeight != offsetHeight || lastOffsetWidth != offsetWidth) {
        lastOffsetHeight = offsetHeight;
        lastOffsetWidth = offsetWidth;
        resettingScrollables = false;
        return true;
      }
      resettingScrollables = false;
      return false;
    }
  }

  /**
   * Implementation of resize event used by IE.
   */
  static class ImplTrident extends Impl {

    @Override
    public void init(Element elem, Delegate delegate) {
      super.init(elem, delegate);
      initResizeEventListener(elem);
    }

    @Override
    public void onAttach() {
      super.onAttach();
      setResizeEventListener(parent, this);
    }

    @Override
    public void onDetach() {
      super.onDetach();
      setResizeEventListener(parent, null);
    }

    /**
     * Initalize the onresize listener. This method doesn't create a memory leak
     * because we don't set a back reference to the Impl class until we attach
     * to the DOM.
     */
    private native void initResizeEventListener(Element elem) /*-{
      var theElem = elem;
      var handleResize = $entry(function() {
        if (theElem.__resizeImpl) {
          theElem.__resizeImpl.@com.google.gwt.user.client.ui.ResizeLayoutPanel.Impl::handleResize()();
        }
      });
      elem.attachEvent('onresize', handleResize);
    }-*/;

    /**
     * Set the event listener that handles resize events.
     */
    private native void setResizeEventListener(Element elem, Impl listener) /*-{
      elem.__resizeImpl = listener;
    }-*/;
  }

  /**
   * Implementation of resize event used by IE6.
   */
  static class ImplIE6 extends ImplTrident {
    @Override
    public void onAttach() {
      super.onAttach();

      /*
       * IE6 doesn't render this panel unless you kick it after its been
       * attached.
       */
      Scheduler.get().scheduleDeferred(new ScheduledCommand() {
        public void execute() {
          if (isAttached) {
            parent.getStyle().setProperty("zoom", "1");
          }
        }
      });
    }
  }

  private final Impl impl = GWT.create(Impl.class);
  private Layer layer;
  private final Layout layout;
  private final ScheduledCommand resizeCmd = new ScheduledCommand() {
    public void execute() {
      resizeCmdScheduled = false;
      handleResize();
    }
  };
  private boolean resizeCmdScheduled = false;

  public ResizeLayoutPanel() {
    layout = new Layout(getElement());
    impl.init(getElement(), new Delegate() {
      public void onResize() {
        scheduleResize();
      }
    });
  }

  public HandlerRegistration addResizeHandler(ResizeHandler handler) {
    return addHandler(handler, ResizeEvent.getType());
  }

  @Override
  public boolean remove(Widget w) {
    // Validate.
    if (widget != w) {
      return false;
    }

    // Orphan.
    try {
      orphan(w);
    } finally {
      // Physical detach.
      layout.removeChild(layer);
      layer = null;

      // Logical detach.
      widget = null;
    }
    return true;
  }

  @Override
  public void setWidget(Widget w) {
    // Validate
    if (w == widget) {
      return;
    }

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

    // Remove old child.
    if (widget != null) {
      remove(widget);
    }

    // Logical attach.
    widget = w;

    if (w != null) {
      // Physical attach.
      layer = layout.attachChild(widget.getElement(), widget);
      layer.setTopHeight(0.0, Unit.PX, 100.0, Unit.PCT);
      layer.setLeftWidth(0.0, Unit.PX, 100.0, Unit.PCT);

      adopt(w);

      // Update the layout.
      layout.layout();
      scheduleResize();
    }
  }

  @Override
  protected void onAttach() {
    super.onAttach();
    impl.onAttach();
    layout.onAttach();
    scheduleResize();
  }

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

  private void handleResize() {
    if (!isAttached()) {
      return;
    }

    // Provide resize to child.
    if (widget instanceof RequiresResize) {
      ((RequiresResize) widget).onResize();
    }

    // Fire resize event.
    ResizeEvent.fire(this, getOffsetWidth(), getOffsetHeight());
  }

  /**
   * Schedule a resize handler. We schedule the event so the DOM has time to
   * update the offset sizes, and to avoid duplicate resize events from both a
   * height and width resize.
   */
  private void scheduleResize() {
    if (isAttached() && !resizeCmdScheduled) {
      resizeCmdScheduled = true;
      Scheduler.get().scheduleDeferred(resizeCmd);
    }
  }
}
