/*
 * Copyright 2008 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.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.junit.DoNotRunWith;
import com.google.gwt.junit.Platform;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.client.Command;

import java.util.List;
import java.util.Locale;

/**
 * Tests the DockPanel widget.
 */
public class MenuBarTest extends WidgetTestBase {

  private static final String html = "<b>hello</b><i>world</i>";

  /**
   * A blank command.
   */
  private static final Command BLANK_COMMAND = new Command() {
    @Override
    public void execute() {
    }
  };

  /**
   * A blank scheduled command.
   */
  private static final ScheduledCommand BLANK_SCHEDULED_COMMAND = new ScheduledCommand() {
    @Override
    public void execute() {
    }
  };

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

  /**
   * Test adding and removing {@link MenuItem}s and {@link MenuItemSeparator}s
   * from a menu.
   */
  public void testAddRemoveItemsWithCommand() {
    // Create a menu bar
    MenuBar bar = new MenuBar(true);

    // Add an item, default to text
    MenuItem item0 = bar.addItem("<b>test</b>", BLANK_COMMAND);
    assertEquals("<b>test</b>", item0.getText());
    assertEquals(BLANK_COMMAND, item0.getCommand());
    assertEquals(bar, item0.getParentMenu());

    // Add a separator
    MenuItemSeparator separator0 = bar.addSeparator();
    assertEquals(bar, separator0.getParentMenu());

    // Add another item, force to html
    MenuItem item1 = bar.addItem("<b>test1</b>", true, BLANK_COMMAND);
    assertEquals("test1", item1.getText());
    assertEquals(BLANK_COMMAND, item1.getCommand());
    assertEquals(bar, item1.getParentMenu());

    // Get all items
    List<MenuItem> items = bar.getItems();
    assertEquals(item0, items.get(0));
    assertEquals(item1, items.get(1));

    // Remove an item
    bar.removeItem(item0);
    assertEquals(item1, items.get(0));
    assertNull(item0.getParentMenu());

    // Remove the separator
    bar.removeSeparator(separator0);
    assertEquals(item1, items.get(0));
    assertNull(separator0.getParentMenu());

    // Add a bunch of items and clear them all
    MenuItem item2 = bar.addItem("test2", true, BLANK_COMMAND);
    MenuItemSeparator separator1 = bar.addSeparator();
    MenuItem item3 = bar.addItem("test3", true, BLANK_COMMAND);
    MenuItemSeparator separator2 = bar.addSeparator();
    MenuItem item4 = bar.addItem("test4", true, BLANK_COMMAND);
    MenuItemSeparator separator3 = bar.addSeparator();
    bar.clearItems();
    assertEquals(0, bar.getItems().size());
    assertNull(item2.getParentMenu());
    assertNull(item3.getParentMenu());
    assertNull(item4.getParentMenu());
    assertNull(separator1.getParentMenu());
    assertNull(separator2.getParentMenu());
    assertNull(separator3.getParentMenu());
  }

  /**
   * Test adding and removing {@link MenuItem}s and {@link MenuItemSeparator}s
   * from a menu.
   */
  public void testAddRemoveItemsWithScheduledCommand() {
    // Create a menu bar
    MenuBar bar = new MenuBar(true);

    // Add an item, default to text
    MenuItem item0 = bar.addItem("<b>test</b>", BLANK_SCHEDULED_COMMAND);
    assertEquals("<b>test</b>", item0.getText());
    assertEquals(BLANK_SCHEDULED_COMMAND, item0.getScheduledCommand());
    assertEquals(bar, item0.getParentMenu());

    // Add a separator
    MenuItemSeparator separator0 = bar.addSeparator();
    assertEquals(bar, separator0.getParentMenu());

    // Add another item, force to html
    MenuItem item1 = bar.addItem("<b>test1</b>", true, BLANK_SCHEDULED_COMMAND);
    assertEquals("test1", item1.getText());
    assertEquals(BLANK_SCHEDULED_COMMAND, item1.getScheduledCommand());
    assertEquals(bar, item1.getParentMenu());

    // Get all items
    List<MenuItem> items = bar.getItems();
    assertEquals(item0, items.get(0));
    assertEquals(item1, items.get(1));

    // Remove an item
    bar.removeItem(item0);
    assertEquals(item1, items.get(0));
    assertNull(item0.getParentMenu());

    // Remove the separator
    bar.removeSeparator(separator0);
    assertEquals(item1, items.get(0));
    assertNull(separator0.getParentMenu());

    // Add a bunch of items and clear them all
    MenuItem item2 = bar.addItem("test2", true, BLANK_SCHEDULED_COMMAND);
    MenuItemSeparator separator1 = bar.addSeparator();
    MenuItem item3 = bar.addItem("test3", true, BLANK_SCHEDULED_COMMAND);
    MenuItemSeparator separator2 = bar.addSeparator();
    MenuItem item4 = bar.addItem("test4", true, BLANK_SCHEDULED_COMMAND);
    MenuItemSeparator separator3 = bar.addSeparator();
    bar.clearItems();
    assertEquals(0, bar.getItems().size());
    assertNull(item2.getParentMenu());
    assertNull(item3.getParentMenu());
    assertNull(item4.getParentMenu());
    assertNull(separator1.getParentMenu());
    assertNull(separator2.getParentMenu());
    assertNull(separator3.getParentMenu());
  }

