/*
 * 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.CM;
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.IN;
import static com.google.gwt.dom.client.Style.Unit.MM;
import static com.google.gwt.dom.client.Style.Unit.PC;
import static com.google.gwt.dom.client.Style.Unit.PCT;
import static com.google.gwt.dom.client.Style.Unit.PT;
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.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.junit.DoNotRunWith;
import com.google.gwt.junit.Platform;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.layout.client.Layout.Alignment;
import com.google.gwt.layout.client.Layout.Layer;
import com.google.gwt.user.client.ResizeHelper;
import com.google.gwt.user.client.Window;

/**
 * Tests for the {@link Layout} class.
 */
public class LayoutTest extends GWTTestCase {

  /**
   * The amount of time to wait for asynchronous tests to finish.
   */
  private static final int TEST_DELAY = 2000;

  private static interface LayerInitializer {
    void setupLayers(Layer l0, Layer l1);
  }

  private DivElement parent, child0, child1;
  private Element wrapper0, wrapper1;
  private Layout layout;
  private Layer layer0, layer1;

  @Override
  public String getModuleName() {
    return "com.google.gwt.layout.LayoutTest";
  }

  // All testAnimationTransitions_* tests are disabled because they are flaky
  /**
   * Tests animation constraint- and unit-transitions.
   */
  public void notestAnimationTransitions_LTWH_LTRB_PX_CM() {
    testAnimationTransitions_LTWH_LTRB(PX, CM);
  }

  /**
   * Tests animation constraint- and unit-transitions.
   */
  public void notestAnimationTransitions_LTWH_LTRB_PX_EM() {
    testAnimationTransitions_LTWH_LTRB(PX, EM);
  }

  /**
   * Tests animation constraint- and unit-transitions.
   */
  public void notestAnimationTransitions_LTWH_LTRB_PX_EX() {
    testAnimationTransitions_LTWH_LTRB(PX, EX);
  }

  /**
   * Tests animation constraint- and unit-transitions.
   */
  public void notestAnimationTransitions_LTWH_LTRB_PX_PCT() {
    testAnimationTransitions_LTWH_LTRB(PX, PCT);
  }

  /**
   * Tests animation constraint- and unit-transitions.
   */
  public void notestAnimationTransitions_LTWH_RBWH_PX_CM() {
    testAnimationTransitions_LTWH_RBWH(PX, CM);
  }

  /**
   * Tests animation constraint- and unit-transitions.
   */
  public void notestAnimationTransitions_LTWH_RBWH_PX_EM() {
    testAnimationTransitions_LTWH_RBWH(PX, EM);
  }

  /**
   * Tests animation constraint- and unit-transitions.
   */
  public void notestAnimationTransitions_LTWH_RBWH_PX_EX() {
    testAnimationTransitions_LTWH_RBWH(PX, EX);
  }

  /**
   * Tests animation constraint- and unit-transitions.
   */
  public void notestAnimationTransitions_LTWH_RBWH_PX_PCT() {
    testAnimationTransitions_LTWH_RBWH(PX, PCT);
  }

  /**
   * Tests animation constraint- and unit-transitions.
   */
  public void notestAnimationTransitions_RBWH_LTRB_PX_CM() {
    testAnimationTransitions_RBWH_LTRB(PX, CM);
  }

  /**
   * Tests animation constraint- and unit-transitions.
   */
  public void notestAnimationTransitions_RBWH_LTRB_PX_EM() {
    testAnimationTransitions_RBWH_LTRB(PX, EM);
  }

  /**
   * Tests animation constraint- and unit-transitions.
   */
  public void notestAnimationTransitions_RBWH_LTRB_PX_EX() {
    testAnimationTransitions_RBWH_LTRB(PX, EX);
  }

  /**
   * Tests animation constraint- and unit-transitions.
   */
  public void notestAnimationTransitions_RBWH_LTRB_PX_PCT() {
    testAnimationTransitions_RBWH_LTRB(PX, PCT);
  }

