package chess4j.board;

import java.util.List;

import chess4j.Color;
import chess4j.pieces.Bishop;
import chess4j.pieces.King;
import chess4j.pieces.Knight;
import chess4j.pieces.Pawn;
import chess4j.pieces.Piece;
import chess4j.pieces.Queen;
import chess4j.pieces.Rook;




public class BoardVerifier {

	public static boolean verifyBoard(Board board) {
		if (!verifyBishops(board))
			return false;
		if (!verifyKnights(board))
			return false;
		if (!verifyKings(board))
			return false;
		if (!verifyPawns(board))
			return false;
		if (!verifyRooks(board))
			return false;
		if (!verifyQueens(board))
			return false;
		
		if (!verifyPieces(board))
			return false;
		
		return true;
	}

	private static boolean verifyBishops(Board b) {
		List<Square> bishops = b.getSquares(Bishop.WHITE_BISHOP);
		for (Square bishopSq : bishops) {
			Piece p = b.getPiece(bishopSq);
			assert(p != null);
			if (!Bishop.WHITE_BISHOP.equals(p)) {
				System.out.println("piece is not white bishop.");
				return false;
			}
		}
		
		bishops = b.getSquares(Bishop.BLACK_BISHOP);
		for (Square bishopSq : bishops) {
			Piece p = b.getPiece(bishopSq);
			assert(p != null);
			if (!Bishop.BLACK_BISHOP.equals(p)) {
				System.out.println("piece is not black bishop: " + bishopSq);
				return false;
			}
		}
		
		return true;		
	}

	private static boolean verifyKnights(Board b) {
		List<Square> knights = b.getSquares(Knight.WHITE_KNIGHT);
		for (Square knightSq : knights) {
			Piece p = b.getPiece(knightSq);
			assert(p != null);
			if (!Knight.WHITE_KNIGHT.equals(p)) {
				System.out.println("piece is not white knight.");
				return false;
			}
		}
		
		knights = b.getSquares(Knight.BLACK_KNIGHT);
		for (Square knightSq : knights) {
			Piece p = b.getPiece(knightSq);
			assert(p != null);
			if (!Knight.BLACK_KNIGHT.equals(p)) {
				System.out.println("piece is not black knight: " + knightSq);
				return false;
			}
		}
		
		return true;		
	}
	
	private static boolean verifyPawns(Board b) {
		List<Square> pawns = b.getSquares(Pawn.WHITE_PAWN);
		for (Square pawnSq : pawns) {
			Piece p = b.getPiece(pawnSq);
			assert(p != null);
			if (!Pawn.WHITE_PAWN.equals(p)) {
				System.out.println("piece is not white pawn.");
				return false;
			}
		}
		
		pawns = b.getSquares(Pawn.BLACK_PAWN);
		for (Square pawnSq : pawns) {
			Piece p = b.getPiece(pawnSq);
			assert (p != null);
			if (!Pawn.BLACK_PAWN.equals(p)) {
				System.out.println("piece is not black pawn.");
				return false;
			}
		}
		
		return true;
	}

	private static boolean verifyRooks(Board b) {
		List<Square> rooks = b.getSquares(Rook.WHITE_ROOK);
		for (Square rookSq : rooks) {
			Piece p = b.getPiece(rookSq);
			assert(p != null);
			if (!Rook.WHITE_ROOK.equals(p)) {
				System.out.println("piece is not white rook.");
				return false;
			}
		}
		
		rooks = b.getSquares(Rook.BLACK_ROOK);
		for (Square rookSq : rooks) {
			Piece p = b.getPiece(rookSq);
			assert (p != null);
			if (!Rook.BLACK_ROOK.equals(p)) {
				System.out.println("piece is not black rook.");
				return false;
			}
		}
		
		return true;
	}