  public void testAutoHideChildMenuPopup() {
    // Create a menu bar with children.
    MenuBar l0 = new MenuBar();
    l0.setAutoOpen(true);
    MenuBar l1 = new MenuBar();
    l1.setAutoOpen(true);
    MenuBar l2 = new MenuBar();
    l2.setAutoOpen(true);
    MenuItem item2 = l2.addItem("l2", BLANK_COMMAND);
    MenuItem item1 = l1.addItem("l1", l2);
    MenuItem item0 = l0.addItem("l0", l1);
    RootPanel.get().add(l0);

    // Open l2.
    l0.itemOver(item0, true);
    l1.itemOver(item1, true);
    l2.itemOver(item2, true);
    assertTrue(l0.getPopup().isShowing());
    assertEquals(item0, l0.getSelectedItem());
    assertTrue(l1.getPopup().isShowing());
    assertEquals(item1, l1.getSelectedItem());

    // Auto-hide the child popup.
    l1.getPopup().hide(true);
    assertNull(l0.getPopup());
    assertNull(l0.getSelectedItem());
    assertNull(l1.getPopup());

    // Open l2.
    l0.itemOver(item0, true);
    l1.itemOver(item1, true);
    l2.itemOver(item2, true);
    assertTrue(l0.getPopup().isShowing());
    assertEquals(item0, l0.getSelectedItem());
    assertTrue(l1.getPopup().isShowing());
    assertEquals(item1, l1.getSelectedItem());

    // Close child menus below l1.
    l1.closeAllChildren(true);
    assertTrue(l0.getPopup().isShowing());
    assertEquals(item0, l0.getSelectedItem());
    assertNull(l1.getPopup());
    assertNull(l2.getPopup());
  }

  @DoNotRunWith({Platform.HtmlUnitBug})
  public void testBlur() {
    // Create a menu bar with children.
    final MenuBar menu = new MenuBar();
    MenuItem item0 = menu.addItem("item0", BLANK_COMMAND);
    RootPanel.get().add(menu);

    // Select the item.
    menu.focus();
    menu.selectItem(item0);
    assertEquals(item0, menu.getSelectedItem());

    // Blur the menu bar.
    NativeEvent event = Document.get().createBlurEvent();
    menu.getElement().dispatchEvent(event);
    assertNull(menu.getSelectedItem());
  }

  @DoNotRunWith({Platform.HtmlUnitBug})
  public void testSetFocusOnHoverEnabled() {
    delayTestFinish(1000);
    TextBox focusOwner = new TextBox();
    RootPanel.get().add(focusOwner);
    focusOwner.setFocus(true);
    assertFocused(focusOwner.getElement());

    final MenuBar menu = new MenuBar();
    MenuItem item0 = menu.addItem("item0", BLANK_COMMAND);
    RootPanel.get().add(menu);

    assertFocused(focusOwner.getElement());
    menu.itemOver(item0, true);
    Scheduler.get().scheduleDeferred(new Command() {
      @Override
      public void execute() {
        assertFocused(menu.getElement());
        finishTest();
      }
    });
  }

  public void testSetFocusOnHoverDisabled() {
    TextBox focusOwner = new TextBox();
    RootPanel.get().add(focusOwner);
    focusOwner.setFocus(true);
    assertFocused(focusOwner.getElement());

    // Create a menu bar with children.
    MenuBar menu = new MenuBar();
    menu.setAutoOpen(true);
    menu.setFocusOnHoverEnabled(false);
    MenuItem item0 = menu.addItem("item0", BLANK_COMMAND);
    MenuBar subMenu = new MenuBar();
    subMenu.setFocusOnHoverEnabled(false);
    MenuItem item1 = menu.addItem("item1", subMenu);
    RootPanel.get().add(menu);

    menu.itemOver(item0, true);
    assertFocused(focusOwner.getElement());

    menu.itemOver(item1, true);
    assertFocused(focusOwner.getElement());

    // Cause item1 to hide
    menu.itemOver(item0, true);
    assertFocused(focusOwner.getElement());
  }

