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

import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.http.client.UrlBuilder;
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.Window.Location;
import com.google.gwt.user.client.Window.Navigator;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Test Case for {@link Window}.
 */
public class WindowTest extends GWTTestCase {

  private static native String getNodeName(Element elem) /*-{
    return (elem.nodeName || "").toLowerCase();
  }-*/;

  /**
   * Removes all elements in the body, except scripts and iframes.
   */
  private static void clearBodyContent() {
    Element bodyElem = RootPanel.getBodyElement();

    List<Element> toRemove = new ArrayList<Element>();
    for (int i = 0, n = DOM.getChildCount(bodyElem); i < n; ++i) {
      Element elem = DOM.getChild(bodyElem, i);
      String nodeName = getNodeName(elem);
      if (!"script".equals(nodeName) && !"iframe".equals(nodeName)) {
        toRemove.add(elem);
      }
    }

    for (int i = 0, n = toRemove.size(); i < n; ++i) {
      DOM.removeChild(bodyElem, toRemove.get(i));
    }
  }

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

  public void testLocation() {
    // testing reload, replace, and assign seemed to hang our junit harness.
    // Therefore only testing subset of Location that is testable.

    // Use History to get the #hash part of the url into a known state (if the
    // url has somehow been set to http://host/#, location.hash returns the
    // empty string, but location.href includes the trailing hash).
    History.newItem("foo");

    // As we have no control over these values we cannot assert much about them.
    String hash = Window.Location.getHash();
    String host = Window.Location.getHost();
    String hostName = Window.Location.getHostName();
    String href = Window.Location.getHref();
    assertNull(Window.Location.getParameter("fuzzy bunny"));
    String path = Window.Location.getPath();
    String port = Window.Location.getPort();
    String protocol = Window.Location.getProtocol();
    String query = Window.Location.getQueryString();

    // Check that the sum is equal to its parts.
    assertEquals(host, hostName + ":" + port);
    assertEquals(href, protocol + "//" + host + path + query + hash);
  }

  public void testLocationCreateUrlBuilder() {
    History.newItem("theHash");
    String expected = Location.getHref();

    // Build the string with the builder.
    UrlBuilder builder = Location.createUrlBuilder();
    String actual = builder.buildString();

    // Check the hash.
    {
      String[] expectedParts = expected.split("#");
      String[] actualParts = actual.split("#");
      assertEquals(2, actualParts.length);
      assertEquals(expectedParts[1], actualParts[1]);
      expected = expectedParts[0];
      actual = actualParts[0];
    }

    // Check the query parameters.
    {
      String[] expectedParts = expected.split("[?]");
      String[] actualParts = actual.split("[?]");
      if (expectedParts.length > 1) {
        assertEquals(2, actualParts.length);
        String[] expectedPairs = expectedParts[1].split("&");
        String[] actualPairs = actualParts[1].split("&");
        assertEquals(expectedPairs.length, actualPairs.length);
        for (String actualPair : actualPairs) {
          String[] kv = actualPair.split("=");
          assertEquals(Location.getParameter(kv[0]), kv.length > 1 ? kv[1] : "");
        }
      }
      expected = expectedParts[0];
      actual = actualParts[0];
    }

    // Check everything but the query params and hash/
    assertEquals(expected, actual);
  }

  public void testLocationParsing() {
    Map<String, List<String>> map;

    // typical case
    map = Window.Location.buildListParamMap("?fuzzy=bunnies&foo=bar&num=42");
    assertEquals(map.size(), 3);
    assertEquals(map.get("foo").get(0), "bar");
    assertEquals(map.get("fuzzy").get(0), "bunnies");

    // multiple values for the same parameter
    map = Window.Location.buildListParamMap(
        "?fuzzy=bunnies&foo=bar&num=42&foo=baz");
    assertEquals(map.size(), 3);
    assertEquals(map.get("foo").get(0), "bar");
    assertEquals(map.get("foo").get(1), "baz");

    // no query parameters.
    map = Window.Location.buildListParamMap("");
    assertEquals(map.size(), 0);

    // blank keys should be ignored, but blank values are OK. Also,
    // keys can contain whitespace. (but the browser may give whitespace
    // back as escaped).
    map = Window.Location.buildListParamMap("?&& &a&b=&c=c&d=d=d&=e&f=2&f=1&");
    assertEquals(map.size(), 6);
    assertEquals(map.get(" ").get(0), "");
    assertEquals(map.get("a").get(0), "");
    assertEquals(map.get("b").get(0), "");
    assertEquals(map.get("c").get(0), "c");
    assertEquals(map.get("d").get(0), "d=d");
    assertEquals(map.get("f").get(0), "2");
    assertEquals(map.get("f").get(1), "1");

    // Values escaped with hex codes should work too.
    map = Window.Location.buildListParamMap("?foo=bar%20baz%3aqux");
    assertEquals(map.get("foo").get(0), "bar baz:qux");
  }

