/** model an nxn Magic Square Board.
 */
import java.util.Random;
public class MagicSquareBoard {
  // The board is an nxn collection of tiles, but
  // we don't know what n is until the board is instantiated
  private Tile[][] tileGrid; // 
  private Tile specialTile; // keep track of tile with special symbol
  private int size; // number of rows or columns
  // each MagicSquareBoard has its own random number generator
  private Random random= new Random();

  /** constructor: create a MagicSquareBoard for an nxn game
   *  with the values filled in row-by-row in numerical order,
   *  and the very last tile "*".
   */
  public MagicSquareBoard(int n) {
    size= n; // remember grid size
    tileGrid= new Tile[n][n]; // instantiate grid
    loadTileGrid(n); // load values into grid
    loadTileGridNeighbours(n); // record neighbours
  }

  /** constructor: create a MagicSquareBoard for an nxn game
   *  with the values filled in row-by-row in random order,
   *  with a random tile having "*".
   */
  public MagicSquareBoard(int n, String s) {
    this(n); // set up natural layout
    randomize(); // shuffle the values around
  }

  /** loadTileGrid: load n*n values into tileGrid
   */
  public void loadTileGrid(int n) {
    // place numerals in tiles, from left to right,
    // and top to bottom
    for (int i=0; i < n; i++) {
      for (int j=0; j < n; j++) {
      tileGrid[i][j]= new Tile("");
	tileGrid[i][j].setValue("" + ((i * n) + j + 1));
      }
    }
    // the special symbol starts in the lower right tile
    specialTile = tileGrid[n-1][n-1];
    specialTile.setValue("*");
  }

  /** loadTileGridNeighbours: record the neighbours of n*n
   *  tiles.
   */
  public void loadTileGridNeighbours(int n) {
    for (int i=0; i < n; i++) {
      for (int j=0; j < n; j++) {
	// default is no neighbours
	Tile leftNeighbour= null,
	  rightNeighbour= null,
	  topNeighbour=null,
	  bottomNeighbour= null;
	// add neighbour if one exists
	if (j > 0) { leftNeighbour= tileGrid[i][j - 1]; }
	if (j < n-1) { rightNeighbour= tileGrid[i][j + 1]; }
	if (i > 0) { topNeighbour= tileGrid[i - 1][j]; }
	if (i < n-1) { bottomNeighbour= tileGrid[i + 1][j]; }
	tileGrid[i][j].setNeighbours(leftNeighbour, rightNeighbour,
				 topNeighbour, bottomNeighbour);
      }
    }
  }

  /** randomize: permute the n*n values of this
   *  MagicSquareBoard.  NB: this doesn't permute
   *  each square's neighbours.
   */
  private void randomize() {
    String tmpValue= "";
    int row, column;
    // swap each tile's value with a random tile from
    // this board
    for (int i= 0; i != size; i++)
      for (int j= 0; j != size; j++) {
	row= random.nextInt(size);
	column= random.nextInt(size);
	tmpValue= tileGrid[i][j].getValue();
	tileGrid[i][j].setValue(tileGrid[row][column].getValue());
	tileGrid[row][column].setValue(tmpValue);
	// update specialTile, if necessary
	if (tileGrid[i][j] == specialTile) {
	  specialTile= tileGrid[row][column];
	}
	else if (tileGrid[row][column] == specialTile) {
	  specialTile= tileGrid[i][j];
	}
      }
  }
  
  /** toString: show this MagicSquareBoard
   */
  public String toString() {
    String result= "";
    for (int i= 0; i < size; i++) {
      result += "\n";
      for (int j= 0; j < size; j++) {
	result += tileGrid[i][j].getValue() + "\t";
      }
    }
    result +="\n";
    return result;
  }

  /** swap: Attempt to swap special symbol with n,
   *  a numeral in the range 0..(size*size - 1)
   */
  public String swap(String n) {
    Tile tmpTile; // keep track of specialTile
    // tell user if the input is bad
    if (n.equals("") ||
	Integer.parseInt(n) < 0 ||
	Integer.parseInt(n) > size * size - 1) {
      return "illegal choice --- out of range\n";
    }
    else {
      tmpTile= specialTile.swap(n);
    }
    // tell user if the numeral is not adjacent to special character
    if (tmpTile == specialTile) { // swap wasn't possible
      return "illegal choice --- not adjacent\n";
    }
    else {
      specialTile= tmpTile; // swap changes specialTile
      return "okay\n";
    }
  }
}

