/*
 * 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.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.HasCloseHandlers;
import com.google.gwt.event.logical.shared.HasResizeHandlers;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.HasHandlers;
import com.google.gwt.http.client.URL;
import com.google.gwt.http.client.UrlBuilder;
import com.google.gwt.user.client.impl.WindowImpl;

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

/**
 * This class provides access to the browser window's methods, properties, and
 * events.
 */
public class Window {

  /**
   * Fired just before the browser window closes or navigates to a different
   * site.
   */
  public static class ClosingEvent extends GwtEvent<Window.ClosingHandler> {
    /**
     * The event type.
     */
    private static final Type<ClosingHandler> TYPE = new Type<ClosingHandler>();

    static Type<ClosingHandler> getType() {
      return TYPE;
    }

    /**
     * The message to display to the user to see whether they really want to
     * leave the page.
     */
    private String message = null;

    @Override
    public final Type<ClosingHandler> getAssociatedType() {
      return TYPE;
    }

    /**
     * Get the message that will be presented to the user in a confirmation
     * dialog that asks the user whether or not she wishes to navigate away from
     * the page.
     * 
     * @return the message to display to the user, or null
     */
    public String getMessage() {
      return message;
    }

    /**
     * Set the message to a <code>non-null</code> value to present a
     * confirmation dialog that asks the user whether or not she wishes to
     * navigate away from the page. If multiple handlers set the message, the
     * last message will be displayed; all others will be ignored.
     * 
     * @param message the message to display to the user, or null
     */
    public void setMessage(String message) {
      this.message = message;
    }

    @Override
    protected void dispatch(ClosingHandler handler) {
      handler.onWindowClosing(this);
    }
  }

  /**
   * Handler for {@link Window.ClosingEvent} events.
   */
  public interface ClosingHandler extends EventHandler {
    /**
     * Fired just before the browser window closes or navigates to a different
     * site. No user-interface may be displayed during shutdown.
     * 
     * @param event the event
     */
    void onWindowClosing(Window.ClosingEvent event);
  }

  /**
   * This class provides access to the browser's location's object. The location
   * object contains information about the current URL and methods to manipulate
   * it. <code>Location</code> is a very simple wrapper, so not all browser
   * quirks are hidden from the user.
   * 
   */
  public static class Location {
    private static Map<String, String> paramMap;
    private static Map<String, List<String>> listParamMap;

    /**
     * Assigns the window to a new URL. All GWT state will be lost.
     * 
     * @param newURL the new URL
     */
    public static native void assign(String newURL) /*-{
      $wnd.location.assign(newURL);
    }-*/;

    /**
     * Create a {@link UrlBuilder} based on this {@link Location}.
     * 
     * @return the new builder
     */
    public static UrlBuilder createUrlBuilder() {
      UrlBuilder builder = new UrlBuilder();
      builder.setProtocol(getProtocol());
      builder.setHost(getHost());
      String path = getPath();
      if (path != null && path.length() > 0) {
        builder.setPath(path);
      }
      String hash = getHash();
      if (hash != null && hash.length() > 0) {
        builder.setHash(hash);
      }
      String port = getPort();
      if (port != null && port.length() > 0) {
        builder.setPort(Integer.parseInt(port));
      }

      // Add query parameters.
      Map<String, List<String>> params = getParameterMap();
      for (Map.Entry<String, List<String>> entry : params.entrySet()) {
        List<String> values = new ArrayList<String>(entry.getValue());
        builder.setParameter(entry.getKey(),
            values.toArray(new String[values.size()]));
      }

      return builder;
    }

    /**
     * Gets the string to the right of the URL's hash.
     * 
     * @return the string to the right of the URL's hash.
     */
    public static String getHash() {
      return impl.getHash();
    }

    /**
     * Gets the URL's host and port name.
     * 
     * @return the host and port name
     */
    public static native String getHost() /*-{
      return $wnd.location.host;
    }-*/;

