/*
 * 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.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;

/**
 * Tests for {@link PopupPanel}.
 */
public class PopupTest extends GWTTestCase {

  /**
   * The Widget adder used to set the widget in a {@link PopupPanel}.
   */
  private static class Adder implements HasWidgetsTester.WidgetAdder {
    @Override
    public void addChild(HasWidgets container, Widget child) {
      ((PopupPanel) container).setWidget(child);
    }
  }

  /**
   * Expose otherwise private or protected methods.
   */
  private static class TestablePopupPanel extends PopupPanel {
    private int onLoadCount;

    public void assertOnLoadCount(int expected) {
      assertEquals(expected, onLoadCount);
    }

    @Override
    public com.google.gwt.user.client.Element getContainerElement() {
      return super.getContainerElement();
    }

    @Override
    public void onLoad() {
      super.onLoad();
      onLoadCount++;
    }
  }

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

  /**
   * Test the basic accessors.
   */
  public void testAccessors() {
    PopupPanel popup = createPopupPanel();

    // Animation enabled
    assertFalse(popup.isAnimationEnabled());
    popup.setAnimationEnabled(true);
    assertTrue(popup.isAnimationEnabled());

    // Modal
    popup.setModal(true);
    assertTrue(popup.isModal());
    popup.setModal(false);
    assertFalse(popup.isModal());

    // AutoHide enabled
    popup.setAutoHideEnabled(true);
    assertTrue(popup.isAutoHideEnabled());
    popup.setAutoHideEnabled(false);
    assertFalse(popup.isAutoHideEnabled());

    // PreviewAllNativeEvents enabled
    popup.setPreviewingAllNativeEvents(true);
    assertTrue(popup.isPreviewingAllNativeEvents());
    popup.setPreviewingAllNativeEvents(false);
    assertFalse(popup.isPreviewingAllNativeEvents());

    // setVisible
    assertTrue(popup.isVisible());
    popup.setVisible(false);
    assertFalse(popup.isVisible());
    popup.setVisible(true);
    assertTrue(popup.isVisible());

    // isShowing
    assertFalse(popup.isShowing());
    popup.show();
    assertTrue(popup.isShowing());
    popup.hide();
    assertFalse(popup.isShowing());
  }

  public void testAttachDetachOrder() {
    HasWidgetsTester.testAll(createPopupPanel(), new Adder(), false);
  }

  public void testAutoHidePartner() {
    final PopupPanel popup = new PopupPanel();

    // Add a partner
    DivElement partner0 = Document.get().createDivElement();
    popup.addAutoHidePartner(partner0);
    popup.addAutoHidePartner(Document.get().createDivElement());

    // Remove a partner
    popup.removeAutoHidePartner(partner0);
  }

  public void testAutoHideOnHistoryEvent() {
    PopupPanel popup = createPopupPanel();
    popup.show();
    assertTrue(popup.isShowing());

    // When autoHideOnHistoryEvent is disabled, the popup remains visible.
    History.newItem("popupToken0");
    assertTrue(popup.isShowing());

    // When autoHideOnHistoryEvent is enabled, the popup is hidden.
    popup.setAutoHideOnHistoryEventsEnabled(true);
    History.newItem("popupToken1");
    assertFalse(popup.isShowing());
  }

  /**
   * Tests that a large PopupPanel is not positioned off the top or left edges
   * of the browser window, making part of the panel unreachable.
   */
  public void testCenterLargePopup() {
    PopupPanel popup = new PopupPanel();
    popup.setHeight("4096px");
    popup.setWidth("4096px");
    popup.setWidget(new Label("foo"));
    popup.center();
    assertEquals(0, popup.getAbsoluteTop());
    assertEquals(0, popup.getAbsoluteLeft());
  }

  /**
   * Issue 2463: If a {@link PopupPanel} contains a dependent {@link PopupPanel}
   * that is hidden or shown in the onDetach or onAttach method, we could run
   * into conflicts with the animations. The {@link MenuBar} exhibits this
   * behavior because, when we detach a {@link MenuBar} from the page, it closes
   * all of its sub menus, each located in a different {@link PopupPanel}.
   */
  public void testDependantPopupPanel() {
    // Create the dependent popup
    final PopupPanel dependantPopup = createPopupPanel();
    dependantPopup.setAnimationEnabled(true);

    // Create the primary popup
    final PopupPanel primaryPopup = new PopupPanel(false, false) {
      @Override
      protected void onAttach() {
        dependantPopup.show();
        super.onAttach();
      }

      @Override
      protected void onDetach() {
        dependantPopup.hide();
        super.onDetach();
      }
    };
    primaryPopup.setAnimationEnabled(true);

    testDependantPopupPanel(primaryPopup);
  }

