/*
 * 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.layout.client;

import static com.google.gwt.dom.client.Style.Unit.PX;

import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Overflow;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.layout.client.Layout.Layer;
import com.google.gwt.user.client.Window;

/**
 * IE6-specific implementation, which uses the "onresize" event, along with a
 * series of measurement tools, to deal with several IE6 bugs. Specifically,
 * IE6 doesn't support simultaneous left-right and top-bottom values, and it
 * misplaces by one pixel elements whose right/bottom properties are set.
 * 
 * Because this implementation gets compiled in for both IE6 and 7, it
 * dynamically detects IE7 and punts to the super implementation.
 */
class LayoutImplIE6 extends LayoutImplIE8 {

  private static boolean isIE6 = isIE6();

  // Stolen and modified from UserAgent.gwt.xml.
  // TODO(jgw): Get rid of this method, and switch to using soft permutations
  // once they land in trunk.
  private static native boolean isIE6() /*-{
     function makeVersion(result) {
       return (parseInt(result[1]) * 1000) + parseInt(result[2]);
     }

     var ua = navigator.userAgent.toLowerCase();
     if (ua.indexOf("msie") != -1) {
       var result = /msie ([0-9]+)\.([0-9]+)/.exec(ua);
       if (result && result.length == 3) {
         var v = makeVersion(result);
         if (v < 7000) {
           return true;
         }
       }
     }

     return false;
   }-*/;

  private static Element createStyleRuler(Element parent) {
    DivElement styleRuler = Document.get().createDivElement();
    DivElement styleInner = Document.get().createDivElement();

    styleRuler.getStyle().setPosition(Position.ABSOLUTE);
    styleRuler.getStyle().setLeft(-10000, PX);

    parent.appendChild(styleRuler);
    styleRuler.appendChild(styleInner);
    return styleRuler;
  }

  @SuppressWarnings("unused") // called from JSNI
  private static void hookWindowResize(final Element elem) {
    Window.addResizeHandler(new ResizeHandler() {
      public void onResize(ResizeEvent event) {
        resizeRelativeToParent(elem);
      }
    });
  }

  @SuppressWarnings("unused") // called from JSNI
  private static native void measureDecoration(Element elem) /*-{
    var ruler = elem.__styleRuler;
    var inner = ruler.children[0];
    var s = inner.style, cs = elem.currentStyle;

    s.borderLeftStyle = cs.borderLeftStyle;
    s.borderRightStyle = cs.borderRightStyle;
    s.borderTopStyle = cs.borderTopStyle;
    s.borderBottomStyle = cs.borderBottomStyle;

    s.borderLeftWidth = cs.borderLeftWidth;
    s.borderRightWidth = cs.borderRightWidth;
    s.borderTopWidth = cs.borderTopWidth;
    s.borderBottomWidth = cs.borderBottomWidth;

    // Oddly enough, allowing the word 'auto' to creep into the style
    // ruler's margin causes it to take up all of its parent's space.
    s.marginLeft = (cs.marginLeft == 'auto') ? '' : cs.marginLeft;
    s.marginRight = (cs.marginRight == 'auto') ? '' : cs.marginRight;
    s.marginTop = (cs.marginTop == 'auto') ? '' : cs.marginTop;
    s.marginBottom = (cs.marginBottom == 'auto') ? '' : cs.marginBottom;

    s.paddingLeft = cs.paddingLeft;
    s.paddingRight = cs.paddingRight;
    s.paddingTop = cs.paddingTop;
    s.paddingBottom = cs.paddingBottom;

    s.width = s.height = 32;
    elem.__decoWidth = ruler.offsetWidth - 32;
    elem.__decoHeight = ruler.offsetHeight - 32;
  }-*/;