    /**
     * Gets the URL's host name.
     * 
     * @return the host name
     */
    public static native String getHostName() /*-{
      return $wnd.location.hostname;
    }-*/;

    /**
     * Gets the entire URL.
     * 
     * @return the URL
     */
    public static native String getHref() /*-{
      return $wnd.location.href;
    }-*/;

    /**
     * Gets the URL's parameter of the specified name. Note that if multiple
     * parameters have been specified with the same name, the last one will be
     * returned.
     * 
     * @param name the name of the URL's parameter
     * @return the value of the URL's parameter
     */
    public static String getParameter(String name) {
      ensureParameterMap();
      return paramMap.get(name);
    }

    /**
     * Returns a Map of the URL query parameters for the host page; since
     * changing the map would not change the window's location, the map returned
     * is immutable.
     * 
     * @return a map from URL query parameter names to a list of values
     */
    public static Map<String, List<String>> getParameterMap() {
      if (listParamMap == null) {
        listParamMap = buildListParamMap(getQueryString());
      }
      return listParamMap;
    }

    /**
     * Gets the path to the URL.
     * 
     * @return the path to the URL.
     */
    public static native String getPath() /*-{
      return $wnd.location.pathname;
    }-*/;

    /**
     * Gets the URL's port.
     * 
     * @return the URL's port
     */
    public static native String getPort() /*-{
      return $wnd.location.port;
    }-*/;

    /**
     * Gets the URL's protocol.
     * 
     * @return the URL's protocol.
     */
    public static native String getProtocol() /*-{
      return $wnd.location.protocol;
    }-*/;

    /**
     * Gets the URL's query string.
     * 
     * @return the URL's query string
     */
    public static String getQueryString() {
      return impl.getQueryString();
    }

    /**
     * Reloads the current browser window. All GWT state will be lost.
     */
    public static native void reload() /*-{
      $wnd.location.reload();
    }-*/;

    /**
     * Replaces the current URL with a new one. All GWT state will be lost. In
     * the browser's history, the current URL will be replaced by the new URL.
     * 
     * @param newURL the new URL
     */
    public static native void replace(String newURL) /*-{
      $wnd.location.replace(newURL);
    }-*/;

    /**
     * Builds the immutable map from String to List<String> that we'll return in
     * getParameterMap(). Package-protected for testing.
     * 
     * @return a map from the
     */
    static Map<String, List<String>> buildListParamMap(String queryString) {
      Map<String, List<String>> out = new HashMap<String, List<String>>();

      if (queryString != null && queryString.length() > 1) {
        String qs = queryString.substring(1);

        for (String kvPair : qs.split("&")) {
          String[] kv = kvPair.split("=", 2);
          if (kv[0].length() == 0) {
            continue;
          }

          List<String> values = out.get(kv[0]);
          if (values == null) {
            values = new ArrayList<String>();
            out.put(kv[0], values);
          }
          values.add(kv.length > 1 ? URL.decodeQueryString(kv[1]) : "");
        }
      }

      for (Map.Entry<String, List<String>> entry : out.entrySet()) {
        entry.setValue(Collections.unmodifiableList(entry.getValue()));
      }

      out = Collections.unmodifiableMap(out);

      return out;
    }

    private static void ensureParameterMap() {
      if (paramMap == null) {
        paramMap = new HashMap<String, String>();
        String queryString = getQueryString();
        if (queryString != null && queryString.length() > 1) {
          String qs = queryString.substring(1);
          for (String kvPair : qs.split("&")) {
            String[] kv = kvPair.split("=", 2);
            if (kv.length > 1) {
              paramMap.put(kv[0], URL.decodeQueryString(kv[1]));
            } else {
              paramMap.put(kv[0], "");
            }
          }
        }
      }
    }

    private Location() {
    }
  }