	private static boolean verifyQueens(Board b) {
		List<Square> queens = b.getSquares(Queen.WHITE_QUEEN);
		for (Square queenSq : queens) {
			Piece p = b.getPiece(queenSq);
			assert(p != null);
			if (!Queen.WHITE_QUEEN.equals(p)) {
				System.out.println("piece is not white queen.");
				return false;
			}
		}
		
		queens = b.getSquares(Queen.BLACK_QUEEN);
		for (Square queenSq : queens) {
			Piece p = b.getPiece(queenSq);
			assert (p != null);
			if (!Queen.BLACK_QUEEN.equals(p)) {
				System.out.println("piece is not black queen.");
				return false;
			}
		}
		
		return true;
	}

	private static boolean verifyKings(Board b) {
		List<Square> kings = b.getSquares(King.WHITE_KING);
		assert(kings.size()==1);
		assert(kings.toArray()[0].equals(b.getKingSquare(Color.WHITE)));
		Piece p = b.getPiece((Square)kings.toArray()[0]);
		assert(p != null);
		if (!King.WHITE_KING.equals(p)) {
			System.out.println("piece is not white king.");
			return false;
		}
		kings = b.getSquares(King.BLACK_KING);
		assert(kings.size()==1);
		assert(kings.toArray()[0].equals(b.getKingSquare(Color.BLACK)));
		p = b.getPiece((Square)kings.toArray()[0]);
		assert (p != null);
		if (!King.BLACK_KING.equals(p)) {
			System.out.println("piece is not black king.");
			return false;
		}
		return true;
	}

	private static boolean verifyPieces(Board b) {
		List<Square> squares = Square.allSquares();
		for (Square sq : squares) {
			Piece p = b.getPiece(sq);
			if (p instanceof Bishop) {
				if (p.isWhite()) {
					if (!b.getSquares(Bishop.WHITE_BISHOP).contains(sq)) {
						System.out.println("white bishop not in whiteBishops.");
						return false;
					}
				} else {
					if (!b.getSquares(Bishop.BLACK_BISHOP).contains(sq)) {
						System.out.println("black bishop not in blackBishops.");
						return false;
					}
				}
			} else if (p instanceof Knight) {
				if (p.isWhite()) {
					if (!b.getSquares(Knight.WHITE_KNIGHT).contains(sq)) {
						System.out.println("white knight not in whiteKnights.");
						return false;
					} 
				} else {
					if (!b.getSquares(Knight.BLACK_KNIGHT).contains(sq)) {
						System.out.println("black knight not in blackKnights.");
						return false;
					}
				}
			} else if (p instanceof King) {
				if (!b.getKingSquare(p.getColor()).equals(sq)) {
					System.out.println("kingsq is not right for color " + p.getColor());
					return false;
				}
			} else  if (p instanceof Pawn) {
				if (p.isWhite()) {
					if (!b.getSquares(Pawn.WHITE_PAWN).contains(sq)) {
						System.out.println("white pawn not in whitePawns.");
						return false;
					} 
				} else {
					if (!b.getSquares(Pawn.BLACK_PAWN).contains(sq)) {
						System.out.println("black pawn not in blackPawns.");
						return false;
					}
				}
			} else if (p instanceof Queen) {
				if (p.isWhite()) {
					if (!b.getSquares(Queen.WHITE_QUEEN).contains(sq)) {
						System.out.println("white queen is not in whiteQueens.");
						return false;
					}
				} else {
					if (!b.getSquares(Queen.BLACK_QUEEN).contains(sq)) {
						System.out.println("black queen is not in blackQueens.");
						return false;
					}
				}
			} else if (p instanceof Rook) {
				if (p.isWhite()) {
					if (!b.getSquares(Rook.WHITE_ROOK).contains(sq)) {
						System.out.println("white rook is not in whiteRooks.");
						return false;
					}
				} else {
					if (!b.getSquares(Rook.BLACK_ROOK).contains(sq)) {
						System.out.println("black rook is not in blackRooks.");
						return false;
					}
				}
			}
		}
		
		return true;
	}
}