  /**
   * Tests child alignment within a layer.
   */
  @DoNotRunWith(Platform.HtmlUnitLayout)
  public void testChildAlignment() {
    layer0.setLeftWidth(0, PX, 128, PX);
    layer0.setTopHeight(0, PX, 256, PX);

    layer0.setChildHorizontalPosition(Alignment.STRETCH);
    layer0.setChildVerticalPosition(Alignment.STRETCH);
    layout.layout();
    assertEquals(0, child0.getOffsetLeft());
    assertEquals(0, child0.getOffsetTop());
    assertEquals(128, child0.getOffsetWidth());
    assertEquals(256, child0.getOffsetHeight());

    child0.getStyle().setWidth(64, PX);
    child0.getStyle().setHeight(128, PX);

    layer0.setChildHorizontalPosition(Alignment.BEGIN);
    layer0.setChildVerticalPosition(Alignment.BEGIN);
    layout.layout();
    assertEquals(0, child0.getOffsetLeft());
    assertEquals(0, child0.getOffsetTop());
    assertEquals(64, child0.getOffsetWidth());
    assertEquals(128, child0.getOffsetHeight());

    layer0.setChildHorizontalPosition(Alignment.END);
    layer0.setChildVerticalPosition(Alignment.END);
    layout.layout();
    assertEquals(64, child0.getOffsetLeft());
    assertEquals(128, child0.getOffsetTop());
    assertEquals(64, child0.getOffsetWidth());
    assertEquals(128, child0.getOffsetHeight());
  }

  /**
   * Test that fillParent() works properly when the outer div is a child of
   * another div, and that it correctly follows that div's size.
   */
  @DoNotRunWith(Platform.HtmlUnitLayout)
  public void testFillParent() {
    // We don't use the default elements created in gwtSetUp() because we need
    // to test the behavior when the layout is contained by an element other
    // than the <body>.
    Document doc = Document.get();
    DivElement container = doc.createDivElement();
    DivElement parent = doc.createDivElement();
    DivElement child = doc.createDivElement();
    child.setInnerHTML("&nbsp;");
    doc.getBody().appendChild(container);
    container.appendChild(parent);

    // The container has to be position:relative so that it serves as an offset
    // parent.
    container.getStyle().setPosition(Position.RELATIVE);
    container.getStyle().setWidth(128, PX);
    container.getStyle().setHeight(256, PX);

    Layout layout = new Layout(parent);
    layout.onAttach();
    Layer layer = layout.attachChild(child);
    layer.setTopBottom(0, PX, 0, PX);
    layer.setLeftRight(0, PX, 0, PX);

    layout.fillParent();
    layout.layout();

    // Test 128x256.
    assertEquals(128, container.getOffsetWidth());
    assertEquals(256, container.getOffsetHeight());
    assertEquals(128, parent.getOffsetWidth());
    assertEquals(256, parent.getOffsetHeight());
    assertEquals(128, child.getOffsetWidth());
    assertEquals(256, child.getOffsetHeight());

    // Expand to 256x256. The layout should react automatically.
    container.getStyle().setWidth(256, PX);
    container.getStyle().setHeight(128, PX);
    assertEquals(256, container.getOffsetWidth());
    assertEquals(256, parent.getOffsetWidth());
    assertEquals(256, child.getOffsetWidth());

    layout.onDetach();
  }

  /**
   * Test that fillParent() works properly when the outer div is a child of the
   * document body.
   */
  @DoNotRunWith(Platform.HtmlUnitLayout)
  public void testFillWindow() {
    layer0.setTopBottom(0, PX, 0, PX);
    layer0.setLeftRight(0, PX, 0, PX);
    layout.layout();

    int w = Window.getClientWidth();
    int h = Window.getClientHeight();
    assertEquals(w, parent.getOffsetWidth());
    assertEquals(h, parent.getOffsetHeight());
    assertEquals(w, child0.getOffsetWidth());
    assertEquals(h, child0.getOffsetHeight());
  }

  /**
   * Tests that the layout reacts to font-size changes.
   * 
   * TODO(jgw): Enable this test when it is fixed for IE8.
   */
  public void disabledTestFontSizeChange() {
    layer0.setLeftWidth(0, PX, 1, EM);
    layer0.setTopHeight(0, PX, 1, EM);
    layout.layout();

    parent.getStyle().setFontSize(12, PT);
    int cw = child0.getOffsetWidth();
    int ch = child0.getOffsetHeight();

    parent.getStyle().setFontSize(24, PT);
    int nw = child0.getOffsetWidth();
    int nh = child0.getOffsetHeight();
    assertTrue(nw > cw);
    assertTrue(nh > ch);

    parent.getStyle().clearFontSize();
  }

