/**
 * @(#)ScrabbleBuilder.java	11/03/05
 * 
 * Copyright 2005 3GP01, KCL.  All unmodified code is copyright of its respective owner.
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * The GNU General Public Licence should be contained within licence.txt;
 * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA  02110-1301, USA.
 */

import java.util.*;

/**
 * This class builds the board and loads the letter set from the information loaded by Dictionary
 * 
 * @author 3GP01 - Hardev Bhamra, Deepak Chandarana, James Tompkin
 * @version 2.0
 * @see Game
 * @see Dictionary
 * @see Board
 */

public class ScrabbleBuilder 
{
	private static List premiumSquares = new ArrayList();

	protected List alphabet = new ArrayList(); // of String

	protected List letters = new ArrayList(); // of Letter

	protected Map letterMap = new HashMap(); // String --> Letter

	public List getAlphabet() 
	{
		return alphabet;
	}

	public List getLetters() 
	{
		return letters;
	}

	public Letter getLetter(char ascii) 
	{
		String asc = "" + ascii;
		return (Letter) letterMap.get(asc);
	}

	public Letter getLetter(String symbol) 
	{
		return (Letter) letterMap.get(symbol);
	}

	public static Square[][] getBoard() 
	{
		Square[][] res = new Square[15][15];
		premiumSquares = new ArrayList();

		for (int i = 0; i < 15; i++) 
		{
			for (int j = 0; j < 15; j++) 
			{
				setOrdinarySquare(i, j, res);
			}
		}

		//SRABBLEBUILDER29
		//this for loop was in the wrong place, it was overwriting some TWS and TLS
		//this probably messed up the scoring, generating early game highs
		//
		//set diagonals to dws:
		for (int i = 0; i < 15; i++) 
		{
			setDoubleWS(i, i, res);
			setDoubleWS(i, 14 - i, res);
		}

		setDoubleLS(3, 7, res);
		setDoubleLS(11, 7, res);
		setDoubleLS(3, 0, res);
		setDoubleLS(11, 0, res);
		setDoubleLS(6, 2, res);
		setDoubleLS(8, 2, res);
		setDoubleLS(0, 3, res);
		setDoubleLS(7, 3, res);
		setDoubleLS(14, 3, res);
		setDoubleLS(2, 6, res);
		setDoubleLS(6, 6, res);
		setDoubleLS(8, 6, res);
		setDoubleLS(12, 6, res);
		setDoubleLS(2, 8, res);
		setDoubleLS(6, 8, res);
		setDoubleLS(8, 8, res);
		setDoubleLS(12, 8, res);
		setDoubleLS(3, 14, res);
		setDoubleLS(11, 14, res);
		setDoubleLS(6, 12, res);
		setDoubleLS(8, 12, res);
		setDoubleLS(0, 11, res);
		setDoubleLS(7, 11, res);
		setDoubleLS(14, 11, res);

		for (int x = 1; x <= 13; x = x + 4) 
		{
			setTripleLS(x, 5, res);
			setTripleLS(x, 9, res);
		}
		for (int x = 5; x <= 9; x = x + 4) 
		{
			setTripleLS(x, 1, res);
			setTripleLS(x, 13, res);
		}

		setTripleWS(0, 0, res);
		setTripleWS(7, 0, res);
		setTripleWS(14, 0, res);
		setTripleWS(0, 7, res);
		setTripleWS(14, 7, res);
		setTripleWS(0, 14, res);
		setTripleWS(7, 14, res);
		setTripleWS(14, 14, res);

		setCentreSquare(7, 7, res);
		return res;
	}

	private static void setTripleWS(int x, int y, Square[][] res) 
	{
		TripleWordSquare tws = new TripleWordSquare(x, y);
		premiumSquares.add(0, tws);
		res[x][y] = tws;
	}

	private static void setDoubleWS(int x, int y, Square[][] res) 
	{
		DoubleWordSquare dws = new DoubleWordSquare(x, y);
		premiumSquares.add(0, dws);
		res[x][y] = dws;
	}

	private static void setTripleLS(int x, int y, Square[][] res) 
	{
		TripleLetterSquare tls = new TripleLetterSquare(x, y);
		premiumSquares.add(0, tls);
		res[x][y] = tls;
	}

	private static void setDoubleLS(int x, int y, Square[][] res) 
	{
		DoubleLetterSquare dls = new DoubleLetterSquare(x, y);
		premiumSquares.add(0, dls);
		res[x][y] = dls;
	}

	private static void setOrdinarySquare(int x, int y, Square[][] res) 
	{
		OrdinarySquare os = new OrdinarySquare(x, y);
		res[x][y] = os;
	}

	private static void setCentreSquare(int x, int y, Square[][] res) 
	{
		CentreSquare cs = new CentreSquare(x, y);
		res[x][y] = cs;
	}

	/**
	 * Returns a List of all the premium squares on the board.
	 * 
	 * @return List
	 */
	public static List getPremiumSquares() 
	{
		return (List) ((ArrayList) premiumSquares).clone();
	}

	protected void addLetter(char sym, char asc, int s, int n, boolean isBlank) 
	{	// adds n copies of letter sym with score s
		alphabet.add("" + sym);
		letterMap.put("" + asc, new Letter(sym, s, asc));
		for (int i = 0; i < n; i++) 
		{
			Letter l = new Letter(sym, s, asc);
			l.blank = isBlank;
			letters.add(l);
		}
	}

	/**
	 * ScrabbleBuilder, when invoked, collects the list of letters loaded by Dictionary.
	 * These letter attributes are processed so that new Letters can be constructed, 
	 * creating a letter set with which to play the game.
	 */
	public ScrabbleBuilder() 
	{
		List lettersAttrib = Dictionary.getListOfLetters(); //get List of letters from dictionary
		//for each element in lettersAttrib
		for (int i = 0; i < lettersAttrib.size(); i++) {
			String unicode = lettersAttrib.get(i).toString().substring(2, 6);
			char asc = lettersAttrib.get(i).toString().charAt(6);
			String src = lettersAttrib.get(i).toString().substring(7, 9);
			int score = Integer.parseInt(src);
			String frq = lettersAttrib.get(i).toString().substring(9, 11);
			int frequency = Integer.parseInt(frq);
			char blk = lettersAttrib.get(i).toString().charAt(11);
			boolean blank = false;

			if (blk == '0') {
				blank = false;
			} else {
				blank = true;
			}

			unicode = "0x" + unicode; //turn unicode into absoulte hex representation

			Integer base10 = Integer.decode(unicode); //turn hex into base 10
			char sym = (char) base10.intValue(); //cast base10 unicode representation as char
			addLetter(sym, asc, score, frequency, blank);
		}
	}
}