  private static native void resizeRelativeToParent(Element elem) /*-{
    var parent = elem.__resizeParent;
    if (parent) {
      @com.google.gwt.layout.client.LayoutImplIE6::measureDecoration(Lcom/google/gwt/dom/client/Element;)(elem);
      elem.style.left = 0;
      elem.style.top = 0;
      elem.style.width = parent.clientWidth - elem.__decoWidth;
      elem.style.height = parent.clientHeight - elem.__decoHeight;
    }
  }-*/;

  private static native void setLayer(Element container, Layer layer) /*-{
    // Potential leak: This is cleaned up in detach().
    container.__layer = layer;
  }-*/;

  private static native void setPropertyElement(Element elem, String name,
      Element value) /*-{
    elem[name] = value;
  }-*/;

  @Override
  public Element attachChild(Element parent, Element child, Element before) {
    if (!isIE6) {
      return super.attachChild(parent, child, before);
    }

    DivElement container = Document.get().createDivElement();
    container.appendChild(child);

    container.getStyle().setPosition(Position.ABSOLUTE);
    container.getStyle().setOverflow(Overflow.HIDDEN);
    child.getStyle().setPosition(Position.ABSOLUTE);

    // Hang the style ruler from the container element, but associate it with
    // the child element, so that measureDecoration(child) will work.
    setPropertyElement(child, "__styleRuler", createStyleRuler(container));

    Element beforeContainer = null;
    if (before != null) {
      beforeContainer = before.getParentElement();
      assert beforeContainer.getParentElement() == parent : "Element to insert before must be a sibling";
    }
    parent.insertBefore(container, beforeContainer);
    return container;
  }

  @Override
  public void fillParent(Element elem) {
    if (!isIE6) {
      super.fillParent(elem);
      return;
    }

    fillParentImpl(elem);
  }

  @Override
  public void finalizeLayout(Element parent) {
    if (!isIE6) {
      super.finalizeLayout(parent);
      return;
    }

    resizeRelativeToParent(parent);
    resizeHandler(parent, true);
  }

  @Override
  public void initParent(Element parent) {
    super.initParent(parent);

    if (isIE6) {
      setPropertyElement(parent, "__styleRuler", createStyleRuler(parent));
    }
  }

  public void layout(Layer layer) {
    if (!isIE6) {
      super.layout(layer);
      return;
    }

    Element elem = layer.getContainerElement();
    setLayer(elem, layer);
  }

  @Override
  public void onAttach(Element parent) {
    if (isIE6) {
      // No need to re-connect layer refs. This will be taken care of
      // automatically in layout().
      initResizeHandler(parent);
      initUnitChangeHandler(parent, relativeRuler);
    }
  }

  @Override
  public void onDetach(Element parent) {
    if (isIE6) {
      removeLayerRefs(parent);
      removeResizeHandler(parent);
      removeUnitChangeHandler(relativeRuler);
    }
  }

  private native void fillParentImpl(Element elem) /*-{
    // Hook the parent element's onresize event. If the parent is the <body>,
    // then we have to go through the Window class to get the resize event,
    // because IE6 requires a bunch of foul hackery to safely hook it.
    var parent = elem.parentElement;
    if (parent.tagName.toLowerCase() == 'body') {
      elem.style.position = 'absolute';
      var docElem = parent.parentElement;
      elem.__resizeParent = docElem;
      @com.google.gwt.layout.client.LayoutImplIE6::hookWindowResize(Lcom/google/gwt/dom/client/Element;)(elem);
      return;
    }

    function resize() {
      @com.google.gwt.layout.client.LayoutImplIE6::resizeRelativeToParent(Lcom/google/gwt/dom/client/Element;)(elem);
    }

    elem.__resizeParent = parent;
    parent.onresize = resize;
    resize();
  }-*/;

  /**
   * This does not call $entry() because no user code is reachable from
   * resizeHandler.
   */
  private native void initResizeHandler(Element parent) /*-{
    // Potential leak: This is cleaned up in detach().
    var self = this;
    parent.onresize = function() {
      self.@com.google.gwt.layout.client.LayoutImplIE6::resizeHandler(Lcom/google/gwt/dom/client/Element;)(parent);
    };
  }-*/;

