// This class handles how a piece could move (e.g. on a completely empty table with no blocking pieces)
// and if piece is let to move (e.g. it isn't blocked or moving it would cause the check)
function moveRules() {
	var letter = [];
	letter["a"] = 1;
	letter["b"] = 2;
	letter["c"] = 3;
	letter["d"] = 4;
	letter["e"] = 5;
	letter["f"] = 6;
	letter["g"] = 7;
	letter["h"] = 8;
	var letters = ["0", "a", "b", "c", "d", "e", "f", "g", "h"];
	
	this.pawn = 
	function(game, fromX, fromY, toX, toY, capture) {
		var legalPawns = [];
		var result = [];
		toXnum = letter[toX];

		// White pawns move "up", black move "down"
		if (game.currentMove == "white") 
			mod = 1;
		else
			mod = -1;
		pawns = game.getPiece("pawn", game.currentMove, fromX);
		for(var i = 0; i < pawns.length; i++) {
			pawn = game.pieces[pawns[i]];
			pawnX = letter[pawn.square.x];
			pawnY = pawn.square.y;
			if ((!capture && (toY == pawnY + mod*2 || toY == pawnY + mod) && toXnum == pawnX) || (capture && toY == pawnY + mod && (toXnum == pawnX + 1 || toXnum == pawnX - 1)))
				legalPawns.push(pawn);
		}

		if(legalPawns.length > 1) {
			// The only case is if there's a pawn in starting position and pawn right above it
			result[0] = toX;
			// Legal move would be move for 1
			result[1] = toY - mod;
		} else if(legalPawns.length == 1) {
			result[0] = legalPawns[0].square.x;
			result[1] = legalPawns[0].square.y;
		}
		return result;
	}

	this.knight = 
	function(game, fromX, fromY, toX, toY, capture) {
		var legalKnights = [];
		var toXnum;
		var knights;
		var knight;
		var knightX;
		var knightY;

		toXnum = letter[toX];
		knights = game.getPiece("knight", game.currentMove, fromX, fromY);
		for(var i = 0; i < knights.length; i++) {
			knight = game.pieces[knights[i]];
			knightX = letter[knight.square.x];
			knightY = knight.square.y;
			if((Math.abs(toY - knightY) == 1 && Math.abs(toXnum - knightX) == 2) || (Math.abs(toY - knightY) == 2 && Math.abs(toXnum - knightX) == 1))
				legalKnights.push(knight);
		}
		return this.executeCheck(game, legalKnights, toX, toY, capture);
	}

	this.bishop = 
	function(game, fromX, fromY, toX, toY, capture) {
		var legalBishops = [];
		var bishopX;
		var bishopY;
		var xDiff;
		var yDiff;
		var modX;
		var modY;
		var blocked;
		var bishops;
		var toXnum;

		toXnum = letter[toX];
		bishops = game.getPiece("bishop", game.currentMove, fromX, fromY);
		for(var i = 0; i < bishops.length; i++) {
			bishop = game.pieces[bishops[i]];
			bishopX = letter[bishop.square.x];
			bishopY = bishop.square.y;
			xDiff = toXnum - bishopX;
			yDiff = toY - bishopY;
			// If we could make that move
			if(Math.abs(xDiff) == Math.abs(yDiff)) {
				blocked = false;
				// Now we check if there are no pieces between bishop and target
				if (xDiff > 0)
					modX = 1;
				else
					modX = -1;
				if (xDiff == yDiff)
					modY = 1;
				else
					modY = -1;
				for (var j = 1; j < Math.abs(xDiff); j++) {
					if (game.squares[letters[toXnum - modX*j]][toY - modX*modY*j].piece != null)
						blocked = true;
				}
				if (!blocked)
					legalBishops.push(bishop);
			}
		}
		return this.executeCheck(game, legalBishops, toX, toY, capture);
	}

	this.rook = 
	function(game, fromX, fromY, toX, toY, capture) {
		var legalRooks = [];
		var result = [2];
		var rookX;
		var rookY;
		var diff;
		var modY
		var modA;
		var blocked;
		var rooks;
		var toXnum;

		toXnum = letter[toX];
		rooks = game.getPiece("rook", game.currentMove, fromX, fromY);
		for(var i = 0; i < rooks.length; i++) {
			rook = game.pieces[rooks[i]];
			rookX = letter[rook.square.x];
			rookY = rook.square.y;
			// If we could make that move
			if(toY == rookY || toXnum == rookX) {
				blocked = false;
				// Now we check if there are no pieces between rook and target
				if (toY == rookY) {
					modY = false;
					diff = toXnum - rookX;
				} else {
					modY = true;
					diff = toY - rookY;
				}
				if (diff > 0)
					modA = 1;
				else
					modA = -1;
				for (var j = 1; j < Math.abs(diff); j++) {
					if (modY && game.squares[letters[rookX]][toY - modA*j].piece != null)
						blocked = true;
					else if (!modY && game.squares[letters[toXnum - modA*j]][toY].piece != null)
						blocked = true;
				}
				if (!blocked)
					legalRooks.push(rook);
			}
		}
		return this.executeCheck(game, legalRooks, toX, toY, capture);
	}

	this.queen = 
	function(game, fromX, fromY, toX, toY, capture) {
		var legalQueens = [];
		var queenX;
		var queenY;
		var xDiff;
		var yDiff;
		var modX;
		var modY;
		var diff;
		var modR;
		var modA;
		var blocked;
		var queens;
		var toXnum;

		toXnum = letter[toX];
		queens = game.getPiece("queen", game.currentMove, fromX, fromY);
		for(var i = 0; i < queens.length; i++) {
			queen = game.pieces[queens[i]];
			queenX = letter[queen.square.x];
			queenY = queen.square.y;
			xDiff = toXnum - queenX;
			yDiff = toY - queenY;
			// If we could make that move
			if(Math.abs(xDiff) == Math.abs(yDiff)) {
				blocked = false;
				// Now we check if there are no pieces between queen and target
				if (xDiff > 0)
					modX = 1;
				else
					modX = -1;
				if (xDiff == yDiff)
					modY = 1;
				else
					modY = -1;
				for (var j = 1; j < Math.abs(xDiff); j++) {
					if (game.squares[letters[toXnum - modX*j]][toY - modX*modY*j].piece != null)
						blocked = true;
				}
				if (!blocked)
					legalQueens.push(queen);
			} else if (toY == queenY || toXnum == queenX) {
				blocked = false;
				// Now we check if there are no pieces between queen and target
				if (toY == queenY) {
					modR = false;
					diff = toXnum - queenX;
				} else {
					modR = true;
					diff = toY - queenY;
				}
				if (diff > 0)
					modA = 1;
				else
					modA = -1;
				for (var j = 1; j < Math.abs(diff); j++) {
					if (modR && game.squares[letters[queenX]][toY - modA*j].piece != null)
						blocked = true;
					else if (!modR && game.squares[letters[toXnum - modA*j]][toY].piece != null)
						blocked = true;
				}
				if (!blocked)
					legalQueens.push(queen);
			} 
			
		}
		return this.executeCheck(game, legalQueens, toX, toY, capture);
	}

	// Gets the king position
	this.king = 
	function(game, fromX, fromY, toX, toY, capture) {
		var king;
		var result = [];
		king = game.pieces[game.getPiece("king", game.currentMove)];
		result[0] = king.square.x;
		result[1] = king.square.y;
		return result;
	}

	this.executeCheck =
	function(game, legalPieces, toX, toY, capture) {
		var result = [];
		if(legalPieces.length > 1) {
			for (var i = 0; i < legalPieces.length; i++) {
				var pieceX = legalPieces[i].square.x;
				var pieceY = legalPieces[i].square.y;
				// If nothing, temporarily make that move to see if king would be under check if we do;
				game.makeMove(pieceX, pieceY, toX, toY, capture);
				game.switchMove();
				if (!this.check(game)) {
					result[0] = pieceX;
					result[1] = pieceY;
					game.loadFEN(game.FENs[game.FENs.length - 1]);
					break;
				}
				// Restore the board
				game.loadFEN(game.FENs[game.FENs.length - 1]);
			}
		} else if (legalPieces.length == 1) {
			result[0] = legalPieces[0].square.x;
			result[1] = legalPieces[0].square.y;
		} else {
			result = null;
		}
		return result;
	}

	// Sees if game is in check state for the current player
	this.check = 
	function(game) {
		var attackArray = [];
		var kingColor;
		var king;
		var kingX;
		var kingY;
		
		if(game.currentMove == "white")
			kingColor = "black";
		else
			kingColor = "white";
		king = game.pieces[game.getPiece("king", kingColor)];
		kingX = king.square.x;
		kingY = king.square.y;
		for (var i = 0; i < game.pieces.length; i++) {
			if(game.pieces[i].color == game.currentMove) {
				fromX = game.pieces[i].square.x;
				fromY = game.pieces[i].square.y;
				attackArray = eval("this." + game.pieces[i].name + "(game, \"" + fromX + "\", \"" + fromY + "\", \"" + kingX + "\", \"" + kingY + "\", true)");
				if(attackArray != null) {
					return true;
					break;
				}
			}
		}
		return false;
	}
}
