import java.io.*;
import java.util.*;

/**
 *  class Mediocre
 *
 *  This is the main class of Mediocre
 *  which is used to connect to Winboard etc.
 *
 *  @author Jonatan Pettersson (zlaire@gmail.com)
 *  Date: 2006-12-27
 */

public class Mediocre implements Definitions
{
	private static BufferedReader reader;
	private static String command;
	public static Vector history;
	public static Book book; // Holds the methods for using the book
	public static boolean useBook; // Keeps track of still being in opening or not

	/**
	 *  The main method, initializes the reader
	 *  and calls winBoard.
	 *
	 *  @param String arguments
	 */
	public static void main(String args[]) throws IOException
	{
		book = Book.getInstance(); // Initialize the opening book
		book.readBook(); // Read in the book
		history = new Vector(); // Initialize the history

		if(args[0].charAt(0) == 'x') // If the first character in the first argument is 'x' we can safely assume it is xboard that called for the aplication
		{
			reader = new BufferedReader(new InputStreamReader(System.in)); // Initialize the reader
			winBoard(); // Call the winBoard method
		}


		else // If it was not xboard that called the application, we stop here
			System.out.println("Couldn't find WinBoard.");

			
	}
	//END main()
	
	/**
	 *  Handles input from the winBoard application
	 *  and also sends moves and settings from the engine.
	 *
	 */
	private static void winBoard() throws IOException
	{
		// We start with sending some information to the engine. All data is sent using
		// the System.out.println command.
		//
		// feature - A few special commands that can be sent at startup, more in Tim Mann's guide
		// myname - The name of the engine \" since we need the quotation marks inside the string
		// usermove - Makes winBoard send "usermove Ne4" instead of just "Ne4"
		// setboard - Uses the setboard feature instead of edit
		// done - We are now done with starting up and can begin
		System.out.println("feature myname=\"Mediocre Chess\" usermove=1 setboard=1 done=1");

		Board board = new Board(); // Create a board on which we will be playing
		board.inputFEN("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); // Start position
		
		useBook = true; // Strat with using opening book, if board is changes we make this false below
		
		String openingLine = ""; // Holds the opening line so far

		// This is the loop in which we look for incoming commands from WinBoard
		for(;;)
		{ 
			command = reader.readLine(); // Receive the input

			// A new game is starting so reset the board
			if(command.equals("new"))
			{
				history = new Vector(); // Reset the history
				useBook = true; // Use book
				openingLine = ""; // Initilize the opening line
				board.inputFEN("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); // Insert start position
			}

			// WinBoard is quitting, exit the engine
			if(command.equals("quit"))
			{
				System.exit(-1); // Exit the program
			} 
			if(command.startsWith("setboard"))
			{
				history = new Vector(); // Reset the history
				useBook = false; // Stop using book
				board.inputFEN(command.substring(9)); // Insert the submitted position
			}


			// Opponent played a move or told us to play from the position		
			if(command.startsWith("usermove") || command.equals("go"))
			{
				// The opponent made a move so play it on the board.				
				if(command.startsWith("usermove"))
				{					
					// Receive the move and play it on the board
					Move usermove = receiveMove(command.substring(9), board);
					openingLine += command.substring(9);
					board.makeMove(usermove);
					history.add(board.getShortFEN());
				}

				// The engines turn to move, so find the best line
				Engine.LineEval bestLine = new Engine.LineEval();
				

				if(useBook)
				{
					String bookMove = book.getBestMove(openingLine);

					if(bookMove.equals(""))
					{
						useBook = false;
						bestLine = Engine.search(board);
					}
					else
					{
						openingLine += bookMove;
						bestLine.line.add(receiveMove(bookMove, board));
					}
				}
				else bestLine = Engine.search(board);

				if(bestLine.line.size() != 0) // We have found a move to make
				{


					
					board.makeMove((Move)bestLine.line.get(0)); // Make best move on the board
					history.add(board.getShortFEN()); // Add it to history
					System.out.println("move " + ((Move)bestLine.line.get(0)).inputNotation()); // Tell winboard to make the move

				}
			}
			

		}



	}
	// END winBoard()
	
	/**
	 *  Takes an inputted move-string and matches it with a legal move generated
	 *  from the board
	 *
	 *  @param String The inputted move
	 *  @param Board The board on which to find moves
	 *  @return Move The matched move
	 */
	private static Move receiveMove(String move, Board board)
	{
		Vector legalMoves = board.generateMoves();

		for(int i = 0; i < legalMoves.size(); i++)
		{
			if(((Move)legalMoves.get(i)).inputNotation().equals(move))
				return (Move)legalMoves.get(i);
		}

		// If no move was found return null
		return null;
	}
	// END receiveMove()
	

	

}

