package jrummikub.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Class that stores information for a game of multiple rounds
 */
public class GameState implements Serializable {
	private static final long serialVersionUID = -5787975403310108391L;

	private int firstRoundFirstPlayer;
	private ArrayList<Score> scores = new ArrayList<Score>();

	/**
	 * Gets the number of the first player of the first round
	 * 
	 * @return the number of the first player of the first round
	 */
	public int getFirstRoundFirstPlayer() {
		return firstRoundFirstPlayer;
	}

	/**
	 * Sets the number of the first player of the first round
	 * 
	 * @param firstRoundFirstPlayer
	 *          the number of the first player of the first round
	 */
	public void setFirstRoundFirstPlayer(int firstRoundFirstPlayer) {
		this.firstRoundFirstPlayer = firstRoundFirstPlayer;
	}

	/**
	 * Returns the list of players' scores in the rounds played before
	 * 
	 * @return the list of scores
	 */
	public List<Score> getScores() {
		return scores;
	}

	private Boolean[] getWinners(Integer[] points, int[] wins) {
		int playerCount = scores.get(0).getPoints().size();
		int maxWins = 0, maxPoints = 0;
		Boolean[] winners = new Boolean[playerCount];

		for (int i = 0; i < playerCount; ++i) {
			winners[i] = false;
		}

		for (int i = 0; i < playerCount; ++i) {
			if (wins[i] > maxWins) {
				maxWins = wins[i];
				maxPoints = points[i];

				for (int j = 0; j < i; ++j) {
					winners[j] = false;
				}

				winners[i] = true;
			} else if (wins[i] == maxWins) {
				if (points[i] > maxPoints) {
					maxWins = wins[i];
					maxPoints = points[i];

					for (int j = 0; j < i; ++j) {
						winners[j] = false;
					}

					winners[i] = true;
				} else if (points[i] == maxPoints) {
					winners[i] = true;
				}
			}
		}

		return winners;
	}

	/**
	 * Calculated the accumulated score over the played rounds
	 * 
	 * @return the accumulated score
	 */
	public Score getAccumulatedScore() {
		if (scores.isEmpty()) {
			return null;
		}

		int playerCount = scores.get(0).getPoints().size();
		Integer[] points = new Integer[playerCount];
		int[] wins = new int[playerCount];

		for (int i = 0; i < playerCount; ++i) {
			points[i] = 0;
		}

		for (Score roundScore : scores) {
			for (int i = 0; i < playerCount; ++i) {
				points[i] += roundScore.getPoints().get(i);
				if (roundScore.getWinners().get(i)) {
					wins[i]++;
				}
			}
		}

		Boolean[] winners = getWinners(points, wins);

		return new Score(Arrays.asList(winners), Arrays.asList(points));
	}
}
