import java.util.Vector;
import java.util.Observable;
import java.awt.Color;

/**
 * The <code>Board</code> class manages all static information about
 * the board, such as size, location multipliers.
 * Instances of boards can be created to represent games, evaluate
 * plays and detect (in)valid moves.
 * @author  Rimon Barr
 * @version 1.0
 */

class Board extends Observable {

  ///////////////////////////////////////////////
  // INSTANCE
  ///////////////////////////////////////////////

  ///////////////////////////
  // FIELDS
  ///////////////////////////

  /**
   * Pieces on this board
   *   null represents empty tile
   */
  private Piece pieces[][];

  ///////////////////////////
  // METHODS
  ///////////////////////////
  
  /**
   * Create an empty board
   */
  public Board() {
    pieces=new Piece[SIZE][];
    for(int i=0; i<SIZE; i++) 
      pieces[i]=new Piece[SIZE];
  }
  
  /**
   * Return piece (if exists) at a given row, col
   * @param int row
   * @param int col
   * @return piece at (row,col)
   */
  public Piece getPiece(int row, int col) {
    return pieces[row][col];
  }

  /**
   * Set piece at a given row, col
   * @param int row
   * @param int col
   * @param Piece piece
   */
  public void setPiece(int row, int col, Piece p) {
    pieces[row][col]=p;
    setChanged();
    notifyObservers();
  }
    
  /**
   * Clear piece at a given row, col
   * @param int row
   * @param int col
   */
  public void clearPiece(int row, int col) {
    setPiece(row, col, null);
  }

  /**
   * Construct string representation of board
   */
  public String toString() {
    StringBuffer s=new StringBuffer("");
    for(int row=0; row<SIZE; row++)
      for(int col=0; col<SIZE; col++) {
        Piece p=pieces[row][col];
        if(p==null)
          s.append(' ');
        else {
          if(pieces[row][col] instanceof WildcardPiece) 
            s.append(WildcardPiece.WILDCARD);
          s.append(pieces[row][col].getLetter());
        }
      }
    return s.toString();
  }

  /**
   * Construct board from string representation
   */
  public void fromString(String s) {
    int pos=0;
    int row=0, col=0;
    Piece newpieces[][]=new Piece[SIZE][SIZE];
    while(pos<s.length()) {
      char c=s.charAt(pos);
      Piece p;
      if(c==' ')
        p=null;
      else if(c!=WildcardPiece.WILDCARD)
        p=new Piece(c);
      else {
        WildcardPiece w=new WildcardPiece();
        pos++;
        c=s.charAt(pos);
        if(c!=WildcardPiece.WILDCARD)
          w.setLetter(c);
        p=w;
      }
      newpieces[row][col]=p;
      pos++;
      col++;
      if(col==SIZE) {
        row++;
        col=0;
      }
    }
    pieces=newpieces;
    setChanged();
    notifyObservers();
  }
    

  ///////////////////////////////////////////////
  // STATIC
  ///////////////////////////////////////////////

  ///////////////////////////
  // FIELDS
  ///////////////////////////

  /**
   * Normal square
   */
  public static final int SIZE = 15;

  /**
   * Normal square
   */
  public static final int NRM = 0;

  /**
   * Double letter square
   */
  public static final int LX2 = 1;

  /**
   * Triple letter square
   */
  public static final int LX3 = 2;

  /**
   * Double word square
   */
  public static final int WX2 = 3;

  /**
   * Triple word square
   */
  public static final int WX3 = 4;

  /**
   * Board square colors
   */
  private static final Color COLOR[] = {
    Color.orange.darker(), Color.cyan, Color.blue, Color.pink, Color.red
  };


  /**
   * Board square values
   */
  private static final int BOARD[][] = {
    {WX3,NRM,NRM,LX2,NRM,NRM,NRM,WX3,NRM,NRM,NRM,LX2,NRM,NRM,WX3},
    {NRM,WX2,NRM,NRM,NRM,LX3,NRM,NRM,NRM,LX3,NRM,NRM,NRM,WX2,NRM},
    {NRM,NRM,WX2,NRM,NRM,NRM,LX2,NRM,LX2,NRM,NRM,NRM,WX2,NRM,NRM},
    {LX2,NRM,NRM,WX2,NRM,NRM,NRM,LX2,NRM,NRM,NRM,WX2,NRM,NRM,LX2},
    {NRM,NRM,NRM,NRM,WX2,NRM,NRM,NRM,NRM,NRM,WX2,NRM,NRM,NRM,NRM},
    {NRM,LX3,NRM,NRM,NRM,LX3,NRM,NRM,NRM,LX3,NRM,NRM,NRM,LX3,NRM},
    {NRM,NRM,LX2,NRM,NRM,NRM,LX2,NRM,LX2,NRM,NRM,NRM,LX2,NRM,NRM},
    {WX3,NRM,NRM,LX2,NRM,NRM,NRM,WX2,NRM,NRM,NRM,LX2,NRM,NRM,WX3},
    {NRM,NRM,LX2,NRM,NRM,NRM,LX2,NRM,LX2,NRM,NRM,NRM,LX2,NRM,NRM},
    {NRM,LX3,NRM,NRM,NRM,LX3,NRM,NRM,NRM,LX3,NRM,NRM,NRM,LX3,NRM},
    {NRM,NRM,NRM,NRM,WX2,NRM,NRM,NRM,NRM,NRM,WX2,NRM,NRM,NRM,NRM},
    {LX2,NRM,NRM,WX2,NRM,NRM,NRM,LX2,NRM,NRM,NRM,WX2,NRM,NRM,LX2},
    {NRM,NRM,WX2,NRM,NRM,NRM,LX2,NRM,LX2,NRM,NRM,NRM,WX2,NRM,NRM},
    {NRM,WX2,NRM,NRM,NRM,LX3,NRM,NRM,NRM,LX3,NRM,NRM,NRM,WX2,NRM},
    {WX3,NRM,NRM,LX2,NRM,NRM,NRM,WX3,NRM,NRM,NRM,LX2,NRM,NRM,WX3}
  };

  ///////////////////////////
  // METHODS
  ///////////////////////////

  public static int getSquareValue(int row, int col) {
    return BOARD[row][col];
  }

  public static Color getSquareColor(int row, int col) {
    return COLOR[BOARD[row][col]];
  }
}
