/*
 * 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.EM;
import static com.google.gwt.dom.client.Style.Unit.EX;
import static com.google.gwt.dom.client.Style.Unit.PX;

import com.google.gwt.aria.client.State;
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;
import com.google.gwt.dom.client.Style.Display;
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.layout.client.Layout.Layer;

/**
 * Default implementation, which works with all browsers except for IE6. It uses
 * only the "top", "left", "bottom", "right", "width", and "height" CSS
 * properties.
 * 
 * Note: This implementation class has state, so {@link Layout} must create a
 * new instance for each layout-parent.
 *
 * <p>Deprecated, as this is the only implementation, it may be removed in a future
 * release.</p>
 */
@Deprecated
class LayoutImpl {

  private static DivElement fixedRuler;

  static {
    fixedRuler = createRuler(Unit.CM, Unit.CM);
    Document.get().getBody().appendChild(fixedRuler);
  }

  protected static DivElement createRuler(Unit widthUnit, Unit heightUnit) {
    DivElement ruler = Document.get().createDivElement();
    ruler.setInnerHTML("&nbsp;");
    Style style = ruler.getStyle();
    style.setPosition(Position.ABSOLUTE);
    style.setZIndex(-32767);

    // Position the ruler off the top edge, double the size just to be
    // extra sure it doesn't show up on the screen.
    style.setTop(-20, heightUnit);

    // Note that we are making the ruler element 10x10, because some browsers
    // generate non-integral ratios (e.g., 1em == 13.3px), so we need a little
    // extra precision.
    style.setWidth(10, widthUnit);
    style.setHeight(10, heightUnit);

    style.setVisibility(Visibility.HIDDEN);
    State.HIDDEN.set(ruler, true);
    return ruler;
  }

  protected DivElement relativeRuler;

  public Element attachChild(Element parent, Element child, Element before) {
    DivElement container = Document.get().createDivElement();
    container.appendChild(child);

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

    fillParent(child);

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

  public void fillParent(Element elem) {
    Style style = elem.getStyle();
    style.setPosition(Position.ABSOLUTE);
    style.setLeft(0, PX);
    style.setTop(0, PX);
    style.setRight(0, PX);
    style.setBottom(0, PX);
  }

  /**
   * @param parent the parent element
   */
  public void finalizeLayout(Element parent) {
  }

  public double getUnitSizeInPixels(
      Element parent, Unit unit, boolean vertical) {
    if (unit == null) {
      return 1;
    }

    switch (unit) {
      case PCT:
        return (vertical ? parent.getClientHeight() : parent.getClientWidth())
            / 100.0;
      case EM:
        return relativeRuler.getOffsetWidth() / 10.0;
      case EX:
        return relativeRuler.getOffsetHeight() / 10.0;
      case CM:
        return fixedRuler.getOffsetWidth() * 0.1; // 1.0 cm / cm
      case MM:
        return fixedRuler.getOffsetWidth() * 0.01; // 0.1 cm / mm
      case IN:
        return fixedRuler.getOffsetWidth() * 0.254; // 2.54 cm / in
      case PT:
        return fixedRuler.getOffsetWidth() * 0.00353; // 0.0353 cm / pt
      case PC:
        return fixedRuler.getOffsetWidth() * 0.0423; // 0.423 cm / pc
      default:
      case PX:
        return 1;
    }
  }

  public void initParent(Element parent) {
    parent.getStyle().setPosition(Position.RELATIVE);
    parent.appendChild(relativeRuler = createRuler(EM, EX));
  }

  public void layout(Layer layer) {
    Style style = layer.container.getStyle();

    if (layer.visible) {
      style.clearDisplay();
    } else {
      style.setDisplay(Display.NONE);
    }

    style.setProperty(
        "left", layer.setLeft ? (layer.left + layer.leftUnit.getType()) : "");
    style.setProperty(
        "top", layer.setTop ? (layer.top + layer.topUnit.getType()) : "");
    style.setProperty("right",
        layer.setRight ? (layer.right + layer.rightUnit.getType()) : "");
    style.setProperty("bottom",
        layer.setBottom ? (layer.bottom + layer.bottomUnit.getType()) : "");
    style.setProperty("width",
        layer.setWidth ? (layer.width + layer.widthUnit.getType()) : "");
    style.setProperty("height",
        layer.setHeight ? (layer.height + layer.heightUnit.getType()) : "");

    style = layer.child.getStyle();
    switch (layer.hPos) {
      case BEGIN:
        style.setLeft(0, Unit.PX);
        style.clearRight();
        break;
      case END:
        style.clearLeft();
        style.setRight(0, Unit.PX);
        break;
      case STRETCH:
        style.setLeft(0, Unit.PX);
        style.setRight(0, Unit.PX);
        break;
    }

    switch (layer.vPos) {
      case BEGIN:
        style.setTop(0, Unit.PX);
        style.clearBottom();
        break;
      case END:
        style.clearTop();
        style.setBottom(0, Unit.PX);
        break;
      case STRETCH:
        style.setTop(0, Unit.PX);
        style.setBottom(0, Unit.PX);
        break;
    }
  }

  @SuppressWarnings("unused")
  public void onAttach(Element parent) {
    // Do nothing. This exists only to help LayoutImplIE6 avoid memory leaks.
  }

  @SuppressWarnings("unused")
  public void onDetach(Element parent) {
    // Do nothing. This exists only to help LayoutImplIE6 avoid memory leaks.
  }

  public void removeChild(Element container, Element child) {
    container.removeFromParent();

    // We want this code to be resilient to the child having already been
    // removed from its container (perhaps by widget code).
    if (child.getParentElement() == container) {
      child.removeFromParent();
    }

    // Cleanup child styles set by fillParent().
    Style style = child.getStyle();
    style.clearPosition();
    style.clearLeft();
    style.clearTop();
    style.clearWidth();
    style.clearHeight();
  }
}