  /**
   * This does not call $entry() because no user code is reachable from
   * resizeHandler.
   */
  private native void initUnitChangeHandler(Element parent, Element ruler) /*-{
    // Potential leak: This is cleaned up in detach().
    var self = this;
    ruler.onresize = function() {
      self.@com.google.gwt.layout.client.LayoutImplIE6::resizeHandler(Lcom/google/gwt/dom/client/Element;Z)(parent, true);
    };
  }-*/;

  private native void removeLayerRefs(Element parent) /*-{
    for (var i = 0; i < parent.childNodes.length; ++i) {
      var container = parent.childNodes[i];
      if (container.__layer) {
        container.__layer = null;
      }
    }
  }-*/;

  private native void removeResizeHandler(Element parent) /*-{
    parent.onresize = null;
  }-*/;

  private native void removeUnitChangeHandler(Element ruler) /*-{
    ruler.onresize = null;
  }-*/;


  @SuppressWarnings("unused") // called from JSNI
  private void resizeHandler(Element parent) {
    resizeHandler(parent, false);
  }
  
  private native void resizeHandler(Element parent, boolean force) /*-{
    if (!force &&
        ((parent.offsetWidth == parent.__oldWidth) &&
         (parent.offsetHeight == parent.__oldHeight))) {
      return;
    }
    parent.__oldWidth = parent.offsetWidth;
    parent.__oldHeight = parent.offsetHeight;

    var parentWidth = parent.clientWidth;
    var parentHeight = parent.clientHeight;

    // Iterate over the children, assuming each of them is an unstyled
    // container element.
    for (var i = 0; i < parent.childNodes.length; ++i) {
      // Don't attempt to layout the rulers.
      var container = parent.childNodes[i];
      var layer = container.__layer;
      if (!layer) {
        continue;
      }

      // This is ugly, but it's less ugly than writing all these JSNI refs inline.
      var _setLeft = layer.@com.google.gwt.layout.client.Layout.Layer::setLeft;
      var _setTop = layer.@com.google.gwt.layout.client.Layout.Layer::setTop;
      var _setWidth = layer.@com.google.gwt.layout.client.Layout.Layer::setWidth;
      var _setHeight = layer.@com.google.gwt.layout.client.Layout.Layer::setHeight;
      var _setRight = layer.@com.google.gwt.layout.client.Layout.Layer::setRight;
      var _setBottom = layer.@com.google.gwt.layout.client.Layout.Layer::setBottom;

      var _left = layer.@com.google.gwt.layout.client.Layout.Layer::left;
      var _top = layer.@com.google.gwt.layout.client.Layout.Layer::top;
      var _width = layer.@com.google.gwt.layout.client.Layout.Layer::width;
      var _height = layer.@com.google.gwt.layout.client.Layout.Layer::height;
      var _right = layer.@com.google.gwt.layout.client.Layout.Layer::right;
      var _bottom = layer.@com.google.gwt.layout.client.Layout.Layer::bottom;

      var _leftUnit = layer.@com.google.gwt.layout.client.Layout.Layer::leftUnit;
      var _topUnit = layer.@com.google.gwt.layout.client.Layout.Layer::topUnit;
      var _widthUnit = layer.@com.google.gwt.layout.client.Layout.Layer::widthUnit;
      var _heightUnit = layer.@com.google.gwt.layout.client.Layout.Layer::heightUnit;
      var _rightUnit = layer.@com.google.gwt.layout.client.Layout.Layer::rightUnit;
      var _bottomUnit = layer.@com.google.gwt.layout.client.Layout.Layer::bottomUnit;

      var _hPos = layer.@com.google.gwt.layout.client.Layout.Layer::hPos
                  .@com.google.gwt.layout.client.Layout.Alignment::ordinal()();
      var _vPos = layer.@com.google.gwt.layout.client.Layout.Layer::vPos
                  .@com.google.gwt.layout.client.Layout.Alignment::ordinal()();

      // Apply the requested position & size values to the element's style.
      var style = container.style;
      style.left = _setLeft ? (_left + _leftUnit.@com.google.gwt.dom.client.Style.Unit::getType()()) : "";
      style.top = _setTop ? (_top + _topUnit.@com.google.gwt.dom.client.Style.Unit::getType()()) : "";
      style.width = _setWidth ? (_width + _widthUnit.@com.google.gwt.dom.client.Style.Unit::getType()()) : "";
      style.height = _setHeight ? (_height + _heightUnit.@com.google.gwt.dom.client.Style.Unit::getType()()) : "";

      // If right is defined, reposition/size the container horizontally.
      if (_setRight) {
        var ratio = this.@com.google.gwt.layout.client.LayoutImplIE6::getUnitSizeInPixels(Lcom/google/gwt/dom/client/Element;Lcom/google/gwt/dom/client/Style$Unit;Z)(parent, _rightUnit, false);
        var right = parentWidth - (_right * ratio);

        if (!_setLeft) {
          // There's no left defined; adjust the left position move the element to the right edge.
          container.style.left = (right - container.offsetWidth) + 'px';
        } else {
          // Both left and right are defined; calculate the width and set it.
          var leftRatio = this.@com.google.gwt.layout.client.LayoutImplIE6::getUnitSizeInPixels(Lcom/google/gwt/dom/client/Element;Lcom/google/gwt/dom/client/Style$Unit;Z)(parent, _leftUnit, false);
          var left = (_left * leftRatio);
          if (right > left) {
            container.style.width = (right - left) + 'px';
          }
        }
      }

      // If bottom is defined, reposition/size the container vertically.
      if (_setBottom) {
        var ratio = this.@com.google.gwt.layout.client.LayoutImplIE6::getUnitSizeInPixels(Lcom/google/gwt/dom/client/Element;Lcom/google/gwt/dom/client/Style$Unit;Z)(parent, _bottomUnit, true);
        var bottom = parentHeight - (_bottom * ratio);

        if (!_setTop) {
          // There's no top defined; adjust the left position move the element to the bottom edge.
          container.style.top = (bottom - container.offsetHeight) + 'px';
        } else {
          // Both top and bottom are defined; calculate the height and set it.
          var topRatio = this.@com.google.gwt.layout.client.LayoutImplIE6::getUnitSizeInPixels(Lcom/google/gwt/dom/client/Element;Lcom/google/gwt/dom/client/Style$Unit;Z)(parent, _topUnit, true);
          var top = (_top * topRatio);
          if (bottom > top) {
            container.style.height = (bottom - top) + 'px';
          }
        }
      }

      // Resize and position the child based on the layer's [hv]Pos.
      var child = container.firstChild;
      @com.google.gwt.layout.client.LayoutImplIE6::measureDecoration(Lcom/google/gwt/dom/client/Element;)(child);
      var childDecoWidth = child.__decoWidth;
      var childDecoHeight = child.__decoHeight;

      if (container.offsetWidth > childDecoWidth) {
        switch (_hPos) {
          case 0: // BEGIN
            child.style.left = '0px';
            break;
          case 1: // END
            child.style.left = (container.offsetWidth - childDecoWidth - child.offsetWidth) + 'px';
            break;
          case 2: // STRETCH
            child.style.left = '0px';
            child.style.width = (container.offsetWidth - childDecoWidth) + 'px';
            break;
        }
      }
      if (container.offsetHeight > childDecoHeight) {
        switch (_vPos) {
          case 0: // BEGIN
            child.style.top = '0px';
            break;
          case 1: // END
            child.style.top = (container.offsetHeight - childDecoHeight - child.offsetHeight) + 'px';
            break;
          case 2: // STRETCH
            child.style.top = '0px';
            child.style.height = (container.offsetHeight - childDecoHeight) + 'px';
            break;
        }
      }
    }
  }-*/;
}
