#ifndef _BOARD_H
#define _BOARD_H

#include "Tile.h"

#include <qgrid.h>
#include <vector>
#include <string>

class QSizePolicy;
class QResizeEvent;

using std::vector;
using std::string;


const int MAX_COMPHAND=7;
const int BOARD_SIZE=15;


//	used with computer AI to determine best spot to put a word/////////////////////////
  struct RecommendedTile
{	
	char letter; // letter at position
	int position [2]; // coordinates of letter to play off of
	double FreeSpaces; // number of spaces for new letters weighted by bonuses on the board
	int before;// the number of spaces for new tiles before the old letter
	int after; // the number of spaces for new tiles after the old letter
	bool vertical;
};	


int min (int a, int b);

//***************************************************************************
//	Purpose:	determine if string is in dictionary
//
//	precondition: testme is not empty
//	postcondition:	true if testme is in dictionary
//
//	a very important function, its speed greatly affects the game speed
//***************************************************************************
bool IsWord(const string testme);

//***************************************************************************
//	Board Class
//
//	Purpose:	contain game logic necessary to play Scrabble
//
//	The board is the bulk of the program.  it tests and scores words, and also
//	houses the computer AI as the AI must have intimate knowledge of the board.
//	in QT, objects are more than abstract, they are visual objects, and so Board
//	also contains formatting information/functions, essentially everything
//***************************************************************************
class Board : public QGrid
{
	Q_OBJECT

	private:

		vector <vector<Boardspace*> > GameBoard;
				// holds pointers to the Boardspace pieces

		vector <vector<int> > new_positions;
				// tells the positions of the new pieces
		
		bool IsNew[BOARD_SIZE][BOARD_SIZE];
				// holds true if the tile is new, false if the tile has been confirmed

		const Tile* Register;
				// lets the board know what tile the player wants to use

		bool CompTurn, LastPlayerSkipped;
			//self explanatory, used in newTurn()

		int ComputerScore, PlayerScore;
			//duh

		int ScoreWord(const vector <int> start_position, const vector<int> end_position) const;
			//scores a word given at a certain position, used in FindAndScoreNewWords

		void resetTurn();
			//removes all new tiles from board, to start turn over


//  **************COMPUTER PLAYER STUFF********************************************************************** 
	private:
		void FindSimplePlaces() ;
		void List_Words	(vector <string> & words, vector <vector <int> > & start, vector<vector <int> > & end);
		void  copy(RecommendedTile & left, RecommendedTile Right);
		void sort_positions(); // puts the OpenSpots in order by highest FreeSpace
		int ScoreWord(const vector <int> start_position, const vector<int> end_position, const string letters) const;
		
		// will be replaced with FindWords from Vince .. these are for debugging purposes
		void Board::FindComputerWords(RecommendedTile Recommend, string hand, vector <string> & words, vector <vector <int> > &start, vector <vector <int> > &end);
		vector<string> Board::make_words(int letters_before, int letters_after, char orginal_letter, string hand)const;

		std::vector <Tile*> ComputerHand;
		std::vector<RecommendedTile> OpenSpots; // for suggested places to play
		Tile* TakeComputerTile(char tileLetter);

		bool isFirstTurn;


	public:

		void ComputerPlayWord();
			//function that plays computer AI

		int CompTilesInHand() const;
			//returns num of tiles in computer's hand

		void deleteComputerHand();
			//removes all tiles from computer's hand

		int computerHandValue() const;
			//returns total value of the tiles in hand

	public slots:

		void getComputerTile(int);
			//get a tile from tilebank

//*************************************************************************************************************


	public:

		Board(QWidget* parent=0, const char* name=0);
		~Board();
		
		void addTile(Tile *NewTile, int x_position, int y_position);
			//add a tile, used with computer

		Board& clearTile(int x_position, int y_position);
			//clear a tile! not really used, but there nonetheless

		void eraseBoard();
			//completely erases board and starts over
		
		//pretty obvious, not used much//////////////////////////////
		char getCharacter(int x_position, int y_position) const;
		int getLetterBonus(int x_position, int y_position) const;
		int getLetterID(int x_position, int y_position) const;
		int getValue(int x_position, int y_position) const;
		int getWordBonus(int x_position, int y_position) const;
		//////////////////////////////////////////////////////////////

		//duh
		int getPlayerScore() const;
		int getComputerScore() const;
		
		
		bool AreNewLettersOneWord()const;
			// tells if new letters form a single word.
			// NOTE word being defined as in a single, unbroken line
			// finds first and last tile position and sees if there are letters on tiles in between
			// makes sure there are no other positions besides those

		int FindAndScoreNewWords()const;
			// returns score of new words
			// return -1 if new words are not spelled correctly 
			// return -2 if the word isn't touching anything else on board
			//         (unless 7,7 (the start point) is one of the new letters, then returns score)
			// assumes the AreNewLettersOneWord function returns true
		
		QSizePolicy sizePolicy() const;
			//QT info about how it scales when you make the window bigger

	public slots:

		void setRegister(const Tile*);
			//this slot is used to connect the player to the board
			//so it knows which tile the player wants to lay down

		void newTurn();
			//when you want to end your turn, this goes through all the logic
			//when the next turn button is clicked

	protected slots:

		void resizeEvent(QResizeEvent*);
			//used to resize boardspaces inside board

	private slots:

		void boardClicked();
			//connects the buttons on the board to the register

	signals:

		void resetHand();
			//sent when the player's hand should be reset for a repeat turn

		void boardChanged();
		void boardChanged(int, int);
			//when the board has changed

		void boardClicked(int, int);
			//when the board is simply clicked on, changed or not

		void humanScoreChanged( int );
		void computerScoreChanged( int );
			//notifies the rest of the game when player score changes

		void gameOver();
			//when the game ends, as far as board knows, i.e. both players pass

};



#endif