/*
	cursus - Race series management program
	Copyright 2011  Simon Arlott

	This program 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.

	This program 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 eu.lp0.cursus.scoring;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.common.collect.ArrayTable;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Table;

import eu.lp0.cursus.db.data.Pilot;
import eu.lp0.cursus.db.data.Race;

public abstract class AbstractRaceLapsData<T extends ScoredData> implements RaceLapsData {
	protected final T scores;

	private final Table<Pilot, Race, Integer> raceLaps;
	private final Map<Race, LinkedListMultimap<Integer, Pilot>> lapOrder;

	public AbstractRaceLapsData(T scores) {
		this.scores = scores;

		raceLaps = ArrayTable.create(scores.getPilots(), scores.getRaces());
		lapOrder = new HashMap<Race, LinkedListMultimap<Integer, Pilot>>();

		Map<Race, Integer> zeroLaps = new HashMap<Race, Integer>();
		for (Race race : scores.getRaces()) {
			LinkedListMultimap<Integer, Pilot> order = LinkedListMultimap.create();
			lapOrder.put(race, order);
			zeroLaps.put(race, 0);
		}

		for (Pilot pilot : scores.getPilots()) {
			raceLaps.row(pilot).putAll(zeroLaps);
		}
	}

	@Override
	public int getLaps(Pilot pilot, Race race) {
		return raceLaps.get(pilot, race);
	}

	@Override
	public Map<Race, Integer> getLaps(Pilot pilot) {
		return Collections.unmodifiableMap(raceLaps.row(pilot));
	}

	@Override
	public Map<Pilot, Integer> getLaps(Race race) {
		return Collections.unmodifiableMap(raceLaps.column(race));
	}

	@Override
	public List<Pilot> getLapOrder(Race race) {
		return Collections.unmodifiableList(new ArrayList<Pilot>(lapOrder.get(race).values()));
	}

	protected void completeRaceLap(Race race, Pilot pilot) {
		LinkedListMultimap<Integer, Pilot> order = lapOrder.get(race);
		int laps = raceLaps.get(pilot, race);

		order.remove(laps, pilot);
		raceLaps.put(pilot, race, ++laps);
		order.put(laps, pilot);
	}
}
@@ -856,16 +856,68 @@
 l.Map;%0A%0A
+import com.google.common.collect.ArrayListMultimap;%0A
 import c
@@ -986,22 +986,16 @@
 collect.
-Linked
 ListMult
@@ -992,32 +992,75 @@
 t.ListMultimap;%0A
+import com.google.common.collect.Ordering;%0A
 import com.googl
@@ -1345,38 +1345,32 @@
 final Map%3CRace, 
-Linked
 ListMultimap%3CInt
@@ -1562,22 +1562,16 @@
 p%3CRace, 
-Linked
 ListMult
@@ -1701,22 +1701,16 @@
 )) %7B%0A%09%09%09
-Linked
 ListMult
@@ -1738,22 +1738,21 @@
 order = 
-Linked
+Array
 ListMult
@@ -2327,93 +2327,315 @@
 %7B%0A%09%09
-return Collections.unmodifiableList(new ArrayList%3CPilot%3E(lapOrder.get(race).values())
+ListMultimap%3CInteger, Pilot%3E order = lapOrder.get(race);%0A%09%09List%3CInteger%3E laps = Ordering.natural().reverse().sortedCopy(order.keySet());%0A%09%09List%3CPilot%3E pilotOrder = new ArrayList%3CPilot%3E();%0A%09%09for (Integer lap : laps) %7B%0A%09%09%09pilotOrder.addAll(order.get(lap));%0A%09%09%7D%0A%09%09return Collections.unmodifiableList(pilotOrder
 );%0A%09
@@ -2699,16 +2699,10 @@
 ) %7B%0A
+
 %09%09
-Linked
 List

fix pilot lap ordering