  /**
   * This class provides access to the browser's navigator object. The mimeTypes
   * and plugins properties are not included.
   */
  public static class Navigator {
    /**
     * Gets the navigator.appCodeName.
     *
     * @return the window's navigator.appCodeName.
     */
    public static native String getAppCodeName() /*-{
      return $wnd.navigator.appCodeName;
    }-*/;

    /**
     * Gets the navigator.appName.
     *
     * @return the window's navigator.appName.
     */
    public static native String getAppName() /*-{
      return $wnd.navigator.appName;
    }-*/;

    /**
     * Gets the navigator.appVersion.
     *
     * @return the window's navigator.appVersion.
     */
    public static native String getAppVersion() /*-{
      return $wnd.navigator.appVersion;
    }-*/;

    /**
     * Gets the navigator.platform.
     *
     * @return the window's navigator.platform.
     */
    public static native String getPlatform() /*-{
      return $wnd.navigator.platform;
    }-*/;

    /**
     * Gets the navigator.userAgent.
     *
     * @return the window's navigator.userAgent.
     */
    public static native String getUserAgent() /*-{
      return $wnd.navigator.userAgent;
    }-*/;

    /**
     * Checks whether or not cookies are enabled or disabled.
     *
     * @return true if a cookie can be set, false if not
     */
    public static boolean isCookieEnabled() {
      return Cookies.isCookieEnabled();
    }

    /**
     * Tests whether Java is enabled in the current browser.
     *
     * @return the window's navigator.javaEnabled.
     */
    public static native boolean isJavaEnabled() /*-{
      return $wnd.navigator.javaEnabled();
    }-*/;

    private Navigator() {
    }
  }

  /**
   * Fired when the browser window is scrolled.
   */
  public static class ScrollEvent extends GwtEvent<Window.ScrollHandler> {
    /**
     * The event type.
     */
    static final Type<Window.ScrollHandler> TYPE = new Type<Window.ScrollHandler>();

    static Type<Window.ScrollHandler> getType() {
      return TYPE;
    }

    private int scrollLeft;
    private int scrollTop;

    /**
     * Construct a new {@link Window.ScrollEvent}.
     * 
     * @param scrollLeft the left scroll position
     * @param scrollTop the top scroll position
     */
    private ScrollEvent(int scrollLeft, int scrollTop) {
      this.scrollLeft = scrollLeft;
      this.scrollTop = scrollTop;
    }

    @Override
    public final Type<ScrollHandler> getAssociatedType() {
      return TYPE;
    }

    /**
     * Gets the window's scroll left.
     * 
     * @return window's scroll left
     */
    public int getScrollLeft() {
      return scrollLeft;
    }

    /**
     * Get the window's scroll top.
     * 
     * @return the window's scroll top
     */
    public int getScrollTop() {
      return scrollTop;
    }

    @Override
    protected void dispatch(ScrollHandler handler) {
      handler.onWindowScroll(this);
    }
  }

  /**
   * Handler for {@link Window.ScrollEvent} events.
   */
  public interface ScrollHandler extends EventHandler {
    /**
     * Fired when the browser window is scrolled.
     * 
     * @param event the event
     */
    void onWindowScroll(Window.ScrollEvent event);
  }

  private static class WindowHandlers extends HandlerManager implements
      HasCloseHandlers<Window>, HasResizeHandlers, HasHandlers {

    public WindowHandlers() {
      super(null);
    }

    public HandlerRegistration addCloseHandler(CloseHandler<Window> handler) {
      return addHandler(CloseEvent.getType(), handler);
    }

    public HandlerRegistration addResizeHandler(ResizeHandler handler) {
      return addHandler(ResizeEvent.getType(), handler);
    }

    public HandlerManager getHandlers() {
      return this;
    }
  }

  // Package protected for testing.
  static WindowHandlers handlers;
  private static boolean closeHandlersInitialized;
  private static boolean scrollHandlersInitialized;
  private static boolean resizeHandlersInitialized;
  private static int lastResizeWidth;
  private static int lastResizeHeight;