  public void testGlassPanelDisabled() {
    // Verify that the glass is disabled by default
    PopupPanel popup = createPopupPanel();
    assertFalse(popup.isGlassEnabled());
    assertNull(popup.getGlassElement());

    // Verify the glass panel is never created
    popup.show();
    assertNull(popup.getGlassElement());
    popup.hide();
  }

  public void testGlassDisabledWhileShowing() {
    // Show the popup and glass panel
    PopupPanel popup = createPopupPanel();
    popup.setGlassEnabled(true);
    Element glass = popup.getGlassElement();
    popup.show();

    // Disable the glass panel and hide the popup
    popup.setGlassEnabled(false);
    assertTrue(isAttached(glass));
    popup.hide();
    assertFalse(isAttached(glass));

    // Show the popup and verify that glass is no longer used
    popup.show();
    assertFalse(isAttached(glass));
    popup.hide();
  }

  public void testGlassEnabled() {
    // Verify that the glass is disabled by default
    PopupPanel popup = createPopupPanel();
    assertFalse(popup.isGlassEnabled());
    assertNull(popup.getGlassElement());

    // Enable the glass panel and verify it is created
    popup.setGlassEnabled(true);
    Element glass = popup.getGlassElement();
    assertNotNull(glass);
    assertFalse(isAttached(glass));

    // Show the popup and verify the glass panel is added
    popup.show();
    assertTrue(isAttached(glass));

    // Hide the popup and verify the glass panel is removed
    popup.hide();
    assertFalse(isAttached(glass));
  }

  public void testGlassEnabledWhileShowing() {
    // Verify that the glass is disabled by default
    PopupPanel popup = createPopupPanel();
    assertFalse(popup.isGlassEnabled());
    assertNull(popup.getGlassElement());

    // Show the popup and enable the glass panel
    popup.show();
    popup.setGlassEnabled(true);
    Element glass = popup.getGlassElement();
    assertNotNull(glass);
    assertFalse(isAttached(glass));

    // Hide the popup and verify the glass panel is removed
    popup.hide();
    assertFalse(isAttached(glass));

    // Show the popup and verify the glas is now used
    popup.show();
    assertTrue(isAttached(glass));
    popup.hide();
  }

  /**
   * Test the hiding a popup while it is showing will not result in an illegal
   * state.
   */
  public void testHideWhileShowing() {
    PopupPanel popup = createPopupPanel();

    // Start showing the popup.
    popup.setAnimationEnabled(true);
    popup.show();
    assertTrue(popup.isShowing());

    // Hide the popup while its showing.
    popup.hide();
    assertFalse(popup.isShowing());
  }

  /**
   * Test that the onLoad method is only called once when showing the popup.
   */
  public void testOnLoad() {
    TestablePopupPanel popup = new TestablePopupPanel();

    // show() without animation
    {
      popup.setAnimationEnabled(false);
      popup.show();
      popup.assertOnLoadCount(1);
      popup.hide();
    }

    // show() with animation
    {
      popup.setAnimationEnabled(true);
      popup.show();
      popup.assertOnLoadCount(2);
      popup.hide();
    }

    // center() without animation
    {
      popup.setAnimationEnabled(false);
      popup.center();
      popup.assertOnLoadCount(3);
      popup.hide();
    }

    // center() with animation
    {
      popup.setAnimationEnabled(true);
      popup.center();
      popup.assertOnLoadCount(4);
      popup.hide();
    }
  }

  public void testPopup() {
    // Get rid of window margins so we can test absolute position.
    Window.setMargin("0px");

    PopupPanel popup = createPopupPanel();
    popup.setAnimationEnabled(false);
    Label lbl = new Label("foo");

    // Make sure that setting the popup's size & position works _before_
    // setting its widget.
    popup.setSize("384px", "128px");
    popup.setPopupPosition(128, 64);
    popup.setWidget(lbl);
    popup.show();

    // DecoratorPanel adds width and height because it wraps the content in a
    // 3x3 table.
    assertTrue("Expected >= 384, got " + popup.getOffsetWidth(),
        popup.getOffsetWidth() >= 384);
    assertTrue("Expected >= 128, got " + popup.getOffsetHeight(),
        popup.getOffsetHeight() >= 128);
    assertEquals(128, popup.getPopupLeft());
    assertEquals(64, popup.getPopupTop());

    // Make sure that the popup returns to the correct position
    // after hiding and showing it.
    popup.hide();
    popup.show();
    assertEquals(128, popup.getPopupLeft());
    assertEquals(64, popup.getPopupTop());

    // Make sure that setting the popup's size & position works _after_
    // setting its widget (and that clearing its size properly resizes it to
    // its widget's size).
    popup.setSize("", "");
    popup.setPopupPosition(16, 16);

    // DecoratorPanel adds width and height because it wraps the content in a
    // 3x3 table.
    assertTrue(popup.getOffsetWidth() >= lbl.getOffsetWidth());
    assertTrue(popup.getOffsetWidth() >= lbl.getOffsetHeight());
    assertEquals(16, popup.getAbsoluteLeft());
    assertEquals(16, popup.getAbsoluteTop());

    // Ensure that hiding the popup fires the appropriate events.
    delayTestFinish(1000);
    popup.addCloseHandler(new CloseHandler<PopupPanel>() {
      @Override
      public void onClose(CloseEvent<PopupPanel> event) {
        finishTest();
      }
    });
    popup.hide();
  }

