package com.vaguehope.onosendai.ui.pref;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import org.json.JSONException;
import twitter4j.Twitter;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;
import twitter4j.conf.Configuration;
import twitter4j.conf.ConfigurationBuilder;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import com.vaguehope.onosendai.config.Account;
import com.vaguehope.onosendai.config.AccountProvider;
import com.vaguehope.onosendai.provider.twitter.TwitterOauth;
import com.vaguehope.onosendai.util.DialogHelper;
import com.vaguehope.onosendai.util.LogWrapper;
import com.vaguehope.onosendai.util.Result;
public class TwitterOauthWizard {
private static final LogWrapper LOG = new LogWrapper("TOW");
private final Context context;
private final TwitterOauthHelper helperCallback;
private Configuration twitterConfiguration;
private RequestToken requestToken;
public interface TwitterOauthHelper {
void deligateStartActivityForResult (Intent intent, int requestCode);
}
public interface TwitterOauthComplete {
String getAccountId ();
void onAccount (Account account, String screenName) throws JSONException;
}
private final AtomicInteger requestCodeCounter = new AtomicInteger(100);
private final Map<Integer, TwitterOauthComplete> completeCallbacks = new ConcurrentHashMap<Integer, TwitterOauthWizard.TwitterOauthComplete>();
private final ConcurrentMap<Integer, Twitter> twitters = new ConcurrentHashMap<Integer, Twitter>();
public TwitterOauthWizard (final Context context, final TwitterOauthHelper helperCallback) {
this.context = context;
this.helperCallback = helperCallback;
}
public void start (final TwitterOauthComplete completeCallback) {
final int requestCode = Integer.valueOf(this.requestCodeCounter.incrementAndGet());
this.completeCallbacks.put(requestCode, completeCallback);
new TwitterOauthInitTask(this, requestCode).execute();
}
protected static LogWrapper getLog () {
return LOG;
}
protected Context getContext () {
return this.context;
}
public TwitterOauthHelper getHelperCallback () {
return this.helperCallback;
}
private Configuration getTwitterConfiguration () {
if (this.twitterConfiguration == null) {
final ConfigurationBuilder builder = new ConfigurationBuilder();
builder.setOAuthConsumerKey(TwitterOauth.getConsumerKey());
builder.setOAuthConsumerSecret(TwitterOauth.getConsumerSecret());
this.twitterConfiguration = builder.build();
}
return this.twitterConfiguration;
}
private Twitter makeTwitter () {
final TwitterFactory factory = new TwitterFactory(getTwitterConfiguration());
return factory.getInstance();
}
protected Twitter getTwitter (final int requestCode) {
final Twitter existingT = this.twitters.get(Integer.valueOf(requestCode));
if (existingT != null) return existingT;
final Twitter newT = makeTwitter();
this.twitters.putIfAbsent(requestCode, newT);
return this.twitters.get(Integer.valueOf(requestCode));
}
protected void stashRequestToken (final RequestToken token) {
if (this.requestToken != null) throw new IllegalStateException("Request token alrady stashed.");
if (token == null) throw new IllegalStateException("Can not stash a null token.");
this.requestToken = token;
}
protected RequestToken unstashRequestToken () {
if (this.requestToken == null) throw new IllegalStateException("Request token has not been stashed.");
final RequestToken token = this.requestToken;
this.requestToken = null;
return token;
}
private static class TwitterOauthInitTask extends AsyncTask<Void, Void, Result<RequestToken>> {
private final TwitterOauthWizard host;
private final Integer requestCode;
private ProgressDialog dialog;
public TwitterOauthInitTask (final TwitterOauthWizard host, final Integer requestCode) {
this.host = host;
this.requestCode = requestCode;
}
@Override
protected void onPreExecute () {
this.dialog = ProgressDialog.show(this.host.getContext(), "Onosendai", "Starting Oauth...", true); //ES
}
@Override
protected Result<RequestToken> doInBackground (final Void... params) {
try {
return new Result<RequestToken>(this.host.getTwitter(this.requestCode).getOAuthRequestToken(TwitterOauth.CALLBACK_URL));
}
catch (final Exception e) { // NOSONAR report all errors to user.
return new Result<RequestToken>(e);
}
}
@Override
protected void onPostExecute (final Result<RequestToken> result) {
this.dialog.dismiss();
if (result.isSuccess()) {
final Intent intent = new Intent(this.host.getContext(), TwitterLoginActivity.class);
final RequestToken requtestToken = result.getData();
this.host.stashRequestToken(requtestToken);
intent.putExtra(TwitterOauth.IEXTRA_AUTH_URL, requtestToken.getAuthorizationURL());
this.host.getHelperCallback().deligateStartActivityForResult(intent, this.requestCode);
}
else {
getLog().e("Failed to init OAuth.", result.getE());
DialogHelper.alert(this.host.getContext(), result.getE());
}
}
}
public void onActivityResult (final int requestCode, final int resultCode, final Intent intent) {
LOG.d("onActivityResult(%d, %d, %s)", requestCode, resultCode, intent);
final TwitterOauthComplete completeCallback = this.completeCallbacks.get(Integer.valueOf(requestCode));
if (completeCallback != null) {
if (resultCode == Activity.RESULT_OK) {
final String oauthVerifier = intent.getExtras().getString(TwitterOauth.IEXTRA_OAUTH_VERIFIER);
new TwitterOauthPostTask(this, requestCode, oauthVerifier, completeCallback).execute();
}
else if (resultCode == Activity.RESULT_CANCELED) {
DialogHelper.alert(getContext(), "Twitter auth canceled."); //ES
}
}
}
private static class TwitterOauthPostTask extends AsyncTask<Void, Void, Result<AccessToken>> {
private final TwitterOauthWizard host;
private final int requestCode;
private final String oauthVerifier;
private final TwitterOauthComplete completeCallback;
private ProgressDialog dialog;
public TwitterOauthPostTask (final TwitterOauthWizard host, final int requestCode, final String oauthVerifier, final TwitterOauthComplete completeCallback) {
this.host = host;
this.requestCode = requestCode;
this.oauthVerifier = oauthVerifier;
this.completeCallback = completeCallback;
}
@Override
protected void onPreExecute () {
this.dialog = ProgressDialog.show(this.host.getContext(), "Onosendai", "Completing Oauth...", true); //ES
}
@Override
protected Result<AccessToken> doInBackground (final Void... params) {
try {
final RequestToken token = this.host.unstashRequestToken();
return new Result<AccessToken>(this.host.getTwitter(this.requestCode).getOAuthAccessToken(token, this.oauthVerifier));
}
catch (final Exception e) { // NOSONAR report all errors to user.
return new Result<AccessToken>(e);
}
}
@Override
protected void onPostExecute (final Result<AccessToken> result) {
this.dialog.dismiss();
if (result.isSuccess()) {
this.host.onGotTwitterAccessToken(result.getData(), this.completeCallback);
}
else {
getLog().e("Failed to complete OAuth.", result.getE());
DialogHelper.alert(this.host.getContext(), result.getE());
}
}
}
protected void onGotTwitterAccessToken (final AccessToken accessToken, final TwitterOauthComplete completeCallback) {
try {
LOG.i("Account authorised %s.", accessToken.getScreenName());
final Account account = new Account(completeCallback.getAccountId(), accessToken.getScreenName(), AccountProvider.TWITTER,
getTwitterConfiguration().getOAuthConsumerKey(), getTwitterConfiguration().getOAuthConsumerSecret(),
accessToken.getToken(), accessToken.getTokenSecret());
completeCallback.onAccount(account, accessToken.getScreenName());
}
catch (final Exception e) { // NOSONAR want to show any errors to the user.
LOG.e("Failed to write new Twitter account.", e);
DialogHelper.alert(getContext(), e);
}
}
}