  private static void assertFocused(Element element) {
    assertTrue(isFocused(element));
  }

  private static native boolean isFocused(Element element) /*-{
    return $doc.activeElement == element;
  }-*/;

  public void testPopupAnimationEnabled() {
    // Create a menu bar with children.
    MenuBar l0 = new MenuBar();
    l0.setAutoOpen(true);
    MenuBar l1 = new MenuBar();
    l1.setAutoOpen(true);
    l1.setAnimationEnabled(true);
    MenuBar l2 = new MenuBar();
    l2.setAutoOpen(true);
    MenuItem item2 = l2.addItem("l2", BLANK_COMMAND);
    MenuItem item1 = l1.addItem("l1", l2);
    MenuItem item0 = l0.addItem("l0", l1);
    RootPanel.get().add(l0);

    l0.itemOver(item0, true);
    assertFalse(l0.getPopup().isAnimationEnabled());

    l1.itemOver(item1, true);
    assertTrue(l1.getPopup().isAnimationEnabled());
  }

  public void testDebugId() {
    // Create a sub menu
    MenuBar subMenu = new MenuBar(true);
    subMenu.addItem("sub0", BLANK_COMMAND);
    subMenu.addItem("sub1", BLANK_COMMAND);
    subMenu.addItem("sub2", BLANK_COMMAND);

    // Create a menu bar
    MenuBar bar = new MenuBar(false);
    bar.setAnimationEnabled(false);
    bar.setAutoOpen(true);
    bar.addItem("top0", BLANK_COMMAND);
    bar.addItem("top1", BLANK_COMMAND);
    MenuItem top2 = bar.addItem("top2", subMenu);
    RootPanel.get().add(bar);

    // Open the item with a submenu
    bar.itemOver(top2, true);

    // Set the Debug Id
    bar.ensureDebugId("myMenu");
    UIObjectTest.assertDebugId("myMenu", bar.getElement());

    delayTestFinish(5000);
    Scheduler.get().scheduleDeferred(new ScheduledCommand() {
      @Override
      public void execute() {
        UIObjectTest.assertDebugIdContents("myMenu-item0", "top0");
        UIObjectTest.assertDebugIdContents("myMenu-item1", "top1");
        UIObjectTest.assertDebugIdContents("myMenu-item2", "top2");

        UIObjectTest.assertDebugIdContents("myMenu-item2-item0", "sub0");
        UIObjectTest.assertDebugIdContents("myMenu-item2-item1", "sub1");
        UIObjectTest.assertDebugIdContents("myMenu-item2-item2", "sub2");
        finishTest();
      }
    });
  }

  public void testDisabledItem() {
    MenuBar bar = new MenuBar(true);
    MenuItem item1 = new MenuItem("item1", BLANK_COMMAND);
    MenuItem item2 = new MenuItem("item2", BLANK_COMMAND);
    MenuItem item3 = new MenuItem("item3", BLANK_COMMAND);
    bar.addItem(item1);
    bar.addItem(item2);
    bar.addItem(item3);
    RootPanel.get().add(bar);

    item2.setEnabled(false);

    bar.moveSelectionDown();
    assertEquals(item1, bar.getSelectedItem());
    bar.moveSelectionDown();
    assertEquals(item3, bar.getSelectedItem());
    bar.moveSelectionUp();
    assertEquals(item1, bar.getSelectedItem());
  }

  public void testEscapeKey() {
    // Create a menu bar with children.
    MenuBar l0 = new MenuBar();
    l0.setAutoOpen(true);
    MenuBar l1 = new MenuBar();
    l1.setAutoOpen(true);
    MenuBar l2 = new MenuBar();
    l2.setAutoOpen(true);
    MenuItem item2 = l2.addItem("l2", BLANK_COMMAND);
    MenuItem item1 = l1.addItem("l1", l2);
    MenuItem item0 = l0.addItem("l0", l1);
    RootPanel.get().add(l0);

    // Open l2.
    l0.itemOver(item0, true);
    l1.itemOver(item1, true);
    l2.itemOver(item2, true);
    assertTrue(l0.getPopup().isShowing());
    assertEquals(item0, l0.getSelectedItem());
    assertTrue(l1.getPopup().isShowing());
    assertEquals(item1, l1.getSelectedItem());

    // Escape from the menu.
    NativeEvent event = Document.get().createKeyDownEvent(
        false, false, false, false, KeyCodes.KEY_ESCAPE);
    l1.getElement().dispatchEvent(event);
    assertNull(l0.getPopup());
    assertNull(l0.getSelectedItem());
    assertNull(l1.getPopup());
  }

