package kornell.gui.client;
import java.util.Date;
import java.util.logging.Logger;
import com.github.gwtbootstrap.client.ui.constants.AlertType;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.place.shared.Place;
import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.place.shared.PlaceHistoryHandler;
import com.google.gwt.place.shared.PlaceHistoryHandler.DefaultHistorian;
import com.google.gwt.user.client.Window;
import com.google.web.bindery.event.shared.EventBus;
import com.google.web.bindery.event.shared.SimpleEventBus;
import kornell.api.client.Callback;
import kornell.api.client.KornellSession;
import kornell.core.entity.Enrollment;
import kornell.core.entity.EnrollmentState;
import kornell.core.entity.EntityFactory;
import kornell.core.entity.Institution;
import kornell.core.entity.InstitutionType;
import kornell.core.error.KornellErrorTO;
import kornell.core.event.EventFactory;
import kornell.core.lom.LOMFactory;
import kornell.core.to.CourseClassTO;
import kornell.core.to.CourseClassesTO;
import kornell.core.to.TOFactory;
import kornell.core.to.UserHelloTO;
import kornell.core.to.UserInfoTO;
import kornell.gui.client.event.CourseClassesFetchedEvent;
import kornell.gui.client.mvp.AsyncActivityManager;
import kornell.gui.client.mvp.AsyncActivityMapper;
import kornell.gui.client.mvp.GlobalActivityMapper;
import kornell.gui.client.mvp.HistoryMapper;
import kornell.gui.client.personnel.Captain;
import kornell.gui.client.personnel.Dean;
import kornell.gui.client.personnel.MrPostman;
import kornell.gui.client.personnel.Stalker;
import kornell.gui.client.presentation.admin.courseclass.courseclasses.AdminCourseClassesPlace;
import kornell.gui.client.presentation.classroom.ClassroomPlace;
import kornell.gui.client.presentation.vitrine.VitrinePlace;
import kornell.gui.client.presentation.welcome.WelcomePlace;
import kornell.gui.client.util.ClientProperties;
import kornell.gui.client.util.view.KornellMaintenance;
import kornell.gui.client.util.view.KornellNotification;
//TODO: Organize this big, messy class and interface
public class GenericClientFactoryImpl implements ClientFactory {
Logger logger = Logger.getLogger(GenericClientFactoryImpl.class.getName());
private static KornellConstants constants = GWT.create(KornellConstants.class);
public static final EntityFactory ENTITY_FACTORY = GWT.create(EntityFactory.class);
public static final TOFactory TO_FACTORY = GWT.create(TOFactory.class);
public static final LOMFactory LOM_FACTORY = GWT.create(LOMFactory.class);
public static final EventFactory EVENT_FACTORY = GWT.create(EventFactory.class);
public static final EventBus EVENT_BUS = GWT.create(SimpleEventBus.class);
public static final KornellSession KORNELL_SESSION = GWT.create(KornellSession.class);
/* History Management */
private final PlaceController placeCtrl = new PlaceController(EVENT_BUS);
private final HistoryMapper historyMapper = GWT.create(HistoryMapper.class);
private final DefaultHistorian historian = GWT.create(DefaultHistorian.class);
private final PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(historyMapper);
/* GUI */
private ViewFactory viewFactory;
private Place defaultPlace;
private Place homePlace;
public GenericClientFactoryImpl() {
}
private void initActivityManagers() {
initGlobalActivityManager();
}
private void initGlobalActivityManager() {
AsyncActivityMapper activityMapper = new GlobalActivityMapper(this);
AsyncActivityManager activityManager = new AsyncActivityManager(activityMapper, EVENT_BUS);
activityManager.setDisplay(viewFactory.getShell());
}
private void initHistoryHandler(Place defaultPlace) {
// AppPlaceHistoryMapper historyMapper = GWT.create(AppPlaceHistoryMapper.class);
// PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(historyMapper);
// historyHandler.register(placeController, eventBus, defaultPlace);
historyHandler.register(placeCtrl, EVENT_BUS, defaultPlace);
// sessions that arent authenticated, go to the default place
// except if it's a vitrineplace, then let the history take care of it
if (!KORNELL_SESSION.isAuthenticated() && historian.getToken().indexOf("vitrine") == -1) {
placeCtrl.goTo(defaultPlace);
}
historyHandler.handleCurrentHistory();
}
@Override
public void startApp() {
final String institutionParam = Window.Location.getParameter("institution");
// remove token cookie on page load
final String windowHostName = Window.Location.getHostName();
final Callback<UserHelloTO> userHelloCallback = new Callback<UserHelloTO>() {
@Override
public void ok(final UserHelloTO userHelloTO) {
doCallbackOk(userHelloTO);
}
@Override
public void unauthorized(KornellErrorTO kornellErrorTO) {
// this case means someone entered a URL in the bar with an
// expired token in local storage
// so we clear his old token and we do the call to hello again
ClientProperties.remove(ClientProperties.X_KNL_TOKEN);
ClientProperties.removeCookie(ClientProperties.X_KNL_TOKEN);
final Callback<UserHelloTO> userManualAccessCallback = new Callback<UserHelloTO>() {
@Override
public void ok(final UserHelloTO userHelloTO) {
doCallbackOk(userHelloTO);
}
};
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
String institution = institutionParam;
String hostName = windowHostName;
KORNELL_SESSION.user().getUserHello(institution,
hostName, userManualAccessCallback);
}
});
}
@Override
public void internalServerError(KornellErrorTO kornellErrorTO) {
KornellMaintenance.show();
}
@Override
public void notFound(KornellErrorTO kornellErrorTO) {
KornellMaintenance.show();
}
@Override
public void serviceUnavailable() {
KornellMaintenance.show();
}
private void doCallbackOk(final UserHelloTO userHelloTO) {
Institution institution = userHelloTO.getInstitution();
if (institution == null) {
KornellNotification.show(constants.institutionNotFound(), AlertType.ERROR, -1);
} else {
UserInfoTO userInfoTO = userHelloTO.getUserInfoTO();
KORNELL_SESSION.setInstitution(institution);
KORNELL_SESSION.setCurrentUser(userInfoTO);
boolean authenticated = KORNELL_SESSION.isAuthenticated();
if (authenticated) {
EVENT_BUS.fireEvent(new CourseClassesFetchedEvent(userHelloTO.getCourseClassesTO()));
setHomePlace(new WelcomePlace(), userHelloTO.getCourseClassesTO());
startAuthenticated(userHelloTO.getCourseClassesTO());
} else {
startAnonymous();
}
}
}
};
KORNELL_SESSION.user().getUserHello(institutionParam, windowHostName,
userHelloCallback);
}
private void startAnonymous() {
ClientProperties.remove(ClientProperties.X_KNL_TOKEN);
setDefaultPlace(new VitrinePlace());
startClient(null);
}
private void startAuthenticated(CourseClassesTO courseClassesTO) {
pickDefaultPlace();
startClient(courseClassesTO);
}
private void pickDefaultPlace() {
if (KORNELL_SESSION.hasAnyAdminRole()) {
setDefaultPlace(new AdminCourseClassesPlace());
} else if (InstitutionType.DASHBOARD.equals(KORNELL_SESSION.getInstitution().getInstitutionType())) {
setDefaultPlace(getHomePlace());
} else {
setDefaultPlace(new WelcomePlace());
}
}
protected void startClient(CourseClassesTO courseClassesTO) {
initGUI(courseClassesTO);
initActivityManagers();
initHistoryHandler(defaultPlace);
initException();
initPersonnel(courseClassesTO);
}
private void initGUI(CourseClassesTO courseClassesTO) {
viewFactory = new GenericViewFactoryImpl(this, courseClassesTO);
viewFactory.initGUI();
}
private void initPersonnel(final CourseClassesTO courseClassesTO) {
new Dean(EVENT_BUS, KORNELL_SESSION);
new Captain(EVENT_BUS, KORNELL_SESSION, placeCtrl);
new Stalker(EVENT_BUS, KORNELL_SESSION);
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
@Override
public void execute() {
new MrPostman(viewFactory, EVENT_BUS, KORNELL_SESSION, placeCtrl, ENTITY_FACTORY, courseClassesTO);
}
});
}
private void initException() {
GWT.setUncaughtExceptionHandler(new GWT.UncaughtExceptionHandler() {
@Override
public void onUncaughtException(Throwable e) {
if (Window.Location.getHostName().indexOf("localhost") >= 0
|| Window.Location.getHostName().indexOf("127.0.0.1") >= 0) {
KornellNotification.show(e.getMessage(), AlertType.ERROR, 0);
}
}
});
}
@Override
public PlaceController getPlaceController() {
return placeCtrl;
}
@Override
public HistoryMapper getHistoryMapper() {
return historyMapper;
}
@Override
public EventBus getEventBus() {
return EVENT_BUS;
}
@Override
public Place getDefaultPlace() {
return defaultPlace;
}
@Override
public void setDefaultPlace(Place place) {
this.defaultPlace = place;
}
@Override
public Place getHomePlace() {
return homePlace != null ? homePlace : defaultPlace;
}
@Override
public void setHomePlace(Place place, CourseClassesTO courseClassesTO) {
String enrollmentUUID = null;
if (InstitutionType.DASHBOARD.equals(KORNELL_SESSION.getInstitution().getInstitutionType()) && courseClassesTO != null) {
Date date = new Date(0);
Enrollment enrollment = null;
for (CourseClassTO courseClassTO : courseClassesTO.getCourseClasses()) {
// get latest active enrollment on a class (if no enrollment was
// found yet, get non active enrollment)
enrollment = courseClassTO.getEnrollment();
if (enrollment != null && enrollment.getEnrolledOn().after(date) && enrollment.getCourseClassUUID() != null) {
if (EnrollmentState.enrolled.equals(enrollment.getState()) || enrollmentUUID == null) {
date = enrollment.getEnrolledOn();
enrollmentUUID = enrollment.getUUID();
}
}
}
}
if (enrollmentUUID != null) {
place = new ClassroomPlace(enrollmentUUID);
}
this.homePlace = place;
}
@Override
public ViewFactory getViewFactory() {
return viewFactory;
}
@Override
public void logState() {
// TODO
}
@Override
public KornellSession getKornellSession() {
return KORNELL_SESSION;
}
}