  private static final WindowImpl impl = GWT.create(WindowImpl.class);

  /**
   * Adds a {@link CloseEvent} handler.
   * 
   * @param handler the handler
   * @return returns the handler registration
   */
  public static HandlerRegistration addCloseHandler(CloseHandler<Window> handler) {
    maybeInitializeCloseHandlers();
    return addHandler(CloseEvent.getType(), handler);
  }

  /**
   * Adds a {@link ResizeEvent} handler.
   * 
   * @param handler the handler
   * @return returns the handler registration
   */
  public static HandlerRegistration addResizeHandler(ResizeHandler handler) {
    maybeInitializeCloseHandlers();
    maybeInitializeResizeHandlers();
    return addHandler(ResizeEvent.getType(), handler);
  }

  /**
   * Adds a listener to receive window closing events.
   * 
   * @deprecated use {@link Window#addWindowClosingHandler(ClosingHandler)} and
   *             {@link Window#addCloseHandler(CloseHandler)} instead
   * @param listener the listener to be informed when the window is closing
   */
  @Deprecated
  public static void addWindowCloseListener(WindowCloseListener listener) {
    BaseListenerWrapper.WrapWindowClose.add(listener);
  }

  /**
   * Adds a {@link Window.ClosingEvent} handler.
   * 
   * @param handler the handler
   * @return returns the handler registration
   */
  public static HandlerRegistration addWindowClosingHandler(
      ClosingHandler handler) {
    maybeInitializeCloseHandlers();
    return addHandler(Window.ClosingEvent.getType(), handler);
  }

  /**
   * Adds a listener to receive window resize events.
   * 
   * @param listener the listener to be informed when the window is resized
   * @deprecated use {@link Window#addResizeHandler(ResizeHandler)} instead
   */
  @Deprecated
  public static void addWindowResizeListener(WindowResizeListener listener) {
    BaseListenerWrapper.WrapWindowResize.add(listener);
  }

  /**
   * Adds a {@link Window.ScrollEvent} handler.
   * 
   * @param handler the handler
   * @return returns the handler registration
   */
  public static HandlerRegistration addWindowScrollHandler(
      Window.ScrollHandler handler) {
    maybeInitializeCloseHandlers();
    maybeInitializeScrollHandlers();
    return addHandler(Window.ScrollEvent.getType(), handler);
  }

  /**
   * Adds a listener to receive window scroll events.
   * 
   * @param listener the listener to be informed when the window is scrolled
   * @deprecated use {@link Window#addWindowScrollHandler(ScrollHandler)}
   *             instead
   */
  @Deprecated
  public static void addWindowScrollListener(WindowScrollListener listener) {
    BaseListenerWrapper.WrapWindowScroll.add(listener);
  }

  /**
   * Displays a message in a modal dialog box.
   * 
   * @param msg the message to be displayed.
   */
  public static native void alert(String msg) /*-{
    $wnd.alert(msg);
  }-*/;

  /**
   * Displays a message in a modal dialog box, along with the standard 'OK' and
   * 'Cancel' buttons.
   * 
   * @param msg the message to be displayed.
   * @return <code>true</code> if 'OK' is clicked, <code>false</code> if
   *         'Cancel' is clicked.
   */
  public static native boolean confirm(String msg) /*-{
    return $wnd.confirm(msg);
  }-*/;

  /**
   * Use this method to explicitly disable the window's scrollbars. Applications
   * that choose to resize their user-interfaces to fit within the window's
   * client area will normally want to disable window scrolling.
   * 
   * @param enable <code>false</code> to disable window scrolling
   */
  public static void enableScrolling(boolean enable) {
    Document.get().enableScrolling(enable);
  }

  /**
   * Gets the height of the browser window's client area excluding the scroll
   * bar.
   * 
   * @return the window's client height
   */
  public static int getClientHeight() {
    return Document.get().getClientHeight();
  }