  /**
   * Ensures that two children laid out using various units in such a way that
   * they should abut one another actually do so.
   */
  public void testLayoutStructure() {
    testHorizontalSplit(CM);
    testHorizontalSplit(EM);
    testHorizontalSplit(EX);
    testHorizontalSplit(IN);
    testHorizontalSplit(MM);
    testHorizontalSplit(PC);
    testHorizontalSplit(PT);
    testHorizontalSplit(PX);

    testVerticalSplit(CM);
    testVerticalSplit(EM);
    testVerticalSplit(EX);
    testVerticalSplit(IN);
    testVerticalSplit(MM);
    testVerticalSplit(PC);
    testVerticalSplit(PT);
    testVerticalSplit(PX);
  }

  /**
   * Tests (left-right, left-width, right-width) x (top-bottom, top-height,
   * bottom-height). Ok, so we don't test the *entire* cross-product, but enough
   * to be comfortable.
   */
  @DoNotRunWith(Platform.HtmlUnitLayout)
  public void testStaticConstraints() {
    // This test assumes enough size. Ignore it if size cannot be guaranteed.
    if (!ResizeHelper.isResizeSupported()) {
      return;
    }

    // left-right, top-bottom
    layer0.setTopBottom(32, PX, 32, PX);
    layer0.setLeftRight(32, PX, 32, PX);
    layout.layout();

    int w = parent.getClientWidth();
    int h = parent.getClientHeight();
    assertEquals(32, wrapper0.getOffsetLeft());
    assertEquals(32, wrapper0.getOffsetTop());
    assertEquals(w - 64, wrapper0.getOffsetWidth());
    assertEquals(h - 64, wrapper0.getOffsetHeight());

    // left-width, top-height
    layer0.setTopHeight(16, PX, 128, PX);
    layer0.setLeftWidth(16, PX, 128, PX);
    layout.layout();

    assertEquals(16, wrapper0.getOffsetLeft());
    assertEquals(16, wrapper0.getOffsetTop());
    assertEquals(128, wrapper0.getOffsetWidth());
    assertEquals(128, wrapper0.getOffsetHeight());

    // right-width, bottom-height
    layer0.setBottomHeight(16, PX, 128, PX);
    layer0.setRightWidth(16, PX, 128, PX);
    layout.layout();

    assertEquals(w - (16 + 128), wrapper0.getOffsetLeft());
    assertEquals(h - (16 + 128), wrapper0.getOffsetTop());
    assertEquals(128, wrapper0.getOffsetWidth());
    assertEquals(128, wrapper0.getOffsetHeight());
  }

  /**
   * Tests all unit types.
   */
  @DoNotRunWith(Platform.HtmlUnitLayout)
  public void testUnits() {
    // This test assumes enough size. Ignore it if size cannot be guaranteed.
    if (!ResizeHelper.isResizeSupported()) {
      return;
    }

    // CM
    layer0.setTopBottom(1, CM, 1, CM);
    layer0.setLeftRight(1, CM, 1, CM);
    layout.layout();
    assertLeftRightTopBottomUnitsMakeSense(wrapper0);

    // MM
    layer0.setTopBottom(1, MM, 1, MM);
    layer0.setLeftRight(1, MM, 1, MM);
    layout.layout();
    assertLeftRightTopBottomUnitsMakeSense(wrapper0);

    // IN
    layer0.setTopBottom(1, IN, 1, IN);
    layer0.setLeftRight(1, IN, 1, IN);
    layout.layout();
    assertLeftRightTopBottomUnitsMakeSense(wrapper0);

    // EM
    layer0.setTopBottom(1, EM, 1, EM);
    layer0.setLeftRight(1, EM, 1, EM);
    layout.layout();
    assertLeftRightTopBottomUnitsMakeSense(wrapper0);

    // EX
    layer0.setTopBottom(1, EX, 1, EX);
    layer0.setLeftRight(1, EX, 1, EX);
    layout.layout();
    assertLeftRightTopBottomUnitsMakeSense(wrapper0);

    // PC
    layer0.setTopBottom(1, PC, 1, PC);
    layer0.setLeftRight(1, PC, 1, PC);
    layout.layout();
    assertLeftRightTopBottomUnitsMakeSense(wrapper0);

    // PT
    layer0.setTopBottom(10, PT, 10, PT);
    layer0.setLeftRight(10, PT, 10, PT);
    layout.layout();
    assertLeftRightTopBottomUnitsMakeSense(wrapper0);

    // PCT
    layer0.setTopBottom(10, PCT, 10, PCT);
    layer0.setLeftRight(10, PCT, 10, PCT);
    layout.layout();
    assertLeftRightTopBottomUnitsMakeSense(wrapper0);
  }

