package pylos.model;

import java.util.LinkedList;
import java.util.List;

/**
 * The Pylos Model.
 * Implements the singleton pattern by having everything static and no instance (the object is the class).
 * Contains the global model logic and pointers to the board and players.
 */
public abstract class Model {
	public static final int LEVELS = 4;
	public static final int LEVELS_1 = LEVELS - 1;
	public static final int BALLS = 30;
	public static Board board;
	public static Player player1;
	public static Player player2;
	public static Player[] players;

	public static Player currentPlayer;

	public static void initialize() {
		board = new Board();
		player1 = new Player(+1);
		player2 = new Player(-1);
		players = new Player[] { player1, player2 };
		currentPlayer = player1;
	}

	public static Player otherPlayer() {
		return currentPlayer == player1 ? player2 : player1;
	}

	public static boolean isWinner() {
		return board.anyBallAt(Position.top);
	}

	/**
	 * Checks if there are 4 balls under the position or if it is on the first level
	 * and if there is no ball at that place
	 * (so one can place a ball there)
	 */
	public static boolean canPlaceBallAt(Position position) {
		if (board.anyBallAt(position))
			return false;
		if (position.z == 0)
			return true;
		for (int x = position.x; x < position.x + 2; x++) {
			for (int y = position.y; y < position.y + 2; y++) {
				if (!board.anyBallAt(Position.at(x, y, position.z - 1)))
					return false;
			}
		}
		return true;
	}

	public static boolean canPlaceBallAtIgnoring(Position position, Position ignored) {
		if (board.anyBallAt(position))
			return position == ignored;
		if (position.z == 0)
			return true;
		for (int x = position.x; x < position.x + 2; x++) {
			for (int y = position.y; y < position.y + 2; y++) {
				Position pos = Position.at(x, y, position.z - 1);
				if (!board.anyBallAt(pos) || pos == ignored)
					return false;
			}
		}
		return true;
	}

	/**
	 * 
	 * @return positions to place ball at any level
	 */
	public static List<Position> getPositionBalls() {
		List<Position> list = new LinkedList<Position>();
		for (int level = 0; level < LEVELS; level++) {
			for (Position position : accessibleBalls(level)) {
				list.add(position);
			}
		}
		return list;
	}

	/**
	 * 
	 * @param level
	 * @return positions to place a ball at referenced level
	 */
	public static List<Position> accessibleBalls(int level) {
		List<Position> list = new LinkedList<Position>();
		Position position;
		for (int x = 0; x < LEVELS - level; x++) {
			for (int y = 0; y < LEVELS - level; y++) {
				position = Position.at(x, y, level);
				if (canPlaceBallAt(position))
					list.add(position);
			}
		}
		return list;
	}

	/**
	 * this needs to change onBoard to true, when the ball is placed in his new position
	 * 
	 * @return positions where referenced ball can be rising
	 */
	public static List<Position> getPositionsToMount(Ball ball) {
		List<Position> list = new LinkedList<Position>();
		for (int z = ball.position.z + 1; z < LEVELS; z++) {
			for (int x = 0; x < 4 - z; x++) {
				for (int y = 0; y < 4 - z; y++) {
					if (canPlaceBallAtIgnoring(Position.at(x, y, z), ball.position))
						list.add(Position.at(x, y, z));
				}
			}
		}
		return list;
	}

	public static int ballsBySideAtLevel(int level) {
		return LEVELS - level;
	}

	/**
	 * 
	 * @param level
	 * @param line
	 * @return a list of the positions of the balls that form the referenced line at referenced level
	 */
	public static List<Position> getAllPositionsForLevelLineByLine(int level, int line) { // to check if any lines
		List<Position> list = new LinkedList<Position>();
		for (int x = 0; x < LEVELS - level; x++) {
			list.add(Position.at(x, line, level));
		}
		return list;
	}

	/**
	 * each square is a list of the positions of the balls that form a square at referenced level
	 * 
	 * @param level
	 * @return a list of every possibles squares formed by the balls at referenced level
	 */
	public static List<List<Position>> getAllPositionForLevelSquareBySquare(int level) { // to check if any squares
		List<List<Position>> squares = new LinkedList<List<Position>>();
		for (int line = 1; line < LEVELS - level; line++) {
			for (int column = 1; column < LEVELS - level; column++) {
				List<Position> square = new LinkedList<Position>();
				square.add(Position.at(line, column, level));
				square.add(Position.at(line - 1, column, level));
				square.add(Position.at(line, column - 1, level));
				square.add(Position.at(line - 1, column - 1, level));
				squares.add(square);
			}
		}
		return squares;
	}
}

@@ -3333,1264 +3333,7 @@
 ;%0A%09%7D
-%0A%0A%09/**%0A%09 * %0A%09 * @param level%0A%09 * @param line%0A%09 * @return a list of the positions of the balls that form the referenced line at referenced level%0A%09 */%0A%09public static List%3CPosition%3E getAllPositionsForLevelLineByLine(int level, int line) %7B // to check if any lines%0A%09%09List%3CPosition%3E list = new LinkedList%3CPosition%3E();%0A%09%09for (int x = 0; x %3C LEVELS - level; x++) %7B%0A%09%09%09list.add(Position.at(x, line, level));%0A%09%09%7D%0A%09%09return list;%0A%09%7D%0A%0A%09/**%0A%09 * each square is a list of the positions of the balls that form a square at referenced level%0A%09 * %0A%09 * @param level%0A%09 * @return a list of every possibles squares formed by the balls at referenced level%0A%09 */%0A%09public static List%3CList%3CPosition%3E%3E getAllPositionForLevelSquareBySquare(int level) %7B // to check if any squares%0A%09%09List%3CList%3CPosition%3E%3E squares = new LinkedList%3CList%3CPosition%3E%3E();%0A%09%09for (int line = 1; line %3C LEVELS - level; line++) %7B%0A%09%09%09for (int column = 1; column %3C LEVELS - level; column++) %7B%0A%09%09%09%09List%3CPosition%3E square = new LinkedList%3CPosition%3E();%0A%09%09%09%09square.add(Position.at(line, column, level));%0A%09%09%09%09square.add(Position.at(line - 1, column, level));%0A%09%09%09%09square.add(Position.at(line, column - 1, level));%0A%09%09%09%09square.add(Position.at(line - 1, column - 1, level));%0A%09%09%09%09squares.add(square);%0A%09%09%09%7D%0A%09%09%7D%0A%09%09return squares;%0A%09%7D
 %0A%7D%0A

delete unused methods