package org.edx.mobile.services;
import android.content.Context;
import android.content.SharedPreferences;
import android.support.annotation.NonNull;
import android.view.View;
import org.edx.mobile.base.MainApplication;
import org.edx.mobile.logger.Logger;
import org.edx.mobile.model.api.SyncLastAccessedSubsectionResponse;
import org.edx.mobile.module.prefs.LoginPrefs;
import org.edx.mobile.task.GetLastAccessedTask;
import org.edx.mobile.task.SyncLastAccessedTask;
import org.edx.mobile.util.DateUtil;
import org.edx.mobile.util.Sha1Util;
import javax.inject.Inject;
import javax.inject.Singleton;
@Singleton
public class LastAccessManager {
public interface LastAccessManagerCallback {
boolean isFetchingLastAccessed();
void setFetchingLastAccessed(boolean accessed);
void showLastAccessedView(String lastAccessedSubSectionId, String courseId, View view);
}
protected final Logger logger = new Logger(getClass().getName());
@NonNull
private final LoginPrefs loginPrefs;
@Inject
public LastAccessManager(@NonNull LoginPrefs loginPrefs) {
this.loginPrefs = loginPrefs;
}
public void fetchLastAccessed(final LastAccessManagerCallback callback, final String courseId) {
fetchLastAccessed(callback, null, courseId);
}
public void fetchLastAccessed(final LastAccessManagerCallback callback, final View view, final String courseId) {
try {
if (!callback.isFetchingLastAccessed()) {
final String username = loginPrefs.getUsername();
if (courseId != null && username != null) {
final LastAccessedPrefManager prefManager = new LastAccessedPrefManager(MainApplication.instance(), username, courseId);
final String prefModuleId = prefManager.getLastAccessedSubsectionId();
logger.debug("Last Accessed Module ID from Preferences "
+ prefModuleId);
callback.showLastAccessedView(prefModuleId, courseId, view);
GetLastAccessedTask getLastAccessedTask = new GetLastAccessedTask(MainApplication.instance(), courseId) {
@Override
public void onSuccess(SyncLastAccessedSubsectionResponse result) {
syncWithServerOnSuccess(result, prefModuleId, prefManager, courseId, callback, view);
}
@Override
public void onException(Exception ex) {
super.onException(ex);
callback.setFetchingLastAccessed(false);
}
};
callback.setFetchingLastAccessed(true);
getLastAccessedTask.execute();
}
}
} catch (Exception e) {
logger.error(e);
}
}
private void syncWithServerOnSuccess(SyncLastAccessedSubsectionResponse result,
String prefModuleId,
LastAccessedPrefManager prefManager,
String courseId,
LastAccessManagerCallback callback,
View view
) {
String server_moduleId;
if (result != null && result.getLastVisitedModuleId() != null) {
//Handle the last Visited Module received from Sever
server_moduleId = result.getLastVisitedModuleId();
logger.debug("Last Accessed Module ID from Server Get "
+ server_moduleId);
if (prefManager.isSyncedLastAccessedSubsection()) {
//If preference last accessed flag is true, put the last access fetched
//from server in Preferences and display it on Last Accessed.
prefManager.putLastAccessedSubsection(server_moduleId, true);
callback.showLastAccessedView(server_moduleId, courseId, view);
} else {
//Preference's last accessed is not synced with server,
//Sync with server and display the result from server on UI.
if (prefModuleId != null && prefModuleId.length() > 0) {
syncLastAccessedWithServer(prefManager, view, prefModuleId, courseId, callback);
}
}
} else {
//There is no Last Accessed module on the server
if (prefModuleId != null && prefModuleId.length() > 0) {
syncLastAccessedWithServer(prefManager, view, prefModuleId, courseId, callback);
}
}
callback.setFetchingLastAccessed(false);
}
private void syncLastAccessedWithServer(final LastAccessedPrefManager prefManager,
final View view,
String prefModuleId,
final String courseId,
final LastAccessManagerCallback callback) {
try {
SyncLastAccessedTask syncLastAccessTask = new SyncLastAccessedTask(
MainApplication.instance(), courseId, prefModuleId) {
@Override
public void onSuccess(SyncLastAccessedSubsectionResponse result) {
if (result != null && result.getLastVisitedModuleId() != null) {
prefManager.putLastAccessedSubsection(result.getLastVisitedModuleId(), true);
logger.debug("Last Accessed Module ID from Server Sync "
+ result.getLastVisitedModuleId());
callback.showLastAccessedView(result.getLastVisitedModuleId(), courseId, view);
}
}
};
syncLastAccessTask.execute();
} catch (Exception e) {
logger.error(e);
}
}
public void setLastAccessed(@NonNull String courseId, @NonNull String subsectionId) {
new LastAccessedPrefManager(MainApplication.instance(), loginPrefs.getUsername(), courseId)
.putLastAccessedSubsection(subsectionId, false);
}
private static class LastAccessedPrefManager {
// Preference keys
private static final String LAST_ACCESS_MODIFICATION_TIME = "last_access_modification_time";
private static final String LAST_ACCESSED_MODULE_ID = "last_access_module_id";
private static final String LAST_ACCESSED_SYNCED_FLAG = "lastaccess_synced_flag";
@NonNull
private final Context context;
@NonNull
private final String prefName;
public LastAccessedPrefManager(@NonNull Context context, @NonNull String username, @NonNull String courseId) {
this.context = context;
this.prefName = getPrefNameForLastAccessedBy(username, courseId);
}
/**
* Stores information of last accesses subsection for given id.
* Modification date is also stored for current time.
* Synced is marked as FALSE.
*/
public void putLastAccessedSubsection(String subsectionId, boolean lastAccessedFlag) {
SharedPreferences.Editor edit = context.getSharedPreferences(prefName, Context.MODE_PRIVATE).edit();
edit.putString(LAST_ACCESSED_MODULE_ID, subsectionId);
edit.putString(LAST_ACCESS_MODIFICATION_TIME, DateUtil.getCurrentTimeStamp());
edit.putBoolean(LAST_ACCESSED_SYNCED_FLAG, lastAccessedFlag);
edit.commit();
}
/**
* @return true if given courseId's last access is synced with server, false otherwise.
*/
public boolean isSyncedLastAccessedSubsection() {
return context.getSharedPreferences(prefName, Context.MODE_PRIVATE)
.getBoolean(LAST_ACCESSED_SYNCED_FLAG, true);
}
/**
* @return last accessed subsection id for the given course.
*/
public String getLastAccessedSubsectionId() {
return context.getSharedPreferences(prefName, Context.MODE_PRIVATE)
.getString(LAST_ACCESSED_MODULE_ID, null);
}
}
/**
* @return preference file name that can be used to store information about last accessed subsection.
* This preference file name is SHA1 hash of a combination of username, courseId and a constant suffix.
*/
private static String getPrefNameForLastAccessedBy(@NonNull String username, @NonNull String courseId) {
try {
return Sha1Util.SHA1(username + "-" + courseId + "-last-accessed-subsection_info");
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}