package org.edx.mobile.services;
import android.net.Uri;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.edx.mobile.base.MainApplication;
import org.edx.mobile.http.HttpManager;
import org.edx.mobile.http.HttpRequestDelegate;
import org.edx.mobile.http.HttpRequestEndPoint;
import org.edx.mobile.http.IApi;
import org.edx.mobile.http.OkHttpUtil;
import org.edx.mobile.http.cache.CacheManager;
import org.edx.mobile.interfaces.SectionItemInterface;
import org.edx.mobile.logger.Logger;
import org.edx.mobile.model.Filter;
import org.edx.mobile.model.api.AnnouncementsModel;
import org.edx.mobile.model.api.EnrolledCoursesResponse;
import org.edx.mobile.model.api.HandoutModel;
import org.edx.mobile.model.api.SectionEntry;
import org.edx.mobile.model.api.SyncLastAccessedSubsectionResponse;
import org.edx.mobile.model.api.TranscriptModel;
import org.edx.mobile.model.api.VideoResponseModel;
import org.edx.mobile.model.course.CourseComponent;
import org.edx.mobile.model.course.CourseStructureJsonHandler;
import org.edx.mobile.model.course.CourseStructureV1Model;
import org.edx.mobile.module.prefs.LoginPrefs;
import org.edx.mobile.module.registration.model.RegistrationDescription;
import org.edx.mobile.util.Config;
import java.net.HttpCookie;
import java.util.List;
import java.util.Map;
/**
* This class is introduced to respect normal java application's layer architecture.
* controller -> service -> dao -> data source
* <p/>
* also, api is designed in a way to make future migration to RetroFit easy
* <p/>
* UI layer should call ServiceManager, not IApi directly.
*/
@Singleton
public class ServiceManager {
protected final Logger logger = new Logger(getClass().getName());
private final CacheManager cacheManager;
//TODO - we will move this logic into DI framework
@Inject
Config config;
@Inject
IApi api;
@Inject
LoginPrefs loginPrefs;
public ServiceManager() {
cacheManager = new CacheManager(MainApplication.instance());
}
private HttpRequestEndPoint getEndPointCourseStructure(final String courseId) {
return new HttpRequestEndPoint() {
public String getUrl() {
String url = Uri.parse(config.getApiHostURL() + "/api/courses/v1/blocks/?")
.buildUpon()
.appendQueryParameter("course_id", courseId)
.appendQueryParameter("username", loginPrefs.getUsername())
.appendQueryParameter("depth", "all")
.appendQueryParameter("requested_fields", "graded,format,student_view_multi_device")
.appendQueryParameter("student_view_data", "video,discussion")
.appendQueryParameter("block_counts", "video")
.appendQueryParameter("nav_depth", "3")
.toString();
logger.debug("GET url for enrolling in a Course: " + url);
return url;
}
public String getCacheKey() {
return config.getApiHostURL() + "/api/courses/v1/blocks/?course_id=" + courseId;
}
public Map<String, String> getParameters() {
return null;
}
};
}
public CourseComponent getCourseStructureFromCache(final String courseId) throws Exception {
return getCourseStructure(courseId, OkHttpUtil.REQUEST_CACHE_TYPE.ONLY_CACHE);
}
public CourseComponent getCourseStructure(final String courseId,
OkHttpUtil.REQUEST_CACHE_TYPE requestCacheType) throws Exception {
HttpRequestDelegate<CourseComponent> delegate = new HttpRequestDelegate<CourseComponent>(
api, cacheManager, getEndPointCourseStructure(courseId)) {
@Override
public CourseComponent fromJson(String json) throws Exception {
CourseStructureV1Model model = new CourseStructureJsonHandler().processInput(json);
return (CourseComponent) CourseManager.normalizeCourseStructure(model, courseId);
}
@Override
public HttpManager.HttpResult invokeHttpCall() throws Exception {
return api.getCourseStructure(this);
}
};
return delegate.fetchData(requestCacheType);
}
public List<SectionItemInterface> getLiveOrganizedVideosByChapter(String courseId, final String chapter) throws Exception {
CourseComponent course = this.getCourseStructureFromCache(courseId);
if (course == null) { //it means we cache the old data model in the file system
return api.getLiveOrganizedVideosByChapter(courseId, chapter);
} else {
return CourseManager.mappingAllVideoResponseModelFrom(course, new Filter<VideoResponseModel>() {
@Override
public boolean apply(VideoResponseModel videoResponseModel) {
return videoResponseModel != null && videoResponseModel.getChapterName().equals(chapter);
}
});
}
}
public Map<String, SectionEntry> getCourseHierarchy(String courseId) throws Exception {
CourseComponent course = this.getCourseStructureFromCache(courseId);
if (course == null) { //it means we cache the old data model in the file system
return api.getCourseHierarchy(courseId, true);
} else {
return CourseManager.mappingCourseHierarchyFrom(course);
}
}
public VideoResponseModel getVideoById(String courseId, String videoId)
throws Exception {
CourseComponent course = this.getCourseStructureFromCache(courseId);
if (course == null) { //it means we cache the old data model in the file system
return api.getVideoById(courseId, videoId);
} else {
return CourseManager.getVideoById(course, videoId);
}
}
public TranscriptModel getTranscriptsOfVideo(String enrollmentId,
String videoId) throws Exception {
try {
TranscriptModel transcript;
VideoResponseModel vidModel = getVideoById(enrollmentId, videoId);
if (vidModel != null) {
if (vidModel.getSummary() != null) {
transcript = vidModel.getSummary().getTranscripts();
return transcript;
}
}
} catch (Exception e) {
logger.error(e);
}
return null;
}
public List<EnrolledCoursesResponse> getEnrolledCourses() throws Exception {
return api.getEnrolledCourses();
}
public EnrolledCoursesResponse getCourseById(String courseId) {
return api.getCourseById(courseId);
}
public List<EnrolledCoursesResponse> getEnrolledCourses(boolean fetchFromCache) throws Exception {
return api.getEnrolledCourses(fetchFromCache);
}
public HandoutModel getHandout(String url, boolean fetchFromCache) throws Exception {
return api.getHandout(url, fetchFromCache);
}
public List<AnnouncementsModel> getAnnouncement(String url, boolean preferCache) throws Exception {
return api.getAnnouncement(url, preferCache);
}
public String downloadTranscript(String url) throws Exception {
return api.downloadTranscript(url);
}
public SyncLastAccessedSubsectionResponse syncLastAccessedSubsection(String courseId, String lastVisitedModuleId) throws Exception {
return api.syncLastAccessedSubsection(courseId, lastVisitedModuleId);
}
public SyncLastAccessedSubsectionResponse getLastAccessedSubsection(String courseId) throws Exception {
return api.getLastAccessedSubsection(courseId);
}
public RegistrationDescription getRegistrationDescription() throws Exception {
return api.getRegistrationDescription();
}
public Boolean enrollInACourse(String courseId, boolean email_opt_in) throws Exception {
return api.enrollInACourse(courseId, email_opt_in);
}
public List<HttpCookie> getSessionExchangeCookie() throws Exception {
return api.getSessionExchangeCookie();
}
}