package org.edx.mobile.social.google;

import android.accounts.AccountManager;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.os.AsyncTask;

import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.GooglePlayServicesAvailabilityException;
import com.google.android.gms.auth.UserRecoverableAuthException;
import com.google.android.gms.common.AccountPicker;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;

import org.edx.mobile.social.ISocialImpl;

import java.io.IOException;

public class GoogleOauth2 extends ISocialImpl{
    
    private String accessToken;
    private String mEmail; // Received from newChooseAccountIntent(); passed to getToken()
    private static final int REQUEST_AUTHORIZATION = 343;

    
    public GoogleOauth2(Activity activity) {
        super(activity);
    }

    static final int REQUEST_CODE_PICK_ACCOUNT = 1000;


    //TODO - should we merg GoogleApiActivity code with this class?
    /* Client used to interact with Google APIs. */
    private GoogleApiClient mGoogleApiClient;

    private void pickUserAccount() {
        try {
            String[] accountTypes = new String[]{"com.google"};
            Intent intent = AccountPicker.newChooseAccountIntent(null, null,
                    accountTypes, true, null, null, null, null);
            if ( activity == null )
                return;
            // check if play-services are installed
            int result = GooglePlayServicesUtil.isGooglePlayServicesAvailable(activity);
            if (ConnectionResult.SUCCESS == result) {
                activity.startActivityForResult(intent, REQUEST_CODE_PICK_ACCOUNT);
                logger.debug("Launching google account picker ...");
            } else {
                // display user friendly error message
                logger.debug("Play services are missing ...");
                GooglePlayServicesUtil.getErrorDialog(result, activity, 100).show();
            }
        } catch (ActivityNotFoundException ex) {
            logger.debug("Google-play-services are missing? cannot login by google");
        }
    }

    /**
     * Attempts to retrieve the username.
     * If the account is not yet known, invoke the picker. Once the account is known,
     * start an instance of the AsyncTask to get the auth token and do work with it.
     */
    private void getUsername() {
        if (mEmail == null) {
            pickUserAccount();
        } else {
            if ( activity == null )
                return;
            new FetchGoogleTokenTask(activity, mEmail, getScopes()).execute();
        }
    }

    public class FetchGoogleTokenTask extends AsyncTask<Object, Object, Object> {
        Activity mActivity;
        String mScope;
        String mEmail;

        FetchGoogleTokenTask(Activity activity, String name, String scope) {
            this.mActivity = activity;
            this.mScope = scope;
            this.mEmail = name;
        }

        /**
         * Executes the asynchronous job. This runs when you call execute()
         * on the AsyncTask instance.
         */
        @Override
        protected Object doInBackground(Object... params) {
            try {
                String token = fetchToken();
                if (token != null) {
                    // Insert the good stuff here.
                    // Use the token to access the user's Google data.
                    return token;
                }
            } catch (IOException e) {
                // The fetchToken() method handles Google-specific exceptions,
                // so this indicates something went wrong at a higher level.
                // TIP: Check for network connectivity before starting the AsyncTask.
                logger.error(e);
            }
            return null;
        }
        
        @Override
        protected void onPostExecute(Object result) {
            super.onPostExecute(result);
            if (result != null && result instanceof String) {
                accessToken = (String) result;
                logger.debug("Google oauth2: accessToken: " + accessToken);
                if (callback != null) {
                    callback.onLogin(accessToken);
                }
            }
        }

        /**
         * Gets an authentication token from Google and handles any
         * GoogleAuthException that may occur.
         */
        protected String fetchToken() throws IOException {
            if ( activity == null )
                return null;
            try {
                logger.debug("Fetching google oauth2 token ...");
                return GoogleAuthUtil.getToken(activity, mEmail, mScope);
            } catch (UserRecoverableAuthException userRecoverableException) {
                // GooglePlayServices.apk is either old, disabled, or not present
                // so we need to show the user some UI in the activity to recover.
                logger.debug("User recoverable error occurred");
                logger.error(userRecoverableException);
                
                // Requesting an authorization code will always throw
                  // UserRecoverableAuthException on the first call to GoogleAuthUtil.getToken
                  // because the user must consent to offline access to their data.  After
                  // consent is granted control is returned to your activity in onActivityResult
                  // and the second call to GoogleAuthUtil.getToken will succeed.
                
                activity.startActivityForResult(userRecoverableException.getIntent(), REQUEST_AUTHORIZATION);
            } catch (GoogleAuthException fatalException) {
                logger.warn("google auth error occurred");
                // Some other type of unrecoverable exception has occurred.
                // Report and log the error as appropriate for your app.
                logger.error(fatalException);
            }
            return null;
        }
    }
    
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_CODE_PICK_ACCOUNT) {
            // Receiving a result from the AccountPicker
            if (resultCode == Activity.RESULT_OK) {
                mEmail = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
                logger.debug(data.toString());
                // With the account name acquired, go get the auth token
                getUsername();
            } else if (resultCode == Activity.RESULT_CANCELED) {
                // The account picker dialog closed without selecting an account.
                // Notify users that they must pick an account to proceed.
                // Toast.makeText(this, R.string.pick_account, Toast.LENGTH_SHORT).show();
            }
        }
        else if (requestCode == REQUEST_AUTHORIZATION) {
            // after authorization, try to get token again
            if (resultCode == Activity.RESULT_OK) {
                // re-try go get the auth token
                getUsername();
            }
        }
    }

    @Override
    public void login() {
        pickUserAccount();
    }

    @Override
    public void logout() {
        if (accessToken != null) {
            try {
                if ( activity == null )
                    return;
                GoogleAuthUtil.clearToken(activity, accessToken);
                logger.debug("Google logged out");
            } catch (GooglePlayServicesAvailabilityException e) {
                logger.error(e);
            } catch (GoogleAuthException e) {
                logger.error(e);
            } catch (IOException e) {
                logger.error(e);
            }
        }
    }

    public String getEmail(){
        return mEmail;
    }

    private String getScopes() {
        String login = "https://www.googleapis.com/auth/plus.login";

        //TODO-  this scope is deprecated
        String email = "https://www.googleapis.com/auth/userinfo.email";

        
        String scope = "oauth2:" + login + " " + email;
        logger.debug("Scopes= " + scope);
        return scope;
    }
}

@@ -5737,33 +5737,108 @@
                 
-%0A
+if (activity != null && userRecoverableException.getIntent() != null) %7B%0A    
                 
@@ -5931,16 +5931,34 @@
 ATION);%0A
+                %7D%0A
         

Fix null pointer exception