package app.android.gambit.ui;


import android.accounts.Account;
import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.text.TextUtils;
import app.android.gambit.R;
import app.android.gambit.remote.Synchronizer;


class SyncOperator extends AsyncTask<Void, Void, String>
{
	private final Context activityContext;
	private final Activity activity;

	private final Runnable successRunnable;

	private String driveAuthToken;
	private String apiKey;

	private boolean isTokensInvalidationRequired;

	private ProgressDialogShowHelper progressDialogShowHelper;

	public SyncOperator(Context activityContext, Runnable successRunnable) {
		this.activityContext = activityContext;
		this.activity = (Activity) activityContext;

		this.successRunnable = successRunnable;

		isTokensInvalidationRequired = false;
	}

	@Override
	protected void onPreExecute() {
		super.onPreExecute();

		progressDialogShowHelper = new ProgressDialogShowHelper();
		progressDialogShowHelper.show(activityContext, R.string.loading_sync);
	}

	@Override
	protected String doInBackground(Void... params) {
		String authorizationErrorMessage = authorize();
		if (!TextUtils.isEmpty(authorizationErrorMessage)) {
			return authorizationErrorMessage;
		}

		return sync();
	}

	private String authorize() {
		try {
			Account account = getAccount();

			getApiKey();
			getAuthTokens(account);
			if (isTokensInvalidationRequired) {
				invalidateAuthTokens(account);
			}
		}
		catch (SignUpCanceledException e) {
			// Skip sign up cancel, user already knows that he did it
		}
		catch (SignUpFailedException e) {
			return activityContext.getString(R.string.error_unspecified);
		}
		catch (AuthorizationCanceledException e) {
			// Skip revoking auth access, user already knows that he did it
		}
		catch (AuthorizationFailedException e) {
			return activityContext.getString(R.string.error_unspecified);
		}

		return new String();
	}

	private Account getAccount() {
		try {
			return AccountSelector.select(activity);
		}
		catch (NoAccountRegisteredException e) {
			return AccountCreator.create(activity);
		}
	}

	private void getApiKey() {
		apiKey = activity.getString(R.string.google_api_key);
	}

	private void getAuthTokens(Account account) {
		Authorizer authorizer = new Authorizer(activity);

		driveAuthToken = authorizer.getToken(Authorizer.ServiceType.DRIVE, account);
	}

	private void invalidateAuthTokens(Account account) {
		Authorizer authorizer = new Authorizer(activity);

		authorizer.invalidateToken(driveAuthToken);

		getAuthTokens(account);
	}

	private String sync() {
		Synchronizer synchronizer = new Synchronizer(driveAuthToken, apiKey);
		String spreadsheetKey;

		if (!haveSyncSpreadsheetKeyInPreferences()) {
			spreadsheetKey = synchronizer.sync();
		}
		else {
			spreadsheetKey = synchronizer.sync(loadSyncSpreadsheetKeyFromPreferences());
		}

		saveSyncSpreadsheetKeyToPreferences(spreadsheetKey);

		return new String();
	}

	private boolean haveSyncSpreadsheetKeyInPreferences() {
		return !TextUtils.isEmpty(loadSyncSpreadsheetKeyFromPreferences());
	}

	private String loadSyncSpreadsheetKeyFromPreferences() {
		return PreferencesOperator.get(activityContext,
			PreferencesOperator.PREFERENCE_SYNC_SPREADSHEET_KEY);
	}

	private void saveSyncSpreadsheetKeyToPreferences(String syncSpreadsheetKey) {
		PreferencesOperator.set(activityContext, PreferencesOperator.PREFERENCE_SYNC_SPREADSHEET_KEY,
			syncSpreadsheetKey);
	}

	@Override
	protected void onPostExecute(String errorMessage) {
		super.onPostExecute(errorMessage);

		progressDialogShowHelper.hide();

		if (!TextUtils.isEmpty(errorMessage)) {
			UserAlerter.alert(activityContext, errorMessage);
		}
		else {
			successRunnable.run();
		}
	}
}
@@ -209,16 +209,64 @@
 mbit.R;%0A
+import app.android.gambit.remote.SyncException;%0A
 import a
@@ -2661,16 +2661,186 @@
 ync() %7B%0A
+%09%09try %7B%0A%09%09%09trySync();%0A%09%09%7D%0A%09%09catch (SyncException e) %7B%0A%09%09%09return activity.getString(R.string.error_unspecified);%0A%09%09%7D%0A%0A%09%09return new String();%0A%09%7D%0A%0A%09private void trySync() %7B%0A
 %09%09Synchr
@@ -3174,32 +3174,8 @@
 ey);
-%0A%0A%09%09return new String();
 %0A%09%7D%0A

Fix application possible crashes.