/*******************************************************************************
* Copyright 2011 Antti Havanko
*
* This file is part of Motiver.fi.
* Motiver.fi is licensed under one open source license and one commercial license.
*
* Commercial license: This is the appropriate option if you want to use Motiver.fi in
* commercial purposes. Contact license@motiver.fi for licensing options.
*
* Open source license: This is the appropriate option if you are creating an open source
* application with a license compatible with the GNU GPL license v3. Although the GPLv3 has
* many terms, the most important is that you must provide the source code of your application
* to your users so they can be free to modify your application for their own needs.
******************************************************************************/
package com.delect.motiver.client.presenter.training;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.http.client.Request;
import com.delect.motiver.client.AppController;
import com.delect.motiver.client.Motiver;
import com.delect.motiver.client.MyAsyncCallback;
import com.delect.motiver.client.event.RoutineCreatedEvent;
import com.delect.motiver.client.event.RoutineRemovedEvent;
import com.delect.motiver.client.presenter.CommentsBoxPresenter;
import com.delect.motiver.client.presenter.CommentsBoxPresenter.CommentsBoxDisplay;
import com.delect.motiver.client.presenter.ConfirmDialogPresenter;
import com.delect.motiver.client.presenter.ConfirmDialogPresenter.ConfirmDialogDisplay;
import com.delect.motiver.client.presenter.ConfirmDialogPresenter.ConfirmDialogHandler;
import com.delect.motiver.client.presenter.EmptyPresenter;
import com.delect.motiver.client.presenter.EmptyPresenter.EmptyDisplay;
import com.delect.motiver.client.presenter.Presenter;
import com.delect.motiver.client.presenter.ShowMorePresenter;
import com.delect.motiver.client.presenter.ShowMorePresenter.ShowMoreDisplay;
import com.delect.motiver.client.presenter.ShowMorePresenter.ShowMoreHandler;
import com.delect.motiver.client.presenter.UserPresenter;
import com.delect.motiver.client.presenter.UserPresenter.UserDisplay;
import com.delect.motiver.client.presenter.training.RoutineDayPresenter.RoutineDayDisplay;
import com.delect.motiver.client.service.MyServiceAsync;
import com.delect.motiver.client.view.CommentsBoxView;
import com.delect.motiver.client.view.ConfirmDialogView;
import com.delect.motiver.client.view.Display;
import com.delect.motiver.client.view.EmptyView;
import com.delect.motiver.client.view.ShowMoreView;
import com.delect.motiver.client.view.UserView;
import com.delect.motiver.client.view.training.RoutineDayView;
import com.delect.motiver.shared.Constants;
import com.delect.motiver.shared.RoutineModel;
import com.delect.motiver.shared.WorkoutModel;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
/**
* Shows single routine & all the workouts it contains
*
*/
public class RoutinePresenter extends Presenter {
/**
* Abstract class for view to extend
*/
public abstract static class RoutineDisplay extends Display {
public abstract LayoutContainer getBodyContainer();
public abstract LayoutContainer getCommentsContainer();
public abstract LayoutContainer getUserContainer();
public abstract void setAddButtonsVisible(boolean b);
public abstract void setHandler(RoutineHandler routineHandler);
public abstract void setModel(RoutineModel routine);
}
public interface RoutineHandler {
void routineRemoved();
void saveData(RoutineModel model);
void saveDays(boolean dayAdded);
}
public interface RoutineSelectedHandler {
void select(RoutineModel model);
}
private CommentsBoxPresenter commentsPresenter;
private RoutineDisplay display;
private Presenter[] emptyDayPresenters = null;
private EmptyPresenter emptyPresenter;
//child presenters
private List<RoutineDayPresenter> routineDayPresenters = new ArrayList<RoutineDayPresenter>();
private ShowMorePresenter showMorePresenter;
private UserPresenter userPresenter;
private ConfirmDialogPresenter msgPresenter;
protected RoutineModel routine;
public RoutinePresenter(MyServiceAsync rpcService, SimpleEventBus eventBus, RoutineDisplay display, RoutineModel routine) {
super(rpcService, eventBus);
this.display = display;
this.routine = routine;
}
@Override
public Display getView() {
return display;
}
@Override
public void onBind() {
display.setModel(routine);
emptyDayPresenters = new Presenter[routine.getDays()];
display.setHandler(new RoutineHandler() {
@Override
public void routineRemoved() {
display.setContentEnabled(false);
//remove routine and fire RoutineRemovedEvent
rpcService.removeRoutine(routine, new MyAsyncCallback<Boolean>() {
@Override
public void onSuccess(Boolean result) {
display.setContentEnabled(true);
stop();
//fire event
eventBus.fireEvent(new RoutineRemovedEvent(routine));
}
});
}
@SuppressWarnings("unchecked")
@Override
public void saveData(RoutineModel model) {
//if cancelled adding new measurement
if(model == null) {
stop();
//fire event
eventBus.fireEvent(new RoutineRemovedEvent(routine));
}
//added new measurement
else if(model.getId() == 0) {
routine = model;
display.setContentEnabled(false);
//create model
final Request req = rpcService.addRoutine(model, new MyAsyncCallback<RoutineModel>() {
@Override
public void onSuccess(RoutineModel result) {
display.setContentEnabled(true);
routine = result;
refresh();
//fire event
final RoutineCreatedEvent event = new RoutineCreatedEvent(routine);
eventBus.fireEvent(event);
}
});
addRequest(req);
}
//edited old value
else {
routine = model;
rpcService.updateRoutine(routine, MyAsyncCallback.EmptyCallback);
}
}
@SuppressWarnings("unchecked")
@Override
public void saveDays(boolean dayAdded) {
if(dayAdded) {
routine.setDays( routine.getDays() + 1 );
//add new presenter
final RoutineDayPresenter presenter = new RoutineDayPresenter(rpcService, eventBus, (RoutineDayDisplay)GWT.create(RoutineDayView.class), routine, routine.getDays(), new ArrayList<WorkoutModel>());
addNewPresenter(presenter);
rpcService.updateRoutine(routine, MyAsyncCallback.EmptyCallback);
}
else {
//if not confirmed -> check last days workouts
RoutineDayPresenter rdp = routineDayPresenters.get(routineDayPresenters.size() - 1);
boolean confirmationNeeded = rdp.workoutPresenters.size() > 0;
//ok to remove
if(!confirmationNeeded) {
removeLastDay();
rpcService.updateRoutine(routine, MyAsyncCallback.EmptyCallback);
}
else {
if(msgPresenter != null) {
msgPresenter.stop();
}
msgPresenter = new ConfirmDialogPresenter(rpcService, eventBus, (ConfirmDialogDisplay)GWT.create(ConfirmDialogView.class), AppController.Lang.ConfirmRemoveLastDayInRoutine(), new ConfirmDialogHandler() {
@Override
public void onYes() {
removeLastDay();
rpcService.updateRoutine(routine, MyAsyncCallback.EmptyCallback);
}
@Override
public void onNo() {
}
});
msgPresenter.run(display.getBodyContainer());
}
}
}
});
}
protected void removeLastDay() {
routine.setDays( routine.getDays() - 1 );
//remove last day
RoutineDayPresenter rdp = routineDayPresenters.get(routineDayPresenters.size() - 1);
rdp.stop();
routineDayPresenters.remove(rdp);
}
@Override
public void onRun() {
if(routine.getId() != 0) {
loadWorkouts();
}
//no model -> hightlight
else {
highlight();
}
}
@Override
public void onStop() {
//stop workout presenters
unbindPresenters();
if(showMorePresenter != null) {
showMorePresenter.stop();
}
if(userPresenter != null) {
userPresenter.stop();
}
if(msgPresenter != null) {
msgPresenter.stop();
}
}
/**
* Unbinds all the meal/time presenters
*/
private void unbindPresenters() {
if(emptyPresenter != null) {
emptyPresenter.stop();
}
if(commentsPresenter != null) {
commentsPresenter.stop();
}
if(routineDayPresenters != null) {
for(int i=0; i < routineDayPresenters.size(); i++) {
final Presenter presenter = routineDayPresenters.get(i);
if(presenter != null) {
presenter.stop();
}
}
routineDayPresenters.clear();
}
if(emptyDayPresenters != null) {
for(int i=0; i < emptyDayPresenters.length; i++) {
final Presenter presenter = emptyDayPresenters[i];
if(presenter != null) {
presenter.stop();
emptyDayPresenters[i] = null;
}
}
}
}
/**
* Adds new presenter to view
* @param day in routine
* @param presenter
*/
protected void addNewPresenter(RoutineDayPresenter presenter) {
try {
routineDayPresenters.add(presenter);
presenter.run(display.getBodyContainer());
} catch (Exception e) {
Motiver.showException(e);
}
}
/**
* Loads workouts to this routine
*/
protected void loadWorkouts() {
//if workouts already found
if(routine.getWorkouts().size() > 0) {
showWorkouts(0, routine.getWorkouts());
return;
}
//add empty presenter
emptyPresenter = new EmptyPresenter(rpcService, eventBus, (EmptyDisplay)GWT.create(EmptyView.class), EmptyPresenter.EMPTY_LOADING_SMALL);
emptyPresenter.run(display.getBodyContainer());
//fetch workouts
Motiver.setNextCallCacheable(true);
final Request req = rpcService.getWorkouts(0, routine, new MyAsyncCallback<List<WorkoutModel>>() {
@Override
public void onSuccess(List<WorkoutModel> workouts) {
showWorkouts(0, workouts);
}
});
addRequest(req);
//hide add buttons
display.setAddButtonsVisible(false);
}
/**
* Shows workouts
*/
protected void showWorkouts(final int index, final List<WorkoutModel> workouts) {
long dur = (new Date()).getTime();
if(emptyPresenter != null) {
emptyPresenter.stop();
}
//stop show more
if(showMorePresenter != null) {
showMorePresenter.stop();
}
if(index == 0) {
unbindPresenters();
}
//userview
if(userPresenter != null) {
userPresenter.stop();
}
//show user if not our workout
if(!routine.getUser().equals(AppController.User) && index == 0) {
userPresenter = new UserPresenter(rpcService, eventBus, (UserDisplay) GWT.create(UserView.class), routine.getUser(), false);
userPresenter.run(display.getUserContainer());
}
//each day
int day = 0;
for(day = 1; day <= routine.getDays(); day++) {
//if null value -> list was limited -> add showMorePresenter
if(day - index > Constants.LIMIT_ROUTINE_DAYS) {
showMorePresenter = new ShowMorePresenter(rpcService, eventBus, (ShowMoreDisplay)GWT.create(ShowMoreView.class), new ShowMoreHandler() {
@Override
public void showMore() {
showWorkouts(index + Constants.LIMIT_ROUTINE_DAYS, workouts);
}
});
showMorePresenter.run(display.getBodyContainer());
break;
}
else if(day >= index + 1) {
//find this day's workouts
List<WorkoutModel> daysWorkouts = new ArrayList<WorkoutModel>();
for(int i = 0; i < workouts.size(); i++) {
final WorkoutModel workout = workouts.get(i);
//correct day
if(workout.getDayInRoutine() == day) {
daysWorkouts.add(workout);
}
}
//add presenter
final RoutineDayPresenter routineDay = new RoutineDayPresenter(rpcService, eventBus, (RoutineDayDisplay)GWT.create(RoutineDayView.class), routine, day, daysWorkouts);
addNewPresenter(routineDay);
}
}
//if all days visible -> show buttons
if(day > routine.getDays()) {
display.setAddButtonsVisible(true);
}
if(commentsPresenter != null) {
commentsPresenter.stop();
}
commentsPresenter = new CommentsBoxPresenter(rpcService, eventBus, (CommentsBoxDisplay)GWT.create(CommentsBoxView.class), routine);
commentsPresenter.run(display.getCommentsContainer());
dur = (new Date()).getTime() - dur;
}
}