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

import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.logical.shared.BeforeSelectionEvent;
import com.google.gwt.event.logical.shared.BeforeSelectionHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.junit.DoNotRunWith;
import com.google.gwt.junit.Platform;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Tests for {@link TabLayoutPanel}.
 */
public class TabLayoutPanelTest extends GWTTestCase {

  static class Adder implements HasWidgetsTester.WidgetAdder {
    public void addChild(HasWidgets container, Widget child) {
      ((TabLayoutPanel) container).add(child, "foo");
    }
  }

  private class TestSelectionHandler implements
      BeforeSelectionHandler<Integer>, SelectionHandler<Integer> {
    private boolean onBeforeSelectionFired;
    private boolean onSelectionFired;

    public void assertOnBeforeSelectionFired(boolean expected) {
      assertEquals(expected, onBeforeSelectionFired);
    }

    public void assertOnSelectionFired(boolean expected) {
      assertEquals(expected, onSelectionFired);
    }

    public void onBeforeSelection(BeforeSelectionEvent<Integer> event) {
      assertFalse(onSelectionFired);
      onBeforeSelectionFired = true;
    }

    public void onSelection(SelectionEvent<Integer> event) {
      assertTrue(onBeforeSelectionFired);
      onSelectionFired = true;
    }
  }

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

  public void testAttachDetachOrder() {
    HasWidgetsTester.testAll(new TabLayoutPanel(1, Unit.EM), new Adder(), true);
  }

  /**
   * Ensures that hidden children are layed out properly when their tabs are
   * selected. This has been a problem on IE6 (see issue 4596).
   */
  @DoNotRunWith({Platform.HtmlUnitBug})
  public void testHiddenChildLayout() {
    final TabLayoutPanel p = new TabLayoutPanel(32, Unit.PX);
    p.setSize("128px", "128px");
    RootPanel.get().add(p);

    final Label foo = new Label("foo");
    final Label bar = new Label("bar");
    p.add(foo, new Label("foo"));
    p.add(bar, new Label("bar"));

    delayTestFinish(2000);
    DeferredCommand.addCommand(new Command() {
      public void execute() {
        assertEquals(128, foo.getOffsetWidth());
        assertEquals(128 - 32, foo.getOffsetHeight());

        p.selectTab(1);
        DeferredCommand.addCommand(new Command() {
          public void execute() {
            assertEquals(128, bar.getOffsetWidth());
            assertEquals(128 - 32, bar.getOffsetHeight());
            finishTest();
          }
        });
      }
    });
  }

  /**
   * Ensures that hidden children are layed out properly when their tabs are
   * selected, when they're sized in EM units. This has been a problem on IE8
   * (see issue 4694).
   */
  @DoNotRunWith({Platform.HtmlUnitBug})
  public void testHiddenChildLayoutEM() {
    final TabLayoutPanel p = new TabLayoutPanel(2, Unit.EM);
    p.setSize("128px", "128px");
    RootPanel.get().add(p);

    final Label foo = new Label("foo");
    p.add(foo, new Label("foo"));

    // Add the 'bar' label in a nested LayoutPanel. This is meant to test that
    // layout propagates correctly into nested layout panels (something that
    // should happen naturally, but we have a specific hack for on IE8).
    final DockLayoutPanel inner = new DockLayoutPanel(Unit.EM);
    final Label bar = new Label("bar");
    inner.addSouth(bar, 2);
    inner.add(new Label("center"));
    p.add(inner, new Label("bar"));

    delayTestFinish(2000);
    DeferredCommand.addCommand(new Command() {
      public void execute() {
        p.selectTab(1);
        DeferredCommand.addCommand(new Command() {
          public void execute() {
            // Assert that the 'bar' label is of non-zero size on both axes.
            // The problem fixed in issue 4694 was causing its height to be
            // zero on IE8, because the EM units weren't being calculated
            // properly when it was initially hidden.
            assertTrue(bar.getOffsetWidth() > 0);
            assertTrue(bar.getOffsetHeight() > 0);

            finishTest();
          }
        });
      }
    });
  }

  public void testInsertBeforeSelected() {
    TabLayoutPanel p = new TabLayoutPanel(2, Unit.EM);
    p.add(new Label("foo"), "foo");
    p.selectTab(0);
    p.insert(new Label("bar"), "bar", 0);
    assertEquals(1, p.getSelectedIndex());
  }

