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

import java.util.HashMap;
import java.util.Map;

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

  /**
   * Make sure to call onLayout on the AnimationCallback, when there is
   * no animation (duration =0). This will make sure that onResize will be
   * called on the child panels.
   */
  public void testOnLayoutWhenNoAnimation() {
    final Map<Layer,Double> called = new HashMap();
    layout.layout(0, new Layout.AnimationCallback() {
      @Override
      public void onAnimationComplete() {
      }

      @Override
      public void onLayout(Layer layer, double progress) {
        called.put(layer,progress);
      }
    });
    assertEquals(2,called.size());
    assertEquals(1.0,called.get(layer0));
    assertEquals(1.0,called.get(layer1));
  }

  /**
   * 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.
   */
  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.
   */
  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() {
      @Override
      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() {
      @Override
      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() {
      @Override
      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() {
      @Override
      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() {
      @Override
      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() {
      @Override
      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() {
      @Override
      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();
      }

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