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 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() {
		Position.createPositions();
		board = new Board();
		player1 = new Player(+1);
		player2 = new Player(-1);
		players = new Player[] { player1, player2 };
		currentPlayer = 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 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;
	}

	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
	 */
	public static List<Position> getPositionsToRise(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 (canPlaceBallAt(Position.at(x, y, z)))
						list.add(Position.at(x, y, z));
				}
			}
		}
		return list;
	}

	public static int ballsBySideAtLevel(int level) {
		return LEVELS - 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;
	}

	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;
	}
}

@@ -1376,24 +1376,87 @@
 n true;%0A%09%7D%0A%0A
+%09/**%0A%09 *%0A%09 * @return positions to place ball at any level%0A%09 */%0A
 %09public stat
@@ -1490,24 +1490,24 @@
 onBalls() %7B%0A
-
 %09%09List%3CPosit
@@ -1693,32 +1693,121 @@
 eturn list;%0A%09%7D%0A%0A
+%09/**%0A%09 *%0A%09 * @param level%0A%09 * @return positions to place a ball at referenced level%0A%09 */%0A
 %09public static L
@@ -2676,24 +2676,170 @@
  level;%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 stat
@@ -3092,32 +3092,248 @@
 eturn list;%0A%09%7D%0A%0A
+%09/**%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%09 * each square is a list of the positions of the balls that form a square at referenced level%0A%09 */%0A
 %09public static L

add some javadoc to Model