package chess4j.hash;

import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import chess4j.Color;
import chess4j.board.CastlingRights;
import chess4j.board.Square;
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 Zobrist {

	private static Map<Piece,Integer[]> pieceMap = new HashMap<Piece,Integer[]>();
	private static Map<Color,Integer> playerMap = new HashMap<Color,Integer>();
	private static Map<CastlingRights,Integer> castlingMap = new HashMap<CastlingRights,Integer>();
	private static Map<Square,Integer> epMap = new HashMap<Square,Integer>();

	private static void createZobristKeys(Piece p) {
		Random r = new Random();
		Integer[] keys = new Integer[64];
		for (int i=0;i<64;i++) {
			keys[i] = r.nextInt();
		}
		pieceMap.put(p, keys);
	}
	
	static {	
		Random r = new Random();
		createZobristKeys(Pawn.BLACK_PAWN);
		createZobristKeys(Pawn.WHITE_PAWN);
		createZobristKeys(Rook.BLACK_ROOK);
		createZobristKeys(Rook.WHITE_ROOK);
		createZobristKeys(Knight.BLACK_KNIGHT);
		createZobristKeys(Knight.WHITE_KNIGHT);
		createZobristKeys(Bishop.BLACK_BISHOP);
		createZobristKeys(Bishop.WHITE_BISHOP);
		createZobristKeys(Queen.BLACK_QUEEN);
		createZobristKeys(Queen.WHITE_QUEEN);
		createZobristKeys(King.BLACK_KING);
		createZobristKeys(King.WHITE_KING);
		
		playerMap.put(Color.BLACK, r.nextInt());
		playerMap.put(Color.WHITE, r.nextInt());
		
		Set<CastlingRights> crs = EnumSet.allOf(CastlingRights.class);
		for (CastlingRights cr : crs) {
			castlingMap.put(cr, r.nextInt());
		}
		
		List<Square> sqs = Square.allSquares();
		for (Square sq : sqs) {
			epMap.put(sq, r.nextInt());
		}
	}

	public static int getPieceKey(Square sq,Piece p) {
		return pieceMap.get(p)[sq.value()];
	}
	
	public static int getPlayerKey(Color c) {
		return playerMap.get(c);
	}
	
	public static int getCastlingKey(CastlingRights cr) {
		return castlingMap.get(cr);
	}
	
	public static int getEnPassantKey(Square sq) {
		return epMap.get(sq);
	}
}
