#include "test_morpion.hpp"
#include "mcts_two_players.hpp"
#include "morpion.hpp"
#include <iostream>
#include <map>

using namespace std;


namespace game
{
	test_morpion::test_morpion()
	{
		cout << "=== Play tic tac toe ==="<<endl;
		cout << "Do you want to play a Player vs (P)layer or a Player vs (C)omputer match? (enter P or C) "<<endl;
		string choice;
		cin >> choice;
		if (choice == "P")
			play();
		else if (choice == "C")
			playout();
		else
			cout << "Bad choice." << endl;
	}
	
	/* Start a complete Player vs Player game */
	void test_morpion::play()
	{
		morpion mor;
		cout << "Player vs Player game!" << endl;
		while(!mor.end_of_game())
		{
			cout << mor << endl;
			cout << "It's " << mor.player_to_string(mor.current_player()) << " turn." << endl;
			map<string, int> movesMap;
			//cout << "Number of possible moves: " << mor.number_of_moves() << endl;
			cout << "Possible moves:";
			uint64_t possible_moves = mor.get_state().possible_moves;
			for(int i = 0; i < mor.number_of_moves(); i++)
			{
				uint16_t move = possible_moves & ((uint64_t) 15); //15 = 1111 (a move is on 4 bits)
				//cout << "Possible move: " << mor.move_to_string(move) << endl;
				cout << " " << mor.move_to_string(move);
				movesMap[mor.move_to_string(move)] = i; //In the map: the move as seen by the player and its representation for the computer
				possible_moves = possible_moves >> 4;
			}
			cout << endl << "Choose your move: ";
			string move;
			cin >> move;
			mor.play(movesMap[move]);
		}
		//Game ended: print the final state of the board
		cout << mor << endl;
		if (mor.won(0))
			cout << mor.player_to_string(0) << " has won" << endl;
		else if (mor.won(1))
			cout << mor.player_to_string(1) << " has won" << endl;
		else
			cout << "Draw! too bad :(" << endl;
		
	}
	
	/* Start a complete Player vs Computer game */
	void test_morpion::playout()
	{
		morpion mor;
		auto mctsPlayer = mcts::make_mcts_two_players(mor, 1000, 0.3, 4); // creation du player a partir du morpion. 1000: ms de reflexion 0.3 fateur d'exploration 4: nb_visit_before_expansion on attend d'etre arrive 4 fois sur un noeud avant de le developper
		cout << "Player vs Computer game!" << endl;
		cout << "Who's first? (P)layer or (C)omputer?" << endl;
		string choice;
		cin >> choice;
		int IAPlayer = 1; //Default: the computer will play second
		if (choice == "C") //If however we choosed to let the computer play first
			IAPlayer = 0;
		while(!mor.end_of_game())
		{
			cout << mor << endl;
			if(mor.current_player() == IAPlayer) //It's computer's turn
			{
				mctsPlayer.reset(); //Delete the entire tree: it will construct a new one starting from this state
				uint16_t move = mctsPlayer.select_move();
				//cout << "Computer played move number " << move << endl;
				mor.play(move);
			}
			else //Human turn to play
			{
				cout << "It's your time to shine!" << endl;
				map<string, int> movesMap;
				//cout << "Number of possible moves: " << mor.number_of_moves() << endl;
				cout << "Possible moves:";
				uint64_t possible_moves = mor.get_state().possible_moves;
				for(int i = 0; i < mor.number_of_moves(); i++)
				{
					uint16_t move = possible_moves & ((uint64_t) 15); //15 = 1111 (a move is on 4 bits)
					//cout << "Possible move: " << mor.move_to_string(move) << endl;
					cout << " " << mor.move_to_string(move);
					movesMap[mor.move_to_string(move)] = i; //In the map: the move as seen by the player and 
					possible_moves = possible_moves >> 4;
				}
				cout << endl << "Choose your move: ";
				string move;
				cin >> move;
				mor.play(movesMap[move]);
			}
		}
		//Game ended: print the final state of the board
		cout << mor << endl;
		if (mor.won(0))
			cout << mor.player_to_string(0) << " has won" << endl;
		else if (mor.won(1))
			cout << mor.player_to_string(1) << " has won" << endl;
		else
			cout << "Draw! too bad :(" << endl;
	}

}