  /**
   * Test inserting {@link MenuItem}s and {@link MenuItemSeparator}s into the
   * menu.
   */
  public void testInsertItems() {
    // Create a menu bar
    MenuBar bar = new MenuBar(true);

    // Insert first item
    MenuItem item0 = bar.insertItem(new MenuItem("test", BLANK_COMMAND), 0);
    assertEquals(0, bar.getItemIndex(item0));

    // Insert item at 0
    MenuItem item1 = bar.insertItem(new MenuItem("test", BLANK_COMMAND), 0);
    assertEquals(0, bar.getItemIndex(item1));
    assertEquals(1, bar.getItemIndex(item0));

    // Insert item at end
    MenuItem item2 = bar.insertItem(new MenuItem("test", BLANK_COMMAND), 2);
    assertEquals(0, bar.getItemIndex(item1));
    assertEquals(1, bar.getItemIndex(item0));
    assertEquals(2, bar.getItemIndex(item2));

    // Insert a separator at 0
    MenuItemSeparator separator0 = bar.insertSeparator(0);
    assertEquals(0, bar.getSeparatorIndex(separator0));
    assertEquals(1, bar.getItemIndex(item1));
    assertEquals(2, bar.getItemIndex(item0));
    assertEquals(3, bar.getItemIndex(item2));

    // Insert a separator at end
    MenuItemSeparator separator1 = bar.insertSeparator(4);
    assertEquals(0, bar.getSeparatorIndex(separator0));
    assertEquals(1, bar.getItemIndex(item1));
    assertEquals(2, bar.getItemIndex(item0));
    assertEquals(3, bar.getItemIndex(item2));
    assertEquals(4, bar.getSeparatorIndex(separator1));

    // Insert a separator at middle
    MenuItemSeparator separator2 = bar.insertSeparator(2);
    assertEquals(0, bar.getSeparatorIndex(separator0));
    assertEquals(1, bar.getItemIndex(item1));
    assertEquals(2, bar.getSeparatorIndex(separator2));
    assertEquals(3, bar.getItemIndex(item0));
    assertEquals(4, bar.getItemIndex(item2));
    assertEquals(5, bar.getSeparatorIndex(separator1));
  }

  /**
   * Test inserting {@link MenuItem}s and {@link MenuItemSeparator}s into the
   * menu at indexes that are out of bounds.
   */
  public void testInsertItemsOutOfBounds() {
    // Create a menu bar
    MenuBar bar = new MenuBar(true);

    // Add some items to the menu
    for (int i = 0; i < 3; i++) {
      bar.addItem("item", BLANK_COMMAND);
    }

    // Add an item at a negative index
    try {
      bar.insertItem(new MenuItem("test", BLANK_COMMAND), -1);
      fail("Expected IndexOutOfBoundsException");
    } catch (IndexOutOfBoundsException e) {
      // Expected exception
    }

    // Add an item at a high index
    try {
      bar.insertItem(new MenuItem("test", BLANK_COMMAND), 4);
      fail("Expected IndexOutOfBoundsException");
    } catch (IndexOutOfBoundsException e) {
      // Expected exception
    }
  }

  public void testSafeHtmlWithCommand() {
    MenuBar bar = new MenuBar(true);

    // ensure safehtml passes through when a command is set.
    MenuItem item1 =
      bar.addItem(SafeHtmlUtils.fromSafeConstant(html), BLANK_COMMAND);
    assertEquals(html, item1.getHTML().toLowerCase(Locale.ROOT));
    assertEquals(BLANK_COMMAND, item1.getCommand());
    assertEquals(bar, item1.getParentMenu());

    // ensure safehtml passes through when a submenu/popup is set.
    MenuBar foo = new MenuBar(true);
    MenuItem item2 = foo.addItem(SafeHtmlUtils.fromSafeConstant(html), bar);
    assertEquals(html, item2.getHTML().toLowerCase(Locale.ROOT));
    assertEquals(bar, item2.getSubMenu());
    assertEquals(foo, item2.getParentMenu());
  }

