package org.anhonesteffort.flock;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import org.anhonesteffort.flock.auth.DavAccount;
import org.anhonesteffort.flock.crypto.KeyUtil;
import org.anhonesteffort.flock.registration.RegistrationApi;
import org.anhonesteffort.flock.registration.RegistrationApiException;
import org.anhonesteffort.flock.registration.ResourceAlreadyExistsException;
import org.anhonesteffort.flock.sync.OwsWebDav;
import org.anhonesteffort.flock.sync.addressbook.AddressbookSyncScheduler;
import org.anhonesteffort.flock.sync.addressbook.LocalAddressbookStore;
import org.anhonesteffort.flock.sync.calendar.CalendarsSyncScheduler;
import org.anhonesteffort.flock.sync.key.DavKeyStore;
import org.anhonesteffort.flock.webdav.PropertyParseException;
import org.anhonesteffort.flock.webdav.caldav.CalDavCollection;
import org.anhonesteffort.flock.webdav.caldav.CalDavStore;
import org.apache.jackrabbit.webdav.DavException;
import java.io.IOException;
import java.security.GeneralSecurityException;
import javax.net.ssl.SSLException;
/**
* Created by rhodey
*/
public class RegisterAccountService extends ImportAccountService {
private static final String TAG = "org.anhonesteffort.flock.RegisterAccountService";
private static final String KEY_INTENT = "RegisterAccountService.KEY_INTENT";
protected static final String KEY_MESSENGER = "RegisterAccountService.KEY_MESSENGER";
protected static final String KEY_ACCOUNT_ID = "RegisterAccountService.KEY_ACCOUNT_ID";
protected static final String KEY_MASTER_PASSPHRASE = "RegisterAccountService.KEY_OLD_MASTER_PASSPHRASE";
private Looper serviceLooper;
private ServiceHandler serviceHandler;
private NotificationManager notifyManager;
private NotificationCompat.Builder notificationBuilder;
private Messenger messenger;
private String accountId;
private String masterPassphrase;
private DavAccount registerAcount;
private int resultCode;
private boolean remoteActivityIsAlive = true;
private boolean accountWasImported = false;
private void handleInitializeNotification() {
Log.d(TAG, "handleInitializeNotification()");
notificationBuilder.setContentTitle(getString(R.string.title_register_account))
.setContentText(getString(R.string.registering_account))
.setProgress(0, 0, true)
.setSmallIcon(R.drawable.flock_actionbar_icon);
startForeground(9005, notificationBuilder.build());
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy()");
if (remoteActivityIsAlive || resultCode == ErrorToaster.CODE_SUCCESS)
return;
Bundle errorBundler = new Bundle();
errorBundler.putInt(ErrorToaster.KEY_STATUS_CODE, resultCode);
ErrorToaster.handleDisplayToastBundledError(getBaseContext(), errorBundler);
if (accountWasImported) {
notificationBuilder
.setProgress(0, 0, false)
.setContentText(getString(R.string.account_import_completed_with_errors));
}
else {
notificationBuilder
.setProgress(0, 0, false)
.setContentText(getString(R.string.account_register_failed));
}
notifyManager.notify(9005, notificationBuilder.build());
}
private void handleImportComplete() {
Log.d(TAG, "handleImportComplete()");
if (remoteActivityIsAlive || resultCode == ErrorToaster.CODE_SUCCESS)
stopForeground(true);
else
stopForeground(false);
stopSelf();
}
private void handleRegisterAccount(Bundle result) {
Log.d(TAG, "handleRegisterAccount()");
try {
String authToken = KeyUtil.getAuthTokenForPassphrase(masterPassphrase);
RegistrationApi registrationApi = new RegistrationApi(getBaseContext());
registerAcount = new DavAccount(accountId, authToken, OwsWebDav.HREF_WEBDAV_HOST);
registrationApi.createAccount(registerAcount);
result.putInt(ErrorToaster.KEY_STATUS_CODE, ErrorToaster.CODE_SUCCESS);
} catch (ResourceAlreadyExistsException e) {
result.putInt(ErrorToaster.KEY_STATUS_CODE, ErrorToaster.CODE_ACCOUNT_ID_TAKEN);
} catch (RegistrationApiException e) {
ErrorToaster.handleBundleError(e, result);
} catch (IOException e) {
ErrorToaster.handleBundleError(e, result);
} catch (GeneralSecurityException e) {
ErrorToaster.handleBundleError(e, result);
}
}
private void handleImportAddressbook() {
LocalAddressbookStore localStore = new LocalAddressbookStore(getBaseContext(), registerAcount);
String remotePath = OwsWebDav.getAddressbookPathForUsername(registerAcount.getUserId());
String displayName = getString(R.string.addressbook);
if (localStore.getCollections().size() == 0) {
localStore.addCollection(remotePath, displayName);
new AddressbookSyncScheduler(getBaseContext()).requestSync();
}
}
private void handleDeleteDefaultCalendars(Bundle result) {
try {
CalDavStore store = DavAccountHelper.getCalDavStore(getBaseContext(), registerAcount);
for (CalDavCollection collection : store.getCollections()) {
if (!collection.getPath().contains(DavKeyStore.PATH_KEY_COLLECTION)) {
Log.d(TAG, "deleting default calendar " + collection.getPath());
store.removeCollection(collection.getPath());
}
}
store.closeHttpConnection();
new CalendarsSyncScheduler(getBaseContext()).requestSync();
result.putInt(ErrorToaster.KEY_STATUS_CODE, ErrorToaster.CODE_SUCCESS);
} catch (PropertyParseException e) {
ErrorToaster.handleBundleError(e, result);
} catch (DavException e) {
ErrorToaster.handleBundleError(e, result);
} catch (SSLException e) {
ErrorToaster.handleBundleError(e, result);
} catch (IOException e) {
ErrorToaster.handleBundleError(e, result);
}
}
private void handleRevertRegisterAccount(Bundle result) {
Log.w(TAG, "handleRevertRegisterAccount()");
int statusSave = result.getInt(ErrorToaster.KEY_STATUS_CODE);
try {
new RegistrationApi(getBaseContext()).deleteAccount(registerAcount);
result.putInt(ErrorToaster.KEY_STATUS_CODE, ErrorToaster.CODE_SUCCESS);
} catch (ResourceAlreadyExistsException e) {
result.putInt(ErrorToaster.KEY_STATUS_CODE, ErrorToaster.CODE_ACCOUNT_ID_TAKEN);
} catch (RegistrationApiException e) {
ErrorToaster.handleBundleError(e, result);
} catch (IOException e) {
ErrorToaster.handleBundleError(e, result);
}
if (result.getInt(ErrorToaster.KEY_STATUS_CODE) != ErrorToaster.CODE_SUCCESS)
Log.e(TAG, "unable to revert registed account!!! XXX :(");
result.putInt(ErrorToaster.KEY_STATUS_CODE, statusSave);
}
private void handleUiCallbackAccountImported() {
Log.d(TAG, "handleUiCallbackAccountImported()");
Message message = Message.obtain();
message.arg1 = RegisterAccountFragment.CODE_ACCOUNT_IMPORTED;
try {
messenger.send(message);
} catch (RemoteException e) {
Log.e(TAG, "caught exception while sending message to activity >> ", e);
remoteActivityIsAlive = false;
}
}
private void handleStartRegisterAccount() {
Log.d(TAG, "handleStartRegisterAccount()");
Bundle result = new Bundle();
handleInitializeNotification();
handleRegisterAccount(result);
if (result.getInt(ErrorToaster.KEY_STATUS_CODE) == ErrorToaster.CODE_SUCCESS) {
handleImportAccount(result, registerAcount, masterPassphrase);
if (result.getInt(ErrorToaster.KEY_STATUS_CODE) == ErrorToaster.CODE_SUCCESS) {
accountWasImported = true;
handleUiCallbackAccountImported();
handleImportAddressbook();
handleDeleteDefaultCalendars(result);
}
else
handleRevertRegisterAccount(result);
}
Message message = Message.obtain();
message.arg1 = result.getInt(ErrorToaster.KEY_STATUS_CODE);
resultCode = result.getInt(ErrorToaster.KEY_STATUS_CODE);
try {
if (!accountWasImported)
messenger.send(message);
} catch (RemoteException e) {
Log.e(TAG, "caught exception while sending message to activity >> ", e);
remoteActivityIsAlive = false;
}
handleImportComplete();
}
@Override
public void onCreate() {
HandlerThread thread = new HandlerThread("RegisterAccountService", HandlerThread.NORM_PRIORITY);
thread.start();
serviceLooper = thread.getLooper();
serviceHandler = new ServiceHandler(serviceLooper);
notifyManager = (NotificationManager)getBaseContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationBuilder = new NotificationCompat.Builder(getBaseContext());
}
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
Log.d(TAG, "handleMessage()");
Intent intent = msg.getData().getParcelable(KEY_INTENT);
if (intent != null) {
if (intent.getExtras() != null &&
intent.getExtras().get(KEY_MESSENGER) != null &&
intent.getExtras().getString(KEY_ACCOUNT_ID) != null &&
intent.getExtras().getString(KEY_MASTER_PASSPHRASE) != null)
{
messenger = (Messenger) intent.getExtras().get(KEY_MESSENGER);
accountId = intent.getExtras().getString(KEY_ACCOUNT_ID);
masterPassphrase = intent.getExtras().getString(KEY_MASTER_PASSPHRASE);
handleStartRegisterAccount();
}
else
Log.e(TAG, "received intent without messenger, account id or master passphrase");
}
else
Log.e(TAG, "received message with null intent");
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Message msg = serviceHandler.obtainMessage();
msg.getData().putParcelable(KEY_INTENT, intent);
serviceHandler.sendMessage(msg);
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind()");
return null;
}
}