/*******************************************************************************
* 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;
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.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.Timer;
import com.delect.motiver.client.AppController;
import com.delect.motiver.client.Motiver;
import com.delect.motiver.client.MyAsyncCallback;
import com.delect.motiver.client.StringConstants;
import com.delect.motiver.client.presenter.CommentPresenter.CommentDisplay;
import com.delect.motiver.client.presenter.EmptyPresenter.EmptyDisplay;
import com.delect.motiver.client.presenter.ShowMorePresenter.ShowMoreDisplay;
import com.delect.motiver.client.presenter.ShowMorePresenter.ShowMoreHandler;
import com.delect.motiver.client.service.MyServiceAsync;
import com.delect.motiver.client.view.CommentView;
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.shared.CardioModel;
import com.delect.motiver.shared.CommentModel;
import com.delect.motiver.shared.Constants;
import com.delect.motiver.shared.MealModel;
import com.delect.motiver.shared.MeasurementModel;
import com.delect.motiver.shared.RoutineModel;
import com.delect.motiver.shared.RunModel;
import com.delect.motiver.shared.UserModel;
import com.delect.motiver.shared.WorkoutModel;
import com.delect.motiver.shared.util.CommonUtils;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
/**
* Shows facebook comments "box"
* @author Antti
*
*/
public class CommentsBoxPresenter extends Presenter {
/** Handler for this presenter
*/
public interface CommentBoxHandler {
/**
* Called when user writes new comment
* @param text String
* @param publishOnFacebook boolean
*/
void newComment(String text, boolean publishOnFacebook);
}
/**
* Abstract class for view to extend
*/
public abstract static class CommentsBoxDisplay extends Display {
/**
* Returns container for comments
* @return LayoutContainer
*/
public abstract LayoutContainer getCommentsContainer();
/**
* Sets title for comments box
* @param title String
*/
public abstract void setCommentTitle(String title);
/**
* Disables comment box
*/
public abstract void setDisabled();
/**
* Sets handler for view to call
* @param handler CommentBoxHandler
*/
public abstract void setHandler(CommentBoxHandler handler);
}
private CardioModel cardio;
private List<Presenter> commentPresenters = new ArrayList<Presenter>();
private Date date;
private final CommentsBoxDisplay display;
private EmptyPresenter emptyPresenter;
private MealModel meal;
private MeasurementModel measurement;
private RoutineModel routine;
private RunModel run;
private ShowMorePresenter showMorePresenter;
private String target = "";
private String title = "";
private String uid;
//models
private WorkoutModel workout;
private Timer timer;
/**
* Comments box for cardio
* @param rpcService
* @param eventBus
* @param display
* @param cardio
*/
public CommentsBoxPresenter(MyServiceAsync rpcService, SimpleEventBus eventBus, CommentsBoxDisplay display, CardioModel cardio) {
super(rpcService, eventBus);
this.display = display;
this.cardio = cardio;
}
/**
* Comments box for nutrition day
* @param rpcService
* @param eventBus
* @param display
* @param date
* @param uid : who's nutrition it is
*/
public CommentsBoxPresenter(MyServiceAsync rpcService, SimpleEventBus eventBus, CommentsBoxDisplay display, Date date, String uid) {
super(rpcService, eventBus);
this.display = display;
this.date = date;
this.uid = uid;
}
/**
* Comments box for meal
* @param rpcService
* @param eventBus
* @param display
* @param meal MealModel
*/
public CommentsBoxPresenter(MyServiceAsync rpcService, SimpleEventBus eventBus, CommentsBoxDisplay display, MealModel meal) {
super(rpcService, eventBus);
this.display = display;
this.meal = meal;
}
/**
* Comments box for measurement value
* @param rpcService
* @param eventBus
* @param display
* @param measurement
*/
public CommentsBoxPresenter(MyServiceAsync rpcService, SimpleEventBus eventBus, CommentsBoxDisplay display, MeasurementModel measurement) {
super(rpcService, eventBus);
this.display = display;
this.measurement = measurement;
}
/**
* Comments box for routine
* @param rpcService
* @param eventBus
* @param display
* @param routine RoutineModel
*/
public CommentsBoxPresenter(MyServiceAsync rpcService, SimpleEventBus eventBus, CommentsBoxDisplay display, RoutineModel routine) {
super(rpcService, eventBus);
this.display = display;
this.routine = routine;
}
/**
* Comments box for run
* @param rpcService
* @param eventBus
* @param display
* @param run
*/
public CommentsBoxPresenter(MyServiceAsync rpcService, SimpleEventBus eventBus, CommentsBoxDisplay display, RunModel run) {
super(rpcService, eventBus);
this.display = display;
this.run = run;
}
/**
* Comments box for workout
* @param rpcService
* @param eventBus
* @param display
* @param workout
*/
public CommentsBoxPresenter(MyServiceAsync rpcService, SimpleEventBus eventBus, CommentsBoxDisplay display, WorkoutModel workout) {
super(rpcService, eventBus);
this.display = display;
this.workout = workout;
}
@Override
public Display getView() {
return display;
}
@Override
public void onBind() {
display.setHandler(new CommentBoxHandler() {
@Override
public void newComment(String text, boolean publishOnFacebook) {
sendNewComment(text, publishOnFacebook);
}
});
//workout
if(workout != null) {
title = workout.getName();
target = "w" + workout.getId();
uid = workout.getUser().getUid();
}
//routine
else if(routine != null) {
title = routine.getName();
target = "r" + routine.getId();
uid = routine.getUser().getUid();
}
//meal
else if(meal != null) {
title = meal.getName();
target = "m" + meal.getId();
uid = meal.getUser().getUid();
}
//measurement
else if(measurement != null) {
title = measurement.getNameClient();
target = "me" + measurement.getId();
uid = measurement.getUid();
}
//cardio
else if(cardio != null) {
title = cardio.getNameClient();
target = "c" + cardio.getId();
uid = cardio.getUid();
}
//run
else if(run != null) {
title = run.getNameClient();
target = "ru" + run.getId();
uid = run.getUid();
}
//nutrition day
else if(date != null) {
final DateTimeFormat fmt2 = DateTimeFormat.getFormat(StringConstants.DATEFORMATS[AppController.User.getDateFormat()]);
title = AppController.Lang.Foods().toLowerCase() + " (" + fmt2.format(date) + ")";
target = "n" + (date.getTime() / 1000);
}
display.setCommentTitle(title);
}
@Override
public void onRun() {
//if coach mode -> disable comments
if(AppController.COACH_MODE_ON) {
display.setDisabled();
emptyPresenter = new EmptyPresenter(rpcService, eventBus, (EmptyDisplay)GWT.create(EmptyView.class), AppController.Lang.CommentsDisabledInCoachMode(), EmptyPresenter.OPTION_SMALLER);
emptyPresenter.run(display.getBaseContainer());
}
//load comments
else {
loadComments(0, true);
//refresh comments every X seconds
if(timer != null) {
timer.cancel();
}
timer = new Timer() {
@Override
public void run() {
loadComments(0, false);
}
};
timer.scheduleRepeating(Constants.DELAY_COMMENTS_REFRESH);
}
}
@Override
public void onStop() {
if(timer != null) {
timer.cancel();
}
unbindPresenters();
}
/**
* Stops all comment presenters
*/
private void unbindPresenters() {
if(commentPresenters != null) {
for(int i=0; i < commentPresenters.size(); i++) {
final Presenter presenter = commentPresenters.get(i);
if(presenter != null) {
presenter.stop();
}
}
commentPresenters.clear();
}
}
/**
* Adds new presenter to view
* @param presenter
*/
protected void addNewPresenter(Presenter presenter) {
//remove emptypresenter if present
if(emptyPresenter != null) {
emptyPresenter.stop();
emptyPresenter = null;
}
commentPresenters.add(presenter);
presenter.run(display.getCommentsContainer());
}
/**
* Loads comments from server
* @param index int
* @param loadFromCache : if data is loaded from cache before server call
* @param showLoading : if loading text are shown. If false loads on background and refreshes comments when new data is fetched.
*/
protected void loadComments(final int index, boolean showLoading) {
if(showLoading) {
if(emptyPresenter != null) {
emptyPresenter.stop();
}
//stop show more
if(showMorePresenter != null) {
showMorePresenter.stop();
}
//stop presenters if first items
if(index == 0) {
unbindPresenters();
}
//add empty presenter
emptyPresenter = new EmptyPresenter(rpcService, eventBus, (EmptyDisplay)GWT.create(EmptyView.class), EmptyPresenter.EMPTY_LOADING_SMALL);
emptyPresenter.run(display.getCommentsContainer());
}
//fetch all comments
if(index == 0) {
Motiver.setNextCallCacheable(true);
}
final Request req = rpcService.getComments(index, Constants.LIMIT_COMMENTS, target, uid, true, new MyAsyncCallback<List<CommentModel>>() {
@Override
public void onSuccess(List<CommentModel> result) {
showComments(index, result);
}
});
addRequest(req);
}
/**
* Sends new comment to server
* @param text
* @param publishOnFacebook boolean
*/
protected void sendNewComment(final String text, final boolean publishOnFacebook) {
final CommentModel model = new CommentModel();
model.setDate(CommonUtils.trimDateToDatabase(new Date(), false));
model.setTarget(target);
model.setText(text);
model.setUserTarget(new UserModel(uid));
display.setContentEnabled(false);
//send comment
final Request req = rpcService.addComment(model, new MyAsyncCallback<CommentModel>() {
@Override
public void onSuccess(CommentModel result) {
display.setContentEnabled(true);
loadComments(0, false);
//publish on facebook
// if(publishOnFacebook) {
//
// final RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, "https://graph.facebook.com/me/feed");
// rb.setHeader("Content-Type", "application/x-www-form-urlencoded");
// try {
// //send to facebook servers
// rb.sendRequest(URL.encode("message=" + text + "&link=http://www.motiver.fi&actions={\"name\": \"" + AppController.Lang.ViewOnMotiver() + "\", \"link\": \"http://"+uid+".motiver.fi\"}&privacy={\"value\": \"EVERYONE\"}&access_token=" + AppController.ACCESSTOKEN + ""), null);
// }
// catch (RequestException e) {
// final ConnectionErrorEvent event = new ConnectionErrorEvent(Constants.ERROR_CANT_CONNECT_FACEBOOK);
// eventBus.fireEvent(event);
// }
//
// }
}
});
addRequest(req);
}
/**
* Parses facebooks groups
* @param index int
* @param result List<CommentModel>
*/
protected void showComments(final int index, List<CommentModel> result) {
try {
if(emptyPresenter != null) {
emptyPresenter.stop();
}
//stop show more
if(showMorePresenter != null) {
showMorePresenter.stop();
}
//stop presenters if first items
if(index == 0) {
unbindPresenters();
}
//if no comments
if(result.size() == 0 && index == 0) {
emptyPresenter = new EmptyPresenter(rpcService, eventBus, (EmptyDisplay)GWT.create(EmptyView.class), AppController.Lang.NoComments(), EmptyPresenter.OPTION_SMALLER);
emptyPresenter.run(display.getCommentsContainer());
}
else {
//add comments
for(CommentModel m : result) {
//if null value -> list was limited -> add showMorePresenter
if(m == null) {
showMorePresenter = new ShowMorePresenter(rpcService, eventBus, (ShowMoreDisplay)GWT.create(ShowMoreView.class), new ShowMoreHandler() {
@Override
public void showMore() {
loadComments(index + Constants.LIMIT_COMMENTS, true);
}
});
showMorePresenter.run(display.getCommentsContainer());
}
else {
final CommentPresenter fp = new CommentPresenter(rpcService, eventBus, (CommentDisplay)GWT.create(CommentView.class), m, false);
addNewPresenter(fp);
}
}
}
} catch (Exception e) {
Motiver.showException(e);
}
}
}