package org.amc.game.chess;

import org.amc.util.DefaultSubject;

/**
 * Represents a Chess Board
 * Responsibility is to know the position of all the pieces
 * 
 * @author Adrian Mclaughlin
 *
 */
public class ChessBoard extends DefaultSubject
{
	public enum Coordinate implements Comparable<Coordinate>{
		A(0),
		B(1),
		C(2),
		D(3),
		E(4),
		F(5),
		G(6),
		H(7);
		
		private int name;
		
		private Coordinate(int name){
			this.name=name;
		}
		
		public int getName(){
			return this.name;
		}
		
	}
	
	private final ChessPiece[][] board;
	
	public ChessBoard(){
	    super();
		board=new ChessPiece[8][8];
	}
	
	/**
	 * Sets up the board in it's initial state
	 */
	public void initialise(){
		putPieceOnBoardAt(new BishopPiece(Colour.WHITE), new Location(Coordinate.C,1));
		putPieceOnBoardAt(new BishopPiece(Colour.WHITE), new Location(Coordinate.F,1));
		putPieceOnBoardAt(new KingPiece(Colour.WHITE), new Location(Coordinate.E, 1));
		putPieceOnBoardAt(new KnightPiece(Colour.WHITE), new Location(Coordinate.B, 1));
		putPieceOnBoardAt(new KnightPiece(Colour.WHITE), new Location(Coordinate.G, 1));
		
		
		putPieceOnBoardAt(new BishopPiece(Colour.BLACK), new Location(Coordinate.C,8));
		putPieceOnBoardAt(new BishopPiece(Colour.BLACK), new Location(Coordinate.F,8));
		putPieceOnBoardAt(new KingPiece(Colour.BLACK), new Location(Coordinate.E, 8));
		putPieceOnBoardAt(new KnightPiece(Colour.BLACK), new Location(Coordinate.B, 8));
        putPieceOnBoardAt(new KnightPiece(Colour.BLACK), new Location(Coordinate.G, 8));
	}
	
	public void move(Player player,Move move)throws InvalidMoveException{
		ChessPiece piece=getPieceFromBoardAt(move.getStart());
		if(piece==null){
			throw new InvalidMoveException("No piece at "+move.getStart());
		}else if (player.getColour()!=piece.getColour()){
			throw new InvalidMoveException("Player can only move their own pieces");
		}else{
			if(piece.isValidMove(this, move)){
			    removePieceOnBoardAt(piece, move.getStart());
				putPieceOnBoardAt(piece, move.getEnd());
				this.notifyObservers(null);
			}
			else
			{
			    throw new InvalidMoveException("Not a valid move");
			}
		}
	}
	
	void removePieceOnBoardAt(ChessPiece piece,Location location){
        this.board[location.getLetter().getName()][location.getNumber()-1]=null;
    }
	
	void putPieceOnBoardAt(ChessPiece piece,Location location){
		this.board[location.getLetter().getName()][location.getNumber()-1]=piece;
	}
	
	ChessPiece getPieceFromBoardAt(int letterCoordinate,int numberCoordinate){
		return board[letterCoordinate][numberCoordinate-1];
	}
	
	ChessPiece getPieceFromBoardAt(Location location){
		return getPieceFromBoardAt(location.getLetter().getName(), location.getNumber());
	}
}

@@ -936,24 +936,106 @@
 ate.E, 1));%0A
+%09%09putPieceOnBoardAt(new QueenPiece(Colour.WHITE), new Location(Coordinate.D, 1));%0A
 %09%09putPieceOn
@@ -1188,16 +1188,305 @@
 G, 1));%0A
+%09%09putPieceOnBoardAt(new RookPiece(Colour.WHITE), new Location(Coordinate.A, 1));%0A%09%09putPieceOnBoardAt(new RookPiece(Colour.WHITE), new Location(Coordinate.H, 1));%0A%09%09for(Coordinate coord:Coordinate.values())%7B%0A%09%09    putPieceOnBoardAt(new PawnPiece(Colour.WHITE), new Location(coord, 2));%0A%09%09%7D%0A
 %09%09%0A%09%09%0A%09%09
@@ -1724,24 +1724,106 @@
 ate.E, 8));%0A
+%09%09putPieceOnBoardAt(new QueenPiece(Colour.BLACK), new Location(Coordinate.D, 8));%0A
 %09%09putPieceOn
@@ -1982,16 +1982,335 @@
 G, 8));%0A
+        putPieceOnBoardAt(new RookPiece(Colour.BLACK), new Location(Coordinate.A, 8));%0A        putPieceOnBoardAt(new RookPiece(Colour.BLACK), new Location(Coordinate.H, 8));%0A        for(Coordinate coord:Coordinate.values())%7B%0A            putPieceOnBoardAt(new PawnPiece(Colour.BLACK), new Location(coord, 7));%0A        %7D%0A
 %09%7D%0A%09%0A%09pu
@@ -2789,24 +2789,43 @@
 .getEnd());%0A
+%09%09%09%09piece.moved();%0A
 %09%09%09%09this.not

call to ChessPiece moved() method