/*
 * 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.http.client.URL;
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 bar");

    // 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]),
                       // has a URL encoded ':' in a parameter
                       kv.length > 1 ? URL.decodeQueryString(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(1000);
    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);
  }

}
