package io.github.freddyboucher.gwt.oauth2.sample;

import com.google.gwt.core.client.Callback;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import io.github.freddyboucher.gwt.oauth2.client.Auth;
import io.github.freddyboucher.gwt.oauth2.client.AuthRequest;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

public class App implements EntryPoint {

  private static final Oauth2ServiceAsync GREETING_SERVICE = GWT.create(Oauth2Service.class);
  private static final Logger LOGGER = Logger.getLogger(App.class.getName());
  private static final String GOOGLE_CLIENT_ID =
      "521140962557-s8135bi5j7gla15u3qtljvm0geumd55s.apps.googleusercontent.com";
  private static final String FACEBOOK_CLIENT_ID = "916624668730153";
  private static final String INSTAGRAM_CLIENT_ID = "c6bd4c0dd94540a288bdfd388f7edec3";
  private static final String MICROSOFT_CLIENT_ID = "58e9880d-a64f-48d2-9f59-f0cc19fbe536";
  private static final String APPLE_CLIENT_ID = "com.appspot.gwt-oauth2.client";
  private static final String AMAZON_COGNITO_CLIENT_ID = "3uqob948bbcrr09v9gfoppdkh3";

  @Override
  public void onModuleLoad() {
    VerticalPanel panel = new VerticalPanel();
    panel.setSpacing(10);

    panel.add(new Button("Google", (ClickHandler) event -> {
      AuthRequest req =
          new AuthRequest("https", "accounts.google.com", "o/oauth2/auth", GOOGLE_CLIENT_ID)
              .setParameter("scope", "email profile openid");
      Auth.get().login(req, createCallback(), "access_token");
    }));

    panel.add(new Button("Facebook", (ClickHandler) event -> {
      AuthRequest req =
          new AuthRequest("https", "www.facebook.com", "dialog/oauth", FACEBOOK_CLIENT_ID)
              .setParameter("scope", "public_profile,email");
      Auth.get().login(req, createCallback(), "access_token");
    }));

    panel.add(new Button("Instagram", (ClickHandler) event -> {
      AuthRequest req =
          new AuthRequest("https", "api.instagram.com", "oauth/authorize", INSTAGRAM_CLIENT_ID)
              .setParameter("scope", "basic");
      Auth.get().login(req, createCallback(), "access_token");
    }));

    panel.add(new Button("Microsoft", (ClickHandler) event -> {
      AuthRequest req =
          new AuthRequest("https", "login.microsoftonline.com", "common/oauth2/v2.0/authorize/",
              MICROSOFT_CLIENT_ID).setParameter("scope", "email profile openid");
      Auth.get().login(req, createCallback(), "access_token");
    }));

    panel.add(new Button("Apple (no scope)", (ClickHandler) event -> {
      AuthRequest req =
          new AuthRequest("https", "appleid.apple.com", "auth/authorize", APPLE_CLIENT_ID)
              .setParameter("response_type", "code").setParameter("state", "my_custom_state");
      Auth.get().login(req, createCallback(), "code");
    }));

    panel.add(new Button("Apple (name/email scope)", (ClickHandler) event -> {
      AuthRequest req =
          new AuthRequest("https", "appleid.apple.com", "auth/authorize", APPLE_CLIENT_ID)
              .setParameter("scope", "name email").setParameter("response_type", "code")
              .setParameter("state", "my_custom_state").setParameter("response_mode", "form_post")
              .setParameter("redirect_uri", GWT.getModuleBaseURL() + "oauthWindow.jsp");
      Auth.get().login(req, createCallback(), "code");
    }));

    panel.add(new Button("Amazon Cognito", (ClickHandler) event -> {
      AuthRequest req =
          new AuthRequest("https", "gwt-oauth2.auth.us-east-2.amazoncognito.com", "login",
              AMAZON_COGNITO_CLIENT_ID)
              .setParameter("scope", "email").setParameter("response_type", "code");
      Auth.get().login(req, createCallback());
    }));

    Button clearBtn = new Button("Clear All Tokens");
    clearBtn.addClickHandler(event -> Auth.get().clearAllTokens());
    panel.add(clearBtn);

    Anchor privacyPolicy = new Anchor("Privacy Policy");
    privacyPolicy.setHref(
        "https://www.privacypolicygenerator.info/live.php?token=BYr9WP5smDs5lKjfoyjy7XrTGEMcxYtv");
    privacyPolicy.setTarget("_blank");
    panel.add(privacyPolicy);

    RootPanel.get().add(panel);
  }

  private static Callback<Map<String, String>, Throwable> createCallback() {
    return new Callback<Map<String, String>, Throwable>() {
      @Override
      public void onFailure(Throwable throwable) {
        showThrowable(throwable);
      }

      @Override
      public void onSuccess(Map<String, String> result) {
        LOGGER.log(Level.INFO, result.toString());
        DialogBox box = new DialogBox(true, false);
        box.setGlassEnabled(true);
        box.setWidth("700px");
        box.setText("Response");
        Grid grid = new Grid(result.size(), 2);
        grid.getElement().getStyle().setProperty("wordBreak", "break-all");
        for (int i = 0; i < result.size(); i++) {
          Map.Entry<String, String> entry = result.entrySet().stream().skip(i).findFirst()
              .orElseThrow(IllegalStateException::new);
          grid.setText(i, 0, entry.getKey());
          grid.getCellFormatter().setVerticalAlignment(i, 0, HasVerticalAlignment.ALIGN_TOP);
          grid.setText(i, 1, entry.getValue());
        }
        grid.getColumnFormatter().setWidth(0, "200px");
        box.setWidget(grid);
        box.center();
        GREETING_SERVICE.validate(result.get("access_token"), new AsyncCallback<Boolean>() {
          @Override
          public void onFailure(Throwable throwable) {
            showThrowable(throwable);
          }

          @Override
          public void onSuccess(Boolean result) {
            LOGGER.info("Backend validation response: " + result);
          }
        });
      }
    };
  }

  private static void showThrowable(Throwable throwable) {
    LOGGER.log(Level.SEVERE, null, throwable);
    DialogBox box = new DialogBox(true, false);
    box.setGlassEnabled(true);
    box.setText("Error");
    box.setWidget(new Label(throwable.getMessage()));
    box.center();
  }
}

@@ -1341,40 +1341,24 @@
  = %22
-c6bd4c0dd94540a288bdfd388f7edec3
+1159265561099025
 %22;%0A 
@@ -2586,13 +2586,84 @@
 %22, %22
-basic
+user_profile,user_media%22)%0A              .setParameter(%22response_type%22, %22code
 %22);%0A
@@ -2705,36 +2705,28 @@
 allback(), %22
-access_token
+code
 %22);%0A    %7D));

Fix Instagram button