package com.asana;

import com.google.api.client.auth.oauth2.*;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;

import java.io.IOException;

public class OAuthApp
{
    public static final String NATIVE_REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob";

    private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
    private static final JsonFactory JSON_FACTORY = new GsonFactory();

    private static final String TOKEN_SERVER_URL = "https://app.asana.com/-/oauth_token";
    private static final String AUTHORIZATION_SERVER_URL = "https://app.asana.com/-/oauth_authorize";

    private String redirectUri;

    private AuthorizationCodeFlow flow;
    public Credential credential;

    public OAuthApp(String apiKey, String apiSecret, String redirectUri)
    {
        this(apiKey, apiSecret, redirectUri, null);
    }

    public OAuthApp(String apiKey, String apiSecret, String redirectUri, String accessToken)
    {
        this(apiKey, apiSecret, redirectUri, accessToken, HTTP_TRANSPORT, JSON_FACTORY);
    }
    
    public OAuthApp(String apiKey, String apiSecret, String redirectUri, String accessToken, HttpTransport transport, JsonFactory jsonFactory)
    {
        this.redirectUri = redirectUri;

        this.flow = new AuthorizationCodeFlow.Builder(
                BearerToken.authorizationHeaderAccessMethod(),
                transport,
                jsonFactory,
                new GenericUrl(TOKEN_SERVER_URL),
                new ClientParametersAuthentication(apiKey, apiSecret),
                apiKey,
                AUTHORIZATION_SERVER_URL
        ).build();

        if (accessToken != null) {
            credential = new Credential(BearerToken.authorizationHeaderAccessMethod())
                    .setAccessToken(accessToken);
        }
    }
    
    
    public boolean isAuthorized()
    {
        return this.credential != null;
    }

    public String getAuthorizationUrl(String state)
    {
        AuthorizationCodeRequestUrl url = this.flow.newAuthorizationUrl();
        if (state != null) {
            url.setState(state);
        }
        url.setRedirectUri(this.redirectUri);
        return url.build();
    }

    public String fetchToken(String code, String userId) throws IOException
    {
        TokenResponse tokenResponse = this.flow.newTokenRequest(code)
                .setRedirectUri(this.redirectUri)
                .execute();
        credential = this.flow.createAndStoreCredential(tokenResponse, userId);
        return credential.getAccessToken();
    }

    public String fetchToken(String code) throws IOException
    {
        return fetchToken(code, null);
    }
}

@@ -579,20 +579,16 @@
 ACTORY =
- new
  GsonFac
@@ -591,16 +591,35 @@
 nFactory
+.getDefaultInstance
 ();%0A%0A   
@@ -1292,65 +1292,146 @@
 ey, 
-String apiSecret, String redirectUri, String accessToken,
+%0A                    String apiSecret,%0A                    String redirectUri,%0A                    String accessToken,%0A                   
  Htt
@@ -1451,16 +1451,36 @@
 ansport,
+%0A                   
  JsonFac
@@ -2102,24 +2102,24 @@
 ;%0A        %7D%0A
+
     %7D%0A    %0A 
@@ -2117,21 +2117,16 @@
  %7D%0A    %0A
-    %0A
     publ

use singleton pattern to access GsonFactory, which is the preferred approach