package com.rapidftr.bean;
import android.app.ProgressDialog;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
import com.google.common.base.Throwables;
import com.google.common.io.CharStreams;
import com.rapidftr.RapidFtrApplication;
import com.rapidftr.model.User;
import com.rapidftr.service.FormService;
import com.rapidftr.service.LoginService;
import com.rapidftr.task.MigrateUnverifiedDataToVerified;
import com.rapidftr.utils.http.FluentResponse;
import lombok.Getter;
import lombok.NonNull;
import org.androidannotations.annotations.*;
import org.json.JSONObject;
import java.io.InputStreamReader;
import static com.rapidftr.R.string.*;
import static com.rapidftr.RapidFtrApplication.APP_IDENTIFIER;
@EBean
public class LoginTask {
protected static class LoginException extends RuntimeException {
@Getter protected Integer messageId = null;
public LoginException(String message, Throwable cause) {
super(message, cause);
}
public LoginException(int messageId, Throwable cause) {
super(cause);
this.messageId = messageId;
}
}
@Bean
protected ConnectivityBean connectivityBean;
@App
protected RapidFtrApplication application;
@RootContext
protected Context activity;
protected ProgressDialog progressDialog;
public void login(String userName, String password, String url) {
createProgressDialog();
if (!loginOnline(userName, password, url)) {
loginOffline(userName, password);
}
dismissProgressDialog();
}
protected boolean loginOnline(String userName, String password, String url) {
try {
notifyProgress(login_online_progress);
User user = loadOnline(userName, password, url);
migrateIfVerified(user);
cacheForOffline(user);
loadFormSections();
notifyToast(login_online_success);
return true;
} catch (LoginException e) {
Log.e(APP_IDENTIFIER, "Failed to login online", e);
notifyToast(e);
return false;
}
}
protected boolean loginOffline(String userName, String password) {
try {
notifyProgress(login_offline_progress);
User user = loadOffline(userName, password);
cacheForOffline(user);
notifyToast(login_offline_success);
return true;
} catch (LoginException e) {
Log.e(APP_IDENTIFIER, "Failed to login offline", e);
notifyToast(e);
return false;
}
}
protected User loadOnline(String userName, String password, String url) {
if (!connectivityBean.isOnline()) {
throw new LoginException(login_online_no_connectivity, null);
}
try {
FluentResponse response = new LoginService().login(application, userName, password, url);
String responseAsString = CharStreams.toString(new InputStreamReader(response.getEntity().getContent()));
if (!response.isSuccess()) {
throw new LoginException(responseAsString, null);
}
return new User(userName, password, true, url).read(responseAsString);
} catch (Exception e) {
Throwables.propagateIfInstanceOf(e, LoginException.class);
throw new LoginException(login_online_failed, null);
}
}
protected User loadOffline(String userName, String password) {
User user = new User(userName, password);
if (!user.exists()) {
throw new LoginException(login_offline_no_user, null);
}
try {
return user.load();
} catch(Exception e) {
throw new LoginException(login_offline_failed, e);
}
}
protected void migrateIfVerified(@NonNull User onlineUser) {
User offlineUser = null;
try {
offlineUser = loadOffline(onlineUser.getUserName(), onlineUser.getPassword());
} catch (LoginException e) {
return;
}
if (offlineUser != null && onlineUser.isVerified() && !offlineUser.isVerified()) {
try {
notifyProgress(login_migrate_progress);
new MigrateUnverifiedDataToVerified(new JSONObject(onlineUser.asJSON()), offlineUser, application).execute();
} catch (Exception e) {
throw new LoginException(login_migrate_failed, null);
}
}
}
protected void cacheForOffline(@NonNull User user) {
try {
user.save();
application.setCurrentUser(user);
} catch (Exception e) {
throw new LoginException(login_save_failed, e);
}
}
protected void loadFormSections() {
try {
notifyProgress(login_form_progress);
new FormService(application).downloadPublishedFormSections();
} catch (Exception e) {
throw new LoginException(login_form_failed, e);
}
}
@UiThread
protected void createProgressDialog() {
progressDialog = new ProgressDialog(activity);
progressDialog.setIndeterminate(true);
progressDialog.setCancelable(false);
progressDialog.show();
}
@UiThread
protected void dismissProgressDialog() {
progressDialog.dismiss();
}
@UiThread
public void notifyProgress(Integer message) {
progressDialog.setMessage(application.getString(message));
}
@UiThread
public void notifyToast(LoginException e) {
if (e.getMessageId() != null) {
notifyToast(e.getMessageId());
} else {
Toast.makeText(application, e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
@UiThread
public void notifyToast(int message) {
Toast.makeText(application, message, Toast.LENGTH_SHORT).show();
}
}