package com.novoda.todoapp.tasks.presenter;
import com.novoda.event.DataObserver;
import com.novoda.event.Event;
import com.novoda.event.EventObserver;
import com.novoda.todoapp.tasks.loading.displayer.TasksLoadingDisplayer;
import com.novoda.todoapp.tasks.loading.displayer.RetryActionListener;
import com.novoda.todoapp.navigation.Navigator;
import com.novoda.todoapp.task.data.model.Task;
import com.novoda.todoapp.tasks.data.model.Tasks;
import com.novoda.todoapp.tasks.displayer.TasksActionListener;
import com.novoda.todoapp.tasks.displayer.TasksDisplayer;
import com.novoda.todoapp.tasks.service.TasksService;
import rx.Observable;
import rx.subscriptions.CompositeSubscription;
public class TasksPresenter {
private final TasksService tasksService;
private final TasksLoadingDisplayer loadingDisplayer;
private final TasksDisplayer tasksDisplayer;
private final Navigator navigator;
private CompositeSubscription subscriptions = new CompositeSubscription();
private TasksActionListener.Filter currentFilter = TasksActionListener.Filter.ALL;
public TasksPresenter(TasksService tasksService, TasksDisplayer tasksDisplayer, TasksLoadingDisplayer loadingDisplayer, Navigator navigator) {
this.tasksService = tasksService;
this.loadingDisplayer = loadingDisplayer;
this.tasksDisplayer = tasksDisplayer;
this.navigator = navigator;
}
public void setInitialFilterTo(TasksActionListener.Filter filter){
currentFilter = filter;
}
public TasksActionListener.Filter getCurrentFilter() {
return currentFilter;
}
public void startPresenting() {
loadingDisplayer.attach(retryActionListener);
tasksDisplayer.attach(tasksActionListener);
subscribeToSourcesFilteredWith(currentFilter);
}
private void subscribeToSourcesFilteredWith(TasksActionListener.Filter filter) {
subscriptions.add(
getTasksObservableFor(filter)
.subscribe(tasksObserver)
);
subscriptions.add(
getTasksEventObservableFor(filter)
.subscribe(tasksEventObserver)
);
}
private Observable<Tasks> getTasksObservableFor(TasksActionListener.Filter filter) {
switch (filter) {
case ACTIVE:
return tasksService.getActiveTasks();
case COMPLETED:
return tasksService.getCompletedTasks();
case ALL:
return tasksService.getTasks();
default:
throw new IllegalArgumentException("Unkown filter type " + filter);
}
}
private Observable<Event<Tasks>> getTasksEventObservableFor(TasksActionListener.Filter filter) {
switch (filter) {
case ACTIVE:
return tasksService.getActiveTasksEvents();
case COMPLETED:
return tasksService.getCompletedTasksEvents();
case ALL:
return tasksService.getTasksEvents();
default:
throw new IllegalArgumentException("Unkown filter type " + filter);
}
}
public void stopPresenting() {
loadingDisplayer.detach(retryActionListener);
tasksDisplayer.detach(tasksActionListener);
clearSubscriptions();
}
private void clearSubscriptions() {
subscriptions.clear();
subscriptions = new CompositeSubscription();
}
final RetryActionListener retryActionListener = new RetryActionListener() {
@Override
public void onRetry() {
tasksService.refreshTasks().call();
}
};
final TasksActionListener tasksActionListener = new TasksActionListener() {
@Override
public void onTaskSelected(Task task) {
navigator.toTaskDetail(task);
}
@Override
public void toggleCompletion(Task task) {
if (task.isCompleted()) {
tasksService.activate(task).call();
} else {
tasksService.complete(task).call();
}
}
@Override
public void onRefreshSelected() {
tasksService.refreshTasks().call();
}
@Override
public void onClearCompletedSelected() {
tasksService.clearCompletedTasks().call();
}
@Override
public void onFilterSelected(Filter filter) {
currentFilter = filter;
clearSubscriptions();
subscribeToSourcesFilteredWith(filter);
}
@Override
public void onAddTaskSelected() {
navigator.toAddTask();
}
};
private final DataObserver<Tasks> tasksObserver = new DataObserver<Tasks>() {
@Override
public void onNext(Tasks tasks) {
tasksDisplayer.display(tasks);
}
};
private final EventObserver<Tasks> tasksEventObserver = new EventObserver<Tasks>() {
@Override
public void onLoading(Event<Tasks> event) {
if (event.data().isPresent()) {
loadingDisplayer.showLoadingIndicator();
} else {
loadingDisplayer.showLoadingScreen();
}
}
@Override
public void onIdle(Event<Tasks> event) {
if (event.data().isPresent()) {
loadingDisplayer.showData();
} else {
showEmptyScreen();
}
}
@Override
public void onError(Event<Tasks> event) {
if (event.data().isPresent()) {
loadingDisplayer.showErrorIndicator();
} else {
loadingDisplayer.showErrorScreen();
}
}
};
private void showEmptyScreen() {
switch (currentFilter) {
case ALL:
loadingDisplayer.showEmptyTasksScreen();
break;
case ACTIVE:
loadingDisplayer.showEmptyActiveTasksScreen();
break;
case COMPLETED:
loadingDisplayer.showEmptyCompletedTasksScreen();
break;
}
}
}