  public void testNavigator() {
    assertNotNull(Navigator.getAppCodeName());
    assertNotNull(Navigator.getAppName());
    assertNotNull(Navigator.getAppVersion());
    assertNotNull(Navigator.getPlatform());
    assertNotNull(Navigator.getUserAgent());
    assertTrue(Navigator.isCookieEnabled());
    // We don't care if Java is enabled, but need to make sure this call does
    // not throw. The try/catch block keeps the compiled code from being
    // optimized away.
    try {
      Navigator.isJavaEnabled();
    } catch (JavaScriptException e) {
      throw e;
    }
  }

  /**
   * Tests the ability of the Window to get the client size correctly with and
   * without visible scroll bars.
   * Failed in all modes due to HtmlUnit bug:
   * https://sourceforge.net/tracker/?func=detail&aid=2944261&group_id=47038&atid=448266
   */
  @DoNotRunWith(Platform.HtmlUnitBug)
  public void testGetClientSize() {

    // NOTE: We must clear the DOM here so that previous tests do not pollute
    // our results.
    clearBodyContent();

    // Get the dimensions without any scroll bars
    Window.enableScrolling(false);
    final int oldClientHeight = Window.getClientHeight();
    final int oldClientWidth = Window.getClientWidth();
    assertTrue("Expect positive oldClientHeight. "
        + "This will fail in WebKit if run headless", oldClientHeight > 0);
    assertTrue(oldClientWidth > 0);

    // Firefox hides scrollbar if clientHeight < 49 even when it should show.
    // If we are in this case, simply return.
    if (oldClientHeight < 49 && Navigator.getUserAgent().contains("Firefox")) {
      return;
    }

    // Compare to the dimensions with scroll bars
    Window.enableScrolling(true);
    final Label largeDOM = new Label();
    largeDOM.setPixelSize(oldClientWidth + 100, oldClientHeight + 100);
    RootPanel.get().add(largeDOM);
    delayTestFinish(200);
    DeferredCommand.addCommand(new Command() {
      public void execute() {
        int newClientHeight = Window.getClientHeight();
        int newClientWidth = Window.getClientWidth();
        assertTrue(newClientHeight < oldClientHeight);
        assertTrue(newClientWidth < oldClientWidth);
        RootPanel.get().remove(largeDOM);
        finishTest();
      }
    });
  }

  /**
   * Calculates the sizes for Window extras such as border, menu, tool bar, and
   * stores the original sizes to restore at the end of test.
   */
  public static final class ResizeHelper {
    private static int clientHeight;
    private static int clientWidth;
    private static int extraWidth;
    private static int extraHeight;
    private static boolean initialized;

    public static int getExtraHeight() {
      ensureInitialized();
      return extraHeight;
    }

    public static int getExtraWidth() {
      ensureInitialized();
      return extraWidth;
    }

    /**
     * Wraps {@code Window#resizeBy(int, int)} to ensure initialized. This may
     * be a no-op in Chrome.
     *
     * @param width
     * @param height
     * @return Whether this operation is done
     */
    public static boolean resizeBy(int width, int height) {
      if (ensureInitialized()) {
        Window.resizeBy(width, height);
      }
      return initialized;
    }

    /**
     * Wraps {@code Window#resizeTo(int, int)} to ensure initialized. This may
     * be a no-op in Chrome.
     *
     * @param width
     * @param height
     * @return Whether this operation is done
     */
    public static boolean resizeTo(int width, int height) {
      if (ensureInitialized()) {
        Window.resizeTo(width, height);
      }
      return initialized;
    }

    public static void restoreSize() {
      // Ignore if not initialized
      if (initialized) {
        Window.resizeTo(clientWidth + extraWidth, clientHeight + extraHeight);
      }
    }

    private static synchronized boolean ensureInitialized() {
      if (!initialized) {
        init();
      }
      return initialized;
    }

    private static void init() {
      // resizeTo works in Chrome if the window is opened by Window.open(),
      // which is the case when testing with Selenium and the server is started
      // with -multiWin. However, the size change is deferred. The test would
      // involve many nested DeferredCommand.
      if (Navigator.getUserAgent().toLowerCase().contains("chrome")) {
        return;
      }

      // FF4 on win can start in 'almost' fullscreen when the window title bar 
      // is hidden but accounted incorrectly, so, move the window and resize to 
      // smaller size first, to take it out of 'full screen mode'.
      Window.moveTo(10,10);
      Window.resizeTo(700, 500);

      // store the original size (to be used in restoreSize)
      clientHeight = Window.getClientHeight();
      clientWidth = Window.getClientWidth();
      // IE cannot resize window out of the screen, so we need to move the
      // window such that it can be resized to below size.
      // We do not have method to return the window coordinates (screenLeft,
      // screenTop), so this move is not undone.
      Window.moveTo(0,0);

      // clientWidth is innerWidth, resizeTo specifies outerWidth
      // Let's find out the delta for extras such as border, menu, tool bar.
      // If the sizes are too small to show the extras, resizeTo may not set the
      // sizes as requested.
      // If the sizes are too big, for example, height > screen.availHeight + 40
      // on FF, resizeTo silently sets the height to screen.availHeight + 40.
      // Some test machines are configured at this time as 800x600, reduce the size 
      // to give some 'buffer'
      Window.resizeTo(750, 550);
      extraWidth = 750 - Window.getClientWidth();
      extraHeight = 550 - Window.getClientHeight();
      initialized = true;
      restoreSize();
    }
  }

