/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.models.memory;
import android.support.annotation.*;
import org.isoron.uhabits.models.*;
import java.util.*;
import static org.isoron.uhabits.models.HabitList.Order.*;
/**
* In-memory implementation of {@link HabitList}.
*/
public class MemoryHabitList extends HabitList
{
@NonNull
private LinkedList<Habit> list;
private Comparator<Habit> comparator = null;
@NonNull
private Order order;
public MemoryHabitList()
{
super();
list = new LinkedList<>();
order = Order.BY_POSITION;
}
protected MemoryHabitList(@NonNull HabitMatcher matcher)
{
super(matcher);
list = new LinkedList<>();
order = Order.BY_POSITION;
}
@Override
public void add(@NonNull Habit habit) throws IllegalArgumentException
{
if (list.contains(habit))
throw new IllegalArgumentException("habit already added");
Long id = habit.getId();
if (id != null && getById(id) != null)
throw new RuntimeException("duplicate id");
if (id == null) habit.setId((long) list.size());
list.addLast(habit);
resort();
}
@Override
public Habit getById(long id)
{
for (Habit h : list)
{
if (h.getId() == null) continue;
if (h.getId() == id) return h;
}
return null;
}
@NonNull
@Override
public Habit getByPosition(int position)
{
return list.get(position);
}
@NonNull
@Override
public HabitList getFiltered(HabitMatcher matcher)
{
MemoryHabitList habits = new MemoryHabitList(matcher);
habits.comparator = comparator;
for (Habit h : this) if (matcher.matches(h)) habits.add(h);
return habits;
}
@Override
public Order getOrder()
{
return order;
}
@Override
public int indexOf(@NonNull Habit h)
{
return list.indexOf(h);
}
@Override
public Iterator<Habit> iterator()
{
return Collections.unmodifiableCollection(list).iterator();
}
@Override
public void remove(@NonNull Habit habit)
{
list.remove(habit);
}
@Override
public void reorder(Habit from, Habit to)
{
int toPos = indexOf(to);
list.remove(from);
list.add(toPos, from);
}
@Override
public void setOrder(@NonNull Order order)
{
this.order = order;
this.comparator = getComparatorByOrder(order);
resort();
}
@Override
public int size()
{
return list.size();
}
@Override
public void update(List<Habit> habits)
{
// NOP
}
private Comparator<Habit> getComparatorByOrder(Order order)
{
Comparator<Habit> nameComparator =
(h1, h2) -> h1.getName().compareTo(h2.getName());
Comparator<Habit> colorComparator = (h1, h2) -> {
Integer c1 = h1.getColor();
Integer c2 = h2.getColor();
if (c1.equals(c2)) return nameComparator.compare(h1, h2);
else return c1.compareTo(c2);
};
Comparator<Habit> scoreComparator = (h1, h2) -> {
int s1 = h1.getScores().getTodayValue();
int s2 = h2.getScores().getTodayValue();
return Integer.compare(s2, s1);
};
if (order == BY_POSITION) return null;
if (order == BY_NAME) return nameComparator;
if (order == BY_COLOR) return colorComparator;
if (order == BY_SCORE) return scoreComparator;
throw new IllegalStateException();
}
private void resort()
{
if (comparator != null) Collections.sort(list, comparator);
}
}