  /**
   * Tests layout in the presence of decorations on the parent and child
   * elements.
   */
  @DoNotRunWith(Platform.HtmlUnitLayout)
  public void testWithDecorations() {
    layer0.setTopBottom(0, PX, 0, PX);
    layer0.setLeftRight(0, PX, 0, PX);
    layout.layout();

    // Give each of the parent and child 1px margin and 1px border.
    parent.getStyle().setMargin(1, PX);
    parent.getStyle().setProperty("border", "1px solid black");

    child0.getStyle().setMargin(1, PX);
    child0.getStyle().setProperty("border", "1px solid black");
    layout.layout();

    int w = Window.getClientWidth();
    int h = Window.getClientHeight();
    int pw = parent.getOffsetWidth();
    int ph = parent.getOffsetHeight();

    // The parent's offsetSize should be 2px smaller than the window's client
    // area, because of the margin (the border is *included* in the offsetSize).
    assertEquals(w - 2, pw);
    assertEquals(h - 2, ph);

    // The child's offsetSize (actually that of its wrapper element), should be
    // 2px smaller than the parent, for precisely the same reason.
    assertEquals(pw - 2, wrapper0.getOffsetWidth());
    assertEquals(ph - 2, wrapper0.getOffsetHeight());
  }

  @Override
  protected void gwtSetUp() throws Exception {
    // ensure enough sizes for this test
    ResizeHelper.resizeTo(800, 600);

    Window.enableScrolling(false);

    Document doc = Document.get();
    parent = doc.createDivElement();
    child0 = doc.createDivElement();
    child1 = doc.createDivElement();
    doc.getBody().appendChild(parent);

    layout = new Layout(parent);
    layout.onAttach();
    layout.fillParent();

    layer0 = layout.attachChild(child0);
    layer1 = layout.attachChild(child1);

    wrapper0 = child0.getParentElement();
    wrapper1 = child1.getParentElement();
  }

  @Override
  protected void gwtTearDown() throws Exception {
    Window.enableScrolling(true);
    Document.get().getBody().removeChild(parent);
    layout.onDetach();
  }

  private void assertLeftRightTopBottomUnitsMakeSense(Element elem) {
    // Assume that the element has been laid out to (l, t, r, b) = (1u, 1u, 1u,
    // 1u). Assert that the element's clientLeft/Top are non-zero, and that the
    // clientLeft/Top/Width/Height are consistent with the parent's size.
    int w = parent.getClientWidth();
    int h = parent.getClientHeight();
    int cl = elem.getOffsetLeft();
    int ct = elem.getOffsetTop();
    int cw = elem.getOffsetWidth();
    int ch = elem.getOffsetHeight();

    // Assert that the left-top unit came out at least non-zero size.
    assertTrue(cl > 0);
    assertTrue(ct > 0);

    // Assert that the right-bottom also came out non-zero. We should be able
    // to assert that it came out the same size as the top-left, but it turns
    // out that this isn't quite reliable because of rounding errors.
    assertTrue(w - (cl + cw) > 0);
    assertTrue(h - (ct + ch) > 0);
  }

  // This method may only be called once per test, as it uses delayTestFinish()
  // internally.
  private void testAnimationTransitions_LTWH_LTRB(final Unit unit0,
      final Unit unit1) {
    testAnimationTransitionsHelper(new LayerInitializer() {
      public void setupLayers(Layer l0, Layer l1) {
        l0.setLeftWidth(0, unit0, 10, unit0);
        l0.setTopHeight(0, unit0, 10, unit0);
        l1.setLeftRight(1, unit1, 1, unit1);
        l1.setTopBottom(1, unit1, 1, unit1);
      }
    }, new LayerInitializer() {
      public void setupLayers(Layer l0, Layer l1) {
        l1.setLeftWidth(0, unit0, 10, unit0);
        l1.setTopHeight(0, unit0, 10, unit0);
        l0.setLeftRight(1, unit1, 1, unit1);
        l0.setTopBottom(1, unit1, 1, unit1);
      }
    });
  }