  public void testInsertMultipleTimes() {
    TabLayoutPanel p = new TabLayoutPanel(2, Unit.EM);

    TextBox tb = new TextBox();
    p.add(tb, "Title");
    p.add(tb, "Title");
    p.add(tb, "Title3");

    assertEquals(1, p.getWidgetCount());
    assertEquals(0, p.getWidgetIndex(tb));
    Iterator<Widget> i = p.iterator();
    assertTrue(i.hasNext());
    assertTrue(tb.equals(i.next()));
    assertFalse(i.hasNext());

    Label l = new Label();
    p.add(l, "Title");
    p.add(l, "Title");
    p.add(l, "Title3");
    assertEquals(2, p.getWidgetCount());
    assertEquals(0, p.getWidgetIndex(tb));
    assertEquals(1, p.getWidgetIndex(l));

    p.insert(l, "Title", 0);
    assertEquals(2, p.getWidgetCount());
    assertEquals(0, p.getWidgetIndex(l));
    assertEquals(1, p.getWidgetIndex(tb));

    p.insert(l, "Title", 1);
    assertEquals(2, p.getWidgetCount());
    assertEquals(0, p.getWidgetIndex(l));
    assertEquals(1, p.getWidgetIndex(tb));

    p.insert(l, "Title", 2);
    assertEquals(2, p.getWidgetCount());
    assertEquals(0, p.getWidgetIndex(tb));
    assertEquals(1, p.getWidgetIndex(l));
  }

  public void testInsertWithHTML() {
    TabLayoutPanel p = new TabLayoutPanel(2, Unit.EM);
    Label l = new Label();
    p.add(l, "three");
    p.insert(new HTML("<b>hello</b>"), "two", true, 0);
    p.insert(new HTML("goodbye"), "one", false, 0);
    assertEquals(3, p.getWidgetCount());
  }

  /**
   * Tests to ensure that arbitrary widgets can be added/inserted effectively.
   */
  public void testInsertWithWidgets() {
    TabLayoutPanel p = new TabLayoutPanel(2, Unit.EM);

    TextBox wa = new TextBox();
    CheckBox wb = new CheckBox();
    VerticalPanel wc = new VerticalPanel();
    wc.add(new Label("First"));
    wc.add(new Label("Second"));

    p.add(new Label("Content C"), wc);
    p.insert(new Label("Content B"), wb, 0);
    p.insert(new Label("Content A"), wa, 0);

    // Call these to ensure we don't throw an exception.
    assertNotNull(p.getTabWidget(0));
    assertNotNull(p.getTabWidget(1));
    assertNotNull(p.getTabWidget(2));
    assertEquals(3, p.getWidgetCount());
  }

  public void testIsWidget() {
    TabLayoutPanel p = new TabLayoutPanel(2, Unit.EM);

    IsWidgetImpl add = new IsWidgetImpl(new Label("add"));
    IsWidgetImpl addText = new IsWidgetImpl(new Label("addText"));
    IsWidgetImpl addHtml = new IsWidgetImpl(new Label("addHtml"));
    IsWidgetImpl addWidget = new IsWidgetImpl(new Label("addWidget"));
    IsWidgetImpl added = new IsWidgetImpl(new Label("added widget"));

    IsWidgetImpl insert = new IsWidgetImpl(new Label("insText"));
    IsWidgetImpl insText = new IsWidgetImpl(new Label("insText"));
    IsWidgetImpl insHtml = new IsWidgetImpl(new Label("insHtml"));
    IsWidgetImpl insWidget = new IsWidgetImpl(new Label("insWidget"));
    IsWidgetImpl inserted = new IsWidgetImpl(new Label("inserted widget"));

    p.add(add);
    p.add(addText, "added text");
    p.add(addHtml, "<b>added html</b>", true);
    p.add(addWidget, added);

    p.insert(insert, 0);
    p.insert(insText, "inserted text", 2);
    p.insert(insHtml, "<b>inserted html</b>", true, 4);
    p.insert(insWidget, inserted, 6);

    assertEquals(8, p.getWidgetCount());
    assertEquals(0, p.getWidgetIndex(insert));
    assertEquals(1, p.getWidgetIndex(add));
    assertEquals(2, p.getWidgetIndex(insText));
    assertEquals(3, p.getWidgetIndex(addText));
    assertEquals(4, p.getWidgetIndex(insHtml));
    assertEquals(5, p.getWidgetIndex(addHtml));
    assertEquals(6, p.getWidgetIndex(insWidget));
    assertEquals(7, p.getWidgetIndex(addWidget));

    assertEquals("", p.getTabWidget(insert).getElement().getInnerHTML());
    assertEquals("", p.getTabWidget(add).getElement().getInnerHTML());
    assertEquals("inserted text", p.getTabWidget(insText).getElement().getInnerHTML());
    assertEquals("added text", p.getTabWidget(addText).getElement().getInnerHTML());
    assertEquals("<b>inserted html</b>", p.getTabWidget(insHtml).getElement().getInnerHTML().toLowerCase());
    assertEquals("<b>added html</b>", p.getTabWidget(addHtml).getElement().getInnerHTML().toLowerCase());
    assertEquals(inserted.w, p.getTabWidget(insWidget));
    assertEquals(added.w, p.getTabWidget(addWidget));

    class Handler implements SelectionHandler<Integer> {
      boolean fired = false;
      public void onSelection(SelectionEvent<Integer> event) {
        fired = true;
      }
    }

    Handler handler = new Handler();
    p.addSelectionHandler(handler);

    p.selectTab(addText, true);
    assertTrue(handler.fired);
    assertEquals(3, p.getSelectedIndex());

    handler.fired = false;
    p.selectTab(insWidget);
    assertTrue(handler.fired);
    assertEquals(6, p.getSelectedIndex());
  }

