package edu.columbia.cs.cs1007.checkers;

import java.util.ArrayList;

import edu.columbia.cs.cs1007.checkers.Constants.HORIZONTAL_DIRECTION;
import edu.columbia.cs.cs1007.checkers.Constants.PIECE_COLOR;
import edu.columbia.cs.cs1007.checkers.Constants.SQUARE_COLOR;
import edu.columbia.cs.cs1007.checkers.Constants.VERTICAL_DIRECTION;

/**
 * A checkers board.  See picture and rules here:
 *     http://www.jimloy.com/checkers/rules2.htm.
 
 @author Julia Stoyanovich
 *        COMS 1007, Summer 2009
 *
 */
public class Board {

  private Square[][] _squares;
  
  /**
   * Constructor
   */
  public Board() {
    _squares = new Square[Constants.NUM_ROWS][Constants.NUM_COLUMNS];
    colorBoard();
    initPosition();
  }
  
  /**
   * Draw the board, with no pieces.
   */
  public void colorBoard() {
    for (int row=0; row<Constants.NUM_ROWS; row++) {
      for (int col=0; col<Constants.NUM_COLUMNS; col++) {
        if (row % == col % 2) {
          // row and column are both even or both odd
          _squares[row][colnew Square (SQUARE_COLOR.YELLOW)
        else {
          // odd row even column, or even row odd column
          _squares[row][colnew Square (SQUARE_COLOR.GREEN);
        }
      }
    }
  }
  
  /**
   * Place the pieces into their initial positions, before the start of the game.
   */
  public void initPosition() {
    // white pieces go into white squares of the first 3 (a.k.a. INITIAL_WIDTH) rows
    for (int row=0; row<Constants.INITIAL_WIDTH; row++) {
      for (Square square : _squares[row]) {
        if (square.getColor() == SQUARE_COLOR.YELLOW) {
          square.setContents(new Piece(PIECE_COLOR.WHITE));
        }
      }
    }

    // black pieces go into white squares of the last 3 rows
    for (int row=Constants.NUM_ROWS - Constants.INITIAL_WIDTH; row<Constants.NUM_ROWS; row++) {
      for (Square square : _squares[row]) {
        if (square.getColor() == SQUARE_COLOR.YELLOW) {
          square.setContents(new Piece(PIECE_COLOR.BLACK));
        }
      }
    }
  }
  
  /**
   * Check whether there is a piece in the specified position.
   @param row
   @param col
   @return true if there is a piece in that position, false otherwise
   */
  public boolean isOccupied(int row, int col) {
    return _squares[row][col].isOccupied();
  }
  
  /**
   * Place a piece into the specified position.
   @param piece
   @param row
   @param col
   */
  public void placePiece(Piece piece, int row, int col) {
    _squares[row][col].setContents(piece);
  }

  /**
   * Remove a piece from the specified position.
   @param row
   @param col
   */
  public void freeUpSquare(int row, int col) {
    _squares[row][col].removeContents();
  }
  
  /**
   *   For each piece of the given color, ask it where it would like to move.
   *  Then check which of the desired moves are possible.
   *
   @param color or the player/pieces
   @return ArrayList of possible Moves
   */
  public ArrayList<Move> getAllPossibleMoves(PIECE_COLOR color) {
    
    ArrayList<Move> possibleMoves = new ArrayList<Move>();
    
    for (int row=0; row<Constants.NUM_ROWS; row++) {
      for (int col=0; col<Constants.NUM_COLUMNS; col++) {
  
        Piece currentPiece = _squares[row][col].getContents();
        if (currentPiece.getColor() == color) {
        
          // see where the piece is trying to move
          VERTICAL_DIRECTION vDir = currentPiece.getDesiredVerticalDirection();
          
          // if we are not on the first row, and the piece wants to move back, 
          // let's try
          if ((row > 0&& 
            (vDir == VERTICAL_DIRECTION.BACK|| 
            (vDir == VERTICAL_DIRECTION.BOTH)) {
            
            // try to go back and left
            if ((col > 0&& !_squares[row-1][col-1].isOccupied()){
              possibleMoves.add(new Move(row, col, VERTICAL_DIRECTION.BACK, HORIZONTAL_DIRECTION.LEFT));
            }
            // try to go back and right
            if ((col < Constants.NUM_COLUMNS-1&& !_squares[row-1][col+1].isOccupied()) {
              possibleMoves.add(new Move(row, col, VERTICAL_DIRECTION.BACK, HORIZONTAL_DIRECTION.RIGHT));              
            }
          
          // if we are not on the last row, and the piece wants to move forward,
          // let's try
          if ((row < Constants.NUM_ROWS - 1&& 
            (vDir == VERTICAL_DIRECTION.FORTH|| 
            (vDir == VERTICAL_DIRECTION.BOTH)) {
            
            // try to go forward and left
            if ((col > 0&& !_squares[row+1][col-1].isOccupied()){
              possibleMoves.add(new Move(row, col, VERTICAL_DIRECTION.FORTH, HORIZONTAL_DIRECTION.LEFT));
            }
            
            // try to go forward and right
            if ((col < Constants.NUM_COLUMNS-1&& !_squares[row+1][col+1].isOccupied()){
              possibleMoves.add(new Move(row, col, VERTICAL_DIRECTION.FORTH, HORIZONTAL_DIRECTION.RIGHT));
            }
          }
        }
      }
    }
    return possibleMoves;
  }
  
  /**
   * Move a piece, position and direction specified by the move parameter.
   @param move
   */
  public void makeAMove(Move move) {
    
    int fromRow = move.getSourceRow();
    int fromCol = move.getSourceColumn();
    int toRow =  move.getTargetRow();
    int toCol = move.getTargetColumn();
    
    Piece pieceToMove = _squares[fromRow][fromCol].getContents();
    placePiece(pieceToMove, toRow, toCol);
    freeUpSquare(fromRow, fromCol);
    
  }
  
  /**
   * Generate a string representation of the board.
   @return string
   */
  public String toString() {
  
    StringBuffer res = new StringBuffer("");
    
    // print top to bottom, left to right
    for (int row = Constants.NUM_ROWS-1; row >=0; row--) {
      for (int col=0; col<Constants.NUM_COLUMNS; col++) {
        res.append(" " + _squares[row][col].toString());
      }
      res.append("\n");
    }
    return res.toString();
  }
  
  public static void main(String[] args) {
    Board board = new Board();
    System.out.println(board.toString());
  }
}