  // This method may only be called once per test, as it uses delayTestFinish()
  // internally.
  private void testAnimationTransitions_LTWH_RBWH(final Unit unit0,
      final Unit unit1) {
    testAnimationTransitionsHelper(new LayerInitializer() {
      public void setupLayers(Layer l0, Layer l1) {
        l0.setLeftWidth(0, unit0, 10, unit0);
        l0.setTopHeight(0, unit0, 10, unit0);
        l1.setRightWidth(0, unit1, 10, unit1);
        l1.setBottomHeight(0, unit1, 10, unit1);
      }
    }, new LayerInitializer() {
      public void setupLayers(Layer l0, Layer l1) {
        l1.setLeftWidth(0, unit0, 10, unit0);
        l1.setTopHeight(0, unit0, 10, unit0);
        l0.setRightWidth(0, unit1, 10, unit1);
        l0.setBottomHeight(0, unit1, 10, unit1);
      }
    });
  }

  // This method may only be called once per test, as it uses delayTestFinish()
  // internally.
  private void testAnimationTransitions_RBWH_LTRB(final Unit unit0,
      final Unit unit1) {
    testAnimationTransitionsHelper(new LayerInitializer() {
      public void setupLayers(Layer l0, Layer l1) {
        l0.setRightWidth(0, unit0, 10, unit0);
        l0.setBottomHeight(0, unit0, 10, unit0);
        l1.setLeftRight(1, unit1, 1, unit1);
        l1.setTopBottom(1, unit1, 1, unit1);
      }
    }, new LayerInitializer() {
      public void setupLayers(Layer l0, Layer l1) {
        l1.setRightWidth(0, unit0, 10, unit0);
        l1.setBottomHeight(0, unit0, 10, unit0);
        l0.setLeftRight(1, unit1, 1, unit1);
        l0.setTopBottom(1, unit1, 1, unit1);
      }
    });
  }

  // This method may only be called once per test, as it uses delayTestFinish()
  // internally.
  private void testAnimationTransitionsHelper(LayerInitializer before,
      LayerInitializer after) {
    before.setupLayers(layer0, layer1);
    layout.layout();

    final int l0 = wrapper0.getOffsetLeft();
    final int t0 = wrapper0.getOffsetTop();
    final int w0 = wrapper0.getOffsetWidth();
    final int h0 = wrapper0.getOffsetHeight();

    final int l1 = wrapper1.getOffsetLeft();
    final int t1 = wrapper1.getOffsetTop();
    final int w1 = wrapper1.getOffsetWidth();
    final int h1 = wrapper1.getOffsetHeight();

    after.setupLayers(layer0, layer1);
    delayTestFinish(TEST_DELAY);
    layout.layout(100, new Layout.AnimationCallback() {
      public void onAnimationComplete() {
        // Assert that the two layers have swapped positions.
        assertEquals(l0, wrapper1.getOffsetLeft());
        assertEquals(t0, wrapper1.getOffsetTop());
        assertEquals(w0, wrapper1.getOffsetWidth());
        assertEquals(h0, wrapper1.getOffsetHeight());

        assertEquals(l1, wrapper0.getOffsetLeft());
        assertEquals(t1, wrapper0.getOffsetTop());
        assertEquals(w1, wrapper0.getOffsetWidth());
        assertEquals(h1, wrapper0.getOffsetHeight());

        finishTest();
      }

      public void onLayout(Layer layer, double progress) {
      }
    });
  }

  private void testHorizontalSplit(Unit unit) {
    // Line them up horizontally, split at 5 units.
    layer0.setTopBottom(0, PX, 0, PX);
    layer0.setLeftWidth(0, PX, 5, unit);

    layer1.setTopBottom(0, PX, 0, PX);
    layer1.setLeftRight(5, unit, 0, PX);
    layout.layout();

    int child0Right = wrapper0.getOffsetWidth();
    int child1Left = wrapper1.getOffsetLeft();
    assertEquals(child0Right, child1Left);
  }

  private void testVerticalSplit(Unit unit) {
    // Line them up vertically, split at 5em.
    layer0.setTopHeight(0, PX, 5, unit);
    layer0.setLeftRight(0, PX, 0, PX);

    layer1.setTopBottom(5, unit, 0, PX);
    layer1.setLeftRight(0, PX, 0, PX);
    layout.layout();

    int child0Bottom = wrapper0.getOffsetHeight();
    int child1Top = wrapper1.getOffsetTop();
    assertEquals(child0Bottom, child1Top);
  }
}