  /**
   * Gets the width of the browser window's client area excluding the vertical
   * scroll bar.
   * 
   * @return the window's client width
   */
  public static int getClientWidth() {
    return Document.get().getClientWidth();
  }

  /**
   * Gets the window's scroll left.
   * 
   * @return window's scroll left
   */
  public static int getScrollLeft() {
    return Document.get().getScrollLeft();
  }

  /**
   * Get the window's scroll top.
   * 
   * @return the window's scroll top
   */
  public static int getScrollTop() {
    return Document.get().getScrollTop();
  }

  /**
   * Gets the browser window's current title.
   * 
   * @return the window's title.
   */
  public static native String getTitle() /*-{
    return $doc.title;
  }-*/;

  /**
   * Moves a window's left and top edge to a specified number of pixels relative
   * to its current coordinates.
   * <p>
   * NOTE: In Chrome, this method only works with windows created by
   * Window.open().
   * </p>
   *
   * @param dx A positive or a negative number that specifies how many pixels
   *          to move the left edge by
   * @param dy A positive or a negative number that specifies how many
   *          pixels to move the top edge by
   */
  public static native void moveBy(int dx, int dy) /*-{
    $wnd.moveBy(dx, dy);
  }-*/;

  /**
   * Moves a window's left and top edge to the specified coordinates.
   * <p>
   * NOTE: In Chrome, this method only works with windows created by
   * Window.open().
   * </p>
   *
   * @param x The left coordinate
   * @param y The top coordinate
   */
  public static native void moveTo(int x, int y) /*-{
    $wnd.moveTo(x, y);
  }-*/;

  /**
   * Opens a new browser window. The "name" and "features" arguments are
   * specified <a href=
   * 'http://developer.mozilla.org/en/docs/DOM:window.open'>here</a>.
   * 
   * @param url the URL that the new window will display
   * @param name the name of the window (e.g. "_blank")
   * @param features the features to be enabled/disabled on this window
   */
  public static native void open(String url, String name, String features) /*-{
    $wnd.open(url, name, features);
  }-*/;

  /**
   * Prints the document in the window, as if the user had issued a "Print"
   * command.
   */
  public static native void print() /*-{
    $wnd.print();
  }-*/;

  /**
   * Displays a request for information in a modal dialog box, along with the
   * standard 'OK' and 'Cancel' buttons.
   * 
   * @param msg the message to be displayed
   * @param initialValue the initial value in the dialog's text field
   * @return the value entered by the user if 'OK' was pressed, or
   *         <code>null</code> if 'Cancel' was pressed
   */
  public static native String prompt(String msg, String initialValue) /*-{
    return $wnd.prompt(msg, initialValue);
  }-*/;

  /**
   * Removes a window closing listener.
   * 
   * @param listener the listener to be removed
   */
  @Deprecated
  public static void removeWindowCloseListener(WindowCloseListener listener) {
    BaseListenerWrapper.WrapWindowClose.remove(handlers, listener);
  }

  /**
   * Removes a window resize listener.
   * 
   * @param listener the listener to be removed
   */
  @Deprecated
  public static void removeWindowResizeListener(WindowResizeListener listener) {
    BaseListenerWrapper.WrapWindowResize.remove(handlers, listener);
  }

  /**
   * Removes a window scroll listener.
   * 
   * @param listener the listener to be removed
   */
  @Deprecated
  public static void removeWindowScrollListener(WindowScrollListener listener) {
    BaseListenerWrapper.WrapWindowScroll.remove(handlers, listener);
  }

  /**
   * Resizes the window by the specified width and height. This method moves the
   * bottom right corner of the window by the specified number of pixels
   * defined. The top left corner will not be moved (it stays in its original
   * coordinates).
   * <p>
   * NOTE: In Chrome, this method only works with windows created by
   * Window.open().
   * </p>
   *
   * @param width A positive or a negative number that specifies how many pixels
   *          to resize the width by
   * @param height A positive or a negative number that specifies how many
   *          pixels to resize the height by
   */
  public static native void resizeBy(int width, int height) /*-{
    $wnd.resizeBy(width, height);
  }-*/;