  public void testIterator() {
    TabLayoutPanel p = new TabLayoutPanel(2, Unit.EM);
    HTML foo = new HTML("foo");
    HTML bar = new HTML("bar");
    HTML baz = new HTML("baz");
    p.add(foo, "foo");
    p.add(bar, "bar");
    p.add(baz, "baz");

    // Iterate over the entire set and make sure it stops correctly.
    Iterator<Widget> it = p.iterator();
    assertTrue(it.hasNext());
    assertTrue(it.next() == foo);
    assertTrue(it.hasNext());
    assertTrue(it.next() == bar);
    assertTrue(it.hasNext());
    assertTrue(it.next() == baz);
    assertFalse(it.hasNext());

    // Test removing using the iterator.
    it = p.iterator();
    it.next();
    it.remove();
    assertTrue(it.next() == bar);
    assertTrue(p.getWidgetCount() == 2);
    assertTrue(p.getWidget(0) == bar);
    assertTrue(p.getWidget(1) == baz);
  }

  public void testSelectionEvents() {
    TabLayoutPanel p = new TabLayoutPanel(2, Unit.EM);
    RootPanel.get().add(p);

    p.add(new Button("foo"), "foo");
    p.add(new Button("bar"), "bar");

    // Make sure selecting a tab fires both events in the right order.
    TestSelectionHandler handler = new TestSelectionHandler();
    p.addBeforeSelectionHandler(handler);
    p.addSelectionHandler(handler);
    p.selectTab(1);
    handler.assertOnBeforeSelectionFired(true);
    handler.assertOnSelectionFired(true);
  }

  public void testSelectionEventsNoFire() {
    TabLayoutPanel p = new TabLayoutPanel(2, Unit.EM);
    RootPanel.get().add(p);

    p.add(new Button("foo"), "foo");
    p.add(new Button("bar"), "bar");

    TestSelectionHandler handler = new TestSelectionHandler();
    p.addBeforeSelectionHandler(handler);
    p.addSelectionHandler(handler);
    p.selectTab(1, false);
    handler.assertOnBeforeSelectionFired(false);
    handler.assertOnSelectionFired(false);
  }

  /**
   * Test that {@link TabLayoutPanel} calls widget.setVisible(true/false) on
   * each widget, when it is shown/hidden.
   */
  public void testSetWidgetVisible() {
    TabLayoutPanel p = new TabLayoutPanel(1, Unit.EM);
    Label[] labels = new Label[3];
    for (int i = 0; i < labels.length; i++) {
      labels[i] = new Label("content" + i);
      p.add(labels[i]);
    }

    // Initially, the first widget should be visible.
    assertTrue(labels[0].isVisible());
    assertFalse(labels[1].isVisible());
    assertFalse(labels[2].isVisible());

    // Show widget at index 1, make sure it becomes visible, and the one at
    // index 0 is hidden.
    p.selectTab(1);
    assertFalse(labels[0].isVisible());
    assertTrue(labels[1].isVisible());
    assertFalse(labels[2].isVisible());

    // Show widget at index 0, make sure it changed back to the initial state.
    p.selectTab(0);
    assertTrue(labels[0].isVisible());
    assertFalse(labels[1].isVisible());
    assertFalse(labels[2].isVisible());
  }

  /**
   * For legacy reasons, {@link TabLayoutPanel#selectTab(Widget)} should call
   * {@link TabLayoutPanel#selectTab(int)}.
   */
  public void testSelectTabLegacy() {
    final List<Integer> called = new ArrayList<Integer>();
    TabLayoutPanel panel = new TabLayoutPanel(100.0, Unit.PX) {
      @Override
      public void selectTab(int index) {
        called.add(index);
        super.selectTab(index);
      }
    };
    Label tab1 = new Label("Tab 1");
    panel.add(new Label("Tab 0"), "Tab 0");
    panel.add(tab1, "Tab 1");
    panel.add(new Label("Tab 2"), "Tab 2");
    called.clear();

    panel.selectTab(tab1);
    assertEquals(1, called.size());
    assertEquals(1, called.get(0).intValue());
  }

  /**
   * Tests that tabs actually line up properly (see issue 4447).
   */
  @DoNotRunWith(Platform.HtmlUnitLayout)
  public void testTabLayout() {
    TabLayoutPanel p = new TabLayoutPanel(2, Unit.EM);
    RootPanel.get().add(p);

    p.add(new Button("foo"), new Label("foo"));
    p.add(new Button("bar"), new Label("bar"));

    assertEquals(p.getTabWidget(0).getElement().getOffsetTop(), p.getTabWidget(
        1).getElement().getOffsetTop());
  }
}