  /**
   * Issue 4720: Glass is not removed when removeFromParent is called.
   */
  public void testRemoveFromParent() {
    PopupPanel popup = createPopupPanel();
    popup.setGlassEnabled(true);
    assertNull(popup.getGlassElement().getParentElement());

    popup.show();
    assertNotNull(popup.getGlassElement().getParentElement());

    popup.removeFromParent();
    assertNull(popup.getGlassElement().getParentElement());
  }

  public void testSeparateContainers() {
    TestablePopupPanel p1 = new TestablePopupPanel();
    TestablePopupPanel p2 = new TestablePopupPanel();
    assertTrue(p1.getContainerElement() != null);
    assertTrue(p2.getContainerElement() != null);
    assertFalse(p1.getContainerElement() == p2.getContainerElement());
  }

  /**
   * Issue 2481: Try to set the contents of the popup while the popup is
   * attached. When we hide the popup, this should not leave the popup in an
   * invalid attach state.
   */
  public void testSetWidgetWhileAttached() {
    PopupPanel popup = createPopupPanel();
    popup.show();
    popup.setWidget(new Label("test"));
    popup.hide();
  }

  public void testSetVisibleWithGlass() {
    PopupPanel popup = createPopupPanel();
    popup.setGlassEnabled(true);
    popup.show();

    Element glass = popup.getGlassElement();
    assertTrue(popup.isVisible());
    assertFalse("hidden".equalsIgnoreCase(glass.getStyle().getVisibility()));

    popup.setVisible(false);
    assertFalse(popup.isVisible());
    assertTrue("hidden".equalsIgnoreCase(glass.getStyle().getVisibility()));

    popup.setVisible(true);
    assertTrue(popup.isVisible());
    assertFalse("hidden".equalsIgnoreCase(glass.getStyle().getVisibility()));

    popup.hide();
  }

  /**
   * Test that showing a popup while it is attached does not put it in an
   * invalid state.
   */
  public void testShowWhileAttached() {
    PopupPanel popup = createPopupPanel();
    RootPanel.get().add(popup);
    popup.show();
    assertTrue(popup.isAttached());
    assertTrue(popup.isShowing());

    popup.hide();
    assertFalse(popup.isAttached());
    assertFalse(popup.isShowing());
  }

  /**
   * Test that showing a popup while it is hiding will not result in an illegal
   * state.
   */
  public void testShowWhileHiding() {
    PopupPanel popup = createPopupPanel();

    // Show the popup
    popup.setAnimationEnabled(false);
    popup.show();
    assertTrue(popup.isShowing());

    // Start hiding the popup
    popup.setAnimationEnabled(true);
    popup.hide();
    assertFalse(popup.isShowing());

    // Show the popup while its hiding
    popup.show();
    assertTrue(popup.isShowing());
  }

  /**
   * Create a new PopupPanel.
   */
  protected PopupPanel createPopupPanel() {
    return new PopupPanel();
  }

  @Override
  protected void gwtTearDown() {
    RootPanel.get().clear();
  }

  /**
   * @see #testDependantPopupPanel()
   */
  protected void testDependantPopupPanel(final PopupPanel primaryPopup) {
    // Show the popup
    primaryPopup.show();

    // Hide the popup
    new Timer() {
      @Override
      public void run() {
        primaryPopup.hide();
      }
    }.schedule(1000);

    delayTestFinish(5000);
    // Give time for any errors to occur
    new Timer() {
      @Override
      public void run() {
        finishTest();
      }
    }.schedule(2000);
  }

  private boolean isAttached(Element elem) {
    return Document.get().getBody().isOrHasChild(elem);
  }
}