  public void testSafeHtmlWithScheduledCommand() {
    MenuBar bar = new MenuBar(true);

    // ensure safehtml passes through when a command is set.
    MenuItem item1 =
      bar.addItem(SafeHtmlUtils.fromSafeConstant(html), BLANK_SCHEDULED_COMMAND);
    assertEquals(html, item1.getHTML().toLowerCase(Locale.ROOT));
    assertEquals(BLANK_SCHEDULED_COMMAND, item1.getScheduledCommand());
    assertEquals(bar, item1.getParentMenu());

    // ensure safehtml passes through when a submenu/popup is set.
    MenuBar foo = new MenuBar(true);
    MenuItem item2 = foo.addItem(SafeHtmlUtils.fromSafeConstant(html), bar);
    assertEquals(html, item2.getHTML().toLowerCase(Locale.ROOT));
    assertEquals(bar, item2.getSubMenu());
    assertEquals(foo, item2.getParentMenu());
  }

  /**
   * Test that the selected item points to the correct item.
   */
  public void testSelectedItem() {
    // Create a menu bar
    MenuBar bar = new MenuBar(true);

    // Add some items
    MenuItem item1 = bar.addItem("item1", BLANK_COMMAND);
    MenuItem item2 = bar.addItem("item2", BLANK_COMMAND);
    MenuItem item3 = bar.addItem("item3", BLANK_COMMAND);

    // Test setting the selected item
    assertNull(bar.getSelectedItem());
    bar.selectItem(item1);
    assertEquals(item1, bar.getSelectedItem());

    // Test removing the selected item
    bar.removeItem(item1);
    assertNull(bar.getSelectedItem());

    // Test removing an item that is not selected
    bar.selectItem(item3);
    assertEquals(item3, bar.getSelectedItem());
    bar.removeItem(item2);
    assertEquals(item3, bar.getSelectedItem());

    // Test clearing all items
    bar.clearItems();
    assertNull(bar.getSelectedItem());
  }

  public void testClearSelectionAfterCommand() {
    MenuBar bar = new MenuBar();
    MenuItem item1 = bar.addItem("item1", BLANK_COMMAND);
    RootPanel.get().add(bar);


    bar.itemOver(item1, true);
    assertNotNull(bar.getSelectedItem());

    bar.itemOver(null, false);
    assertNull(bar.getSelectedItem());
  }
  public void testSelectItem() {
    MenuBar bar = new MenuBar(false);
    MenuItem item1 = new MenuItem("item1", BLANK_COMMAND);
    MenuItem item2 = new MenuItem("item2", BLANK_COMMAND);
    MenuItem item3 = new MenuItem("item3", BLANK_COMMAND);
    bar.addItem(item1);
    bar.addItem(item2);
    bar.addItem(item3);
    RootPanel.get().add(bar);

    bar.selectItem(item1);
    assertEquals(item1, bar.getSelectedItem());
    bar.selectItem(item3);
    assertEquals(item3, bar.getSelectedItem());
    bar.selectItem(null);
    assertNull(bar.getSelectedItem());
  }

  public void testTabKey() {
    // Create a menu bar with children.
    MenuBar l0 = new MenuBar();
    l0.setAutoOpen(true);
    MenuBar l1 = new MenuBar();
    l1.setAutoOpen(true);
    MenuBar l2 = new MenuBar();
    l2.setAutoOpen(true);
    MenuItem item2 = l2.addItem("l2", BLANK_COMMAND);
    MenuItem item1 = l1.addItem("l1", l2);
    MenuItem item0 = l0.addItem("l0", l1);
    RootPanel.get().add(l0);

    // Open l2.
    l0.itemOver(item0, true);
    l1.itemOver(item1, true);
    l2.itemOver(item2, true);
    assertTrue(l0.getPopup().isShowing());
    assertEquals(item0, l0.getSelectedItem());
    assertTrue(l1.getPopup().isShowing());
    assertEquals(item1, l1.getSelectedItem());

    // Tab away from the menu.
    NativeEvent event = Document.get().createKeyDownEvent(
        false, false, false, false, KeyCodes.KEY_TAB);
    l1.getElement().dispatchEvent(event);
    assertNull(l0.getPopup());
    assertNull(l0.getSelectedItem());
    assertNull(l1.getPopup());
  }
}