  private static final class TestResizeHandler implements ResizeHandler {
    private int height;
    private int width;

    public void onResize(ResizeEvent event) {
      width = event.getWidth();
      height = event.getHeight();
    }

    public int getHeight() {
      return height;
    }

    public int getWidth() {
      return width;
    }
  }

  /**
   * Tests the ability of resize the Window and catch resize events.
   */
  @DoNotRunWith({Platform.HtmlUnitLayout})
  public void testResizing() {
    clearBodyContent();

    // Handler for resize events
    final TestResizeHandler resizeHandler = new TestResizeHandler();
    final HandlerRegistration handlerRegistration = Window.addResizeHandler(resizeHandler);

    delayTestFinish(2000);
    DeferredCommand.addCommand(new Command() {
      public void execute() {
        // Sizes must be appropriate, otherwise browsers may not resize as
        // requested. See comments in ResizeHelper.
        int width = 600;
        int height = 500;
        // ensureInitialized could fail on Chrome
        if (!ResizeHelper.resizeTo(width, height)) {
          handlerRegistration.removeHandler();
          finishTest(); // nothing we can test
        }

        assertEquals(width, Window.getClientWidth() + ResizeHelper.getExtraWidth());
        assertEquals(height, Window.getClientHeight() + ResizeHelper.getExtraHeight());
        // TODO: TestResizeHandler.getWidth() returns 0 -- need to investigate
        // assertEquals(resizeHandler.getWidth(), Window.getClientWidth());
        // assertEquals(resizeHandler.getHeight(), Window.getClientHeight());
        ResizeHelper.resizeBy(10, 20);
        assertEquals(width + 10, Window.getClientWidth() + ResizeHelper.getExtraWidth());
        assertEquals(height + 20, Window.getClientHeight() + ResizeHelper.getExtraHeight());
        // assertEquals(resizeHandler.getWidth(), Window.getClientWidth());
        // assertEquals(resizeHandler.getHeight(), Window.getClientHeight());

        // Cleanup the window
        handlerRegistration.removeHandler();
        ResizeHelper.restoreSize();
        finishTest();
      }
    });
  }

  /**
   * Tests the ability of scroll the Window and catch scroll events.
   * Failed in all modes due to HtmlUnit bug:
   * https://sourceforge.net/tracker/?func=detail&aid=2897457&group_id=47038&atid=448266
   * <p>
   * TODO(flin): it is marked fixed, but is still not fixed.
   */
  @DoNotRunWith(Platform.HtmlUnitBug)
  public void testScrolling() {
    // Force scroll bars to appear
    Window.enableScrolling(true);
    int clientHeight = Window.getClientHeight();
    int clientWidth = Window.getClientWidth();
    final Label largeDOM = new Label();
    largeDOM.setPixelSize(clientWidth + 500, clientHeight + 500);
    RootPanel.get().add(largeDOM);

    // Listener for scroll events
    Window.scrollTo(100, 200);
    assertEquals(100, Window.getScrollLeft());
    assertEquals(200, Window.getScrollTop());
    Window.scrollTo(0, 0);
    assertEquals(0, Window.getScrollLeft());
    assertEquals(0, Window.getScrollTop());

    // Cleanup the window
    RootPanel.get().remove(largeDOM);
  }

  @SuppressWarnings("deprecation")
  static class ListenerTester implements WindowResizeListener {
    static int resize = 0;

    public void onWindowResized(int width, int height) {
      ++resize;
    }

    public static void fire() {
      resize = 0;
      ResizeEvent.fire(Window.handlers, 0, 0);
    }
  }

  @SuppressWarnings("deprecation")
  public void testListenerRemoval() {

    WindowResizeListener r1 = new ListenerTester();
    WindowResizeListener r2 = new ListenerTester();

    Window.addWindowResizeListener(r1);
    Window.addWindowResizeListener(r2);

    ListenerTester.fire();
    assertEquals(ListenerTester.resize, 2);

    Window.removeWindowResizeListener(r1);
    ListenerTester.fire();
    assertEquals(ListenerTester.resize, 1);

    Window.removeWindowResizeListener(r2);
    ListenerTester.fire();
    assertEquals(ListenerTester.resize, 0);
  }

}