  /**
   * Resizes the window to the specified width and height.
   * <p>
   * NOTE: In Chrome, this method only works with windows created by
   * Window.open().
   * </p>
   *
   * @param width The width of the window, in pixels
   * @param height The height of the window, in pixels
   */
  public static native void resizeTo(int width, int height) /*-{
    $wnd.resizeTo(width, height);
  }-*/;

  /**
   * Scroll the window to the specified position.
   * 
   * @param left the left scroll position
   * @param top the top scroll position
   */
  public static native void scrollTo(int left, int top) /*-{
    $wnd.scrollTo(left, top);
  }-*/;

  /**
   * Sets the size of the margins used within the window's client area. It is
   * sometimes necessary to do this because some browsers, such as Internet
   * Explorer, add margins by default, which can confound attempts to resize
   * panels to fit exactly within the window.
   * 
   * @param size the window's new margin size, in CSS units.
   */
  public static native void setMargin(String size) /*-{
    $doc.body.style.margin = size;
  }-*/;

  /**
   * Sets the status text for the window, if permitted by the browser's
   * settings.
   *
   * @param status the new message to display.
   */
  public static native void setStatus(String status) /*-{
    $wnd.status = status;
  }-*/;

  /**
   * Sets the browser window's title.
   * 
   * @param title the new window title.
   */
  public static native void setTitle(String title) /*-{
    $doc.title = title;
  }-*/;

  static void onClosed() {
    if (closeHandlersInitialized) {
      CloseEvent.fire(getHandlers(), null);
    }
  }

  static String onClosing() {
    if (closeHandlersInitialized) {
      Window.ClosingEvent event = new Window.ClosingEvent();
      fireEvent(event);
      return event.getMessage();
    }
    return null;
  }

  static void onResize() {
    if (resizeHandlersInitialized) {
      // On webkit and IE we sometimes get duplicate window resize events.
      // Here, we manually filter them.
      int width = getClientWidth();
      int height = getClientHeight();
      if (lastResizeWidth != width || lastResizeHeight != height) {
        lastResizeWidth = width;
        lastResizeHeight = height;
        ResizeEvent.fire(getHandlers(), width, height);
      }
    }
  }

  static void onScroll() {
    if (scrollHandlersInitialized) {
      fireEvent(new Window.ScrollEvent(getScrollLeft(), getScrollTop()));
    }
  }

  /**
   * Adds this handler to the Window.
   * 
   * @param <H> the type of handler to add
   * @param type the event type
   * @param handler the handler
   * @return {@link HandlerRegistration} used to remove the handler
   */
  private static <H extends EventHandler> HandlerRegistration addHandler(
      GwtEvent.Type<H> type, final H handler) {
    return getHandlers().addHandler(type, handler);
  }

  /**
   * Fires an event.
   * 
   * @param event the event
   */
  private static void fireEvent(GwtEvent<?> event) {
    if (handlers != null) {
      handlers.fireEvent(event);
    }
  }

  private static WindowHandlers getHandlers() {
    if (handlers == null) {
      handlers = new WindowHandlers();
    }
    return handlers;
  }

  private static void maybeInitializeCloseHandlers() {
    if (GWT.isClient() && !closeHandlersInitialized) {
      impl.initWindowCloseHandler();
      closeHandlersInitialized = true;
    }
  }

  private static void maybeInitializeResizeHandlers() {
    if (GWT.isClient() && !resizeHandlersInitialized) {
      impl.initWindowResizeHandler();
      resizeHandlersInitialized = true;
    }
  }

  private static void maybeInitializeScrollHandlers() {
    if (GWT.isClient() && !scrollHandlersInitialized) {
      impl.initWindowScrollHandler();
      scrollHandlersInitialized = true;
    }
  }

  private Window() {
  }
}
