/*
 * Copyright (C) 2011 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.api.gwt.oauth2.client;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.http.client.UrlBuilder;

/**
 * Provides methods to manage authentication flow.
 *
 * @author jasonhall@google.com (Jason Hall)
 */
// TODO(jasonhall): Test this in some way.
public class Auth {

  static {
    register();
  }

  private static native void register() /*-{
    $wnd.doLogin = $entry(function(hash) {
      @com.google.api.gwt.oauth2.client.Auth::finish(Ljava/lang/String;)(hash);
    });
  }-*/;

  /** Whether there is an auth process currently in progress. */
  private static Window window;

  private static LoginCallback callback;

  public static void authenticate(UrlBuilder urlBuilder, LoginCallback callback) {
    urlBuilder.setParameter("redirect_uri", AuthResources.INSTANCE.popupWindow().getUrl());
    urlBuilder.setParameter("response_type", "token");

    if (window != null && window.isOpen()) {
      callback.onFailure(new IllegalStateException("Authentication window is open: in progress"));
    } else {
      Auth.callback = callback;
      window = openWindow(urlBuilder.buildString());
      if (window == null) {
        callback.onFailure(new RuntimeException("The popup appears to have been blocked"));
      }
    }
  }

  static void finish(String hash) {
    String[] parts = hash.substring(1).split("&");
    for (String part : parts) {
      String[] bits = part.split("=");
      if ("access_token".equals(bits[0])) {
        callback.onLogin(bits[1]);
        return;
      }
    }
    callback.onFailure(new RuntimeException("Could not find access_token in hash " + hash));
  }

  // Because GWT's Window.open() method does not return a reference to the
  // newly-opened window, we have to manage this all ourselves manually...
  private static native Window openWindow(String url) /*-{
    return $wnd.open(url, 'popupWindow', 'width=400,height=600');
  }-*/;

  private static final class Window extends JavaScriptObject {

    @SuppressWarnings("unused")
    protected Window() {
    }

    native boolean isOpen() /*-{
      return !this.closed;
    }-*/;
  }
}

@@ -934,16 +934,646 @@
 );%0A  %7D%0A%0A
+  /**%0A   * URL of the popup window that will be redirected to once access has been granted. By default,%0A   * this will be the URL of the popupWindow.html resource defined in %7B@link AuthResources%7D, but can%0A   * be overridden in cases where the GWT script is hosted on another domain from the popup window.%0A   *%0A   * %3Cp%3E%0A   * The popup window *must include* a script element which executes%0A   * %7B@code window.opener.doLogin(location.hash);%7D, and could be copied from the popupWindow.html%0A   * resource, as that is all that page does.%0A   * %3C/p%3E%0A   */%0A  public static String popupUrl = AuthResources.INSTANCE.popupWindow().getUrl();%0A%0A
   privat
@@ -1605,24 +1605,24 @@
 ster() /*-%7B%0A
-
     $wnd.doL
@@ -2020,53 +2020,16 @@
 i%22, 
-AuthResources.INSTANCE.popupWindow().get
+popup
 Url
-()
 );%0A 

Fix OAuth2 flow in embedded Explorer by requiring the OAuth popup to be hosted on the embedding domain