/*
 * Game board
 */

import java.util.Iterator;
import java.util.NoSuchElementException;
import java.lang.UnsupportedOperationException;

public abstract class Board implements Iterable<ConstBoardPosition>
{
   
   protected BoardPosition[][] matrix;
   protected int rows;
   protected int cols;

   public Board(int r, int c){
      rows = r;
      cols = c;
      matrix = new BoardPosition[rows][cols];
      for (int i = 0; i < rows; i++)
      { 
         for (int j = 0; j < cols; j++)
         {
            matrix[i][j] = new BoardPosition(i, j);
         }
      }
   }

   public Iterator<ConstBoardPosition> iterator()
   {
      return new BoardIterator();
   }

   /**
    * Resets the board to the initial state
    */
   public void reset(){
      for (int i = 0; i < rows; i++)
      {
         for (int j = 0; j < cols; j++)
         {
            matrix[i][j].clear();
         }
      }
   }

   /**
    * Places a game piece on the board
    * @param p: the game piece to place on the board
    * @param pos: the position where to place the game piece
    * @return true on success, false on failure
    */
   public boolean setPiece(GamePiece p, ConstBoardPosition pos){
      int row = pos.getRow();
      int col = pos.getCol();
      if (row < cols && col < rows)
      {
         return matrix[row][col].addGamePiece(p);
      }
      return false;
   }

   /**
    * Determines if the winning state has been reached
    */
    public abstract boolean hasWinner(); 
 
   /**
    * Determines if the board has any open positions left
    */
   public boolean hasOpenPositions(){
      for (int i = 0; i < rows; i++)
      {
         for (int j = 0; j < cols; j++)
         {
            if (matrix[i][j].isOpen())
            {
               return true;
            }
         }
      }
      return false;
   }

   public boolean isPositionOpen(ConstBoardPosition pos){
      int row = pos.getRow();
      int col = pos.getCol();
      if (row <= 3 && row >= 0 && col < 3 && col >=0)
      {
          return (matrix[row][col].isOpen());
      }
      return false;
   }
   /**
    * Displays the current state of the board
    */
   public void display(){
      for (int i = 0; i < rows; i++)
      {
         System.out.println("------");
         System.out.print('|');
         for (int j = 0; j < cols; j++)
         {
             matrix[i][j].display();
             System.out.print('|');
         }
         System.out.print('\n');
      }
      System.out.println("------");
   }

   public abstract void disable();

   /**
    * Iterator class
    */
   private class BoardIterator implements Iterator<ConstBoardPosition>
   {
      private int position;
      public BoardIterator()
      {
         position = -1;
      }

      public boolean hasNext()
      {
         return position < rows * cols;
      }

      public ConstBoardPosition next()
      {
         if (hasNext() )
         {
            position++;
            int row = position/cols;
            int col = position % cols;
            return matrix[row][col];
         }
         throw new NoSuchElementException();
      }

      public void remove()
      {
         throw new UnsupportedOperationException();
      }
   }

}
