package com.novoda.todoapp.tasks.data.model; import com.google.auto.value.AutoValue; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.novoda.data.ImmutableMapWithCopy; import com.novoda.data.SyncState; import com.novoda.data.SyncedData; import com.novoda.todoapp.task.data.model.Id; import com.novoda.todoapp.task.data.model.Task; import java.util.Collection; import java.util.Map; import static com.google.common.base.Predicates.not; @AutoValue public abstract class Tasks { public static Tasks empty() { return from(ImmutableMapWithCopy.<Id, SyncedData<Task>>empty()); } public static Tasks asSynced(Collection<Task> tasks, long syncActionTimestamp) { ImmutableMap.Builder<Id, SyncedData<Task>> builder = ImmutableMap.builder(); for (Task task : tasks) { builder.put(task.id(), SyncedData.from(task, SyncState.IN_SYNC, syncActionTimestamp)); } return from(ImmutableMapWithCopy.from(builder.build())); } static Tasks from(ImmutableMapWithCopy<Id, SyncedData<Task>> map) { return new AutoValue_Tasks(map); } Tasks() { // AutoValue best practices https://github.com/google/auto/blob/master/value/userguide/practices.md } abstract ImmutableMapWithCopy<Id, SyncedData<Task>> internalMap(); public boolean isEmpty() { return internalMap().isEmpty(); } public boolean isMostRecentAction(SyncedData<Task> syncedData) { SyncedData<Task> currentSyncData = internalMap().get(syncedData.data().id()); return currentSyncData == null || syncedData.lastSyncAction() >= currentSyncData.lastSyncAction(); } public Tasks save(SyncedData<Task> taskSyncedData) { return from(internalMap().put(taskSyncedData.data().id(), taskSyncedData)); } public ImmutableList<SyncedData<Task>> all() { return ImmutableList.copyOf(internalMap().values()); } public int size() { return internalMap().size(); } public SyncedData<Task> syncedDataFor(Id taskId) { return internalMap().get(taskId); } public boolean containsTask(Id taskId) { return internalMap().containsKey(taskId); } public Tasks onlyActives() { return Tasks.from(internalMap().filter(not(isCompleted()))); } public Tasks onlyCompleted() { return Tasks.from(internalMap().filter(isCompleted())); } private static Predicate<Map.Entry<Id, SyncedData<Task>>> isCompleted() { return new Predicate<Map.Entry<Id, SyncedData<Task>>>() { @Override public boolean apply(Map.Entry<Id, SyncedData<Task>> input) { return input.getValue().data().isCompleted(); } }; } }