#include <sphelper.h>
#include <windows.h>
#include <string>
#include <fstream>

#include "GUI_App.h"
#include "Demo.h"
#include "GameData.h"
#include "Ball.h"
#include "Marionette.h"
#include "App.h"
#include "LogicPlayer.h"

#define GRAMMAR_ID 10
#define COMMAND_RULE 420
#define WM_RECOEVENT WM_USER+190
#define SPEECH_THRESHOLD 90

#define DISPLAY_LOADING_SCREEN 0
#define DISPLAY_END_OF_ROUND 1
#define DISPLAY_END_OF_MATCH 2
#define DISPLAY_ROUND 3
#define DISPLAY_SELECTION_SCREEN 4
#define DISPLAY_HELP_SCREEN 5

#define POS_REINF_TXT	L"HELL YEAH"
#define NEG_REINF_TXT	L"STOP THAT"
#define NEXT_ROUND_TXT	L"NEXT ROUND"
#define NEW_MATCH_TXT	L"NEW MATCH"
#define HELP_TXT		L"HELP"
#define POS_REINF_ID	129
#define NEG_REINF_ID	130
#define NEXT_ROUND_ID	131
#define NEW_MATCH_ID	132
#define HELP_ID			133
#define REINF_AMT		100

CComPtr<ISpRecognizer>  g_cpEngine;
CComPtr<ISpRecoContext> g_cpRecoCtxt;
CComPtr<ISpRecoGrammar> g_cpCmdGrammar;

Demo* g_demo;
HWND g_hwnd;

#include <iostream>
using namespace std;
using namespace dojo;

Demo::Demo(App* _app) : DApplet(_app), app(_app), gui_app(_app->gui_app) {
    logo = Texture::fromTwoFiles("dojo-color.png", "dojo-alpha.png", TextureFormat::RGBA8, Texture::CLAMP);
	gameUI = new GameUI(app);

	game = new GameData(this);

	//get a handle to the UI display to show the score
	//scoreHandle = gameUI->addText(app->debugFont,12,Vector2(10,10),"Score", Color3::white());
}

Demo::~Demo()
{
	delete game;
	cleanup_sapi();
}

void Demo::onInit()  {
    DApplet::onInit();

    // Called before Demo::run() beings
    app->setApplet(this);

	g_demo = this;

	alwaysAssertM(SUCCEEDED(init_sapi()), "SPEECH RECOGNITION FAILED TO INITIALIZE!");

	match_going = false;
	round_going = false;
	prev_code = DISPLAY_LOADING_SCREEN;
	display_code = DISPLAY_LOADING_SCREEN;

    app->debugController.setActive(false);

	ai_timed_decisions=true;
	ai_cycle_pos = 1;
	ai_cycle_len = 1;

	save_time = 0;

	pureDeltaMouse = true;

	check_time = false;
	time_left = 0;
	num_chosen = -1;

	player = enemy = 0;
	ai_player = ai_enemy = 0;

	alwaysAssertM(SUCCEEDED(setup_player_commands()), "COULDN'T SETUP PLAYERS MOVES!");

	game->match.load_textures();

	load_available_players();

	player1_name = gameUI->addText(app->debugFont, 12, Vector2(15, 30), "Player 1", Color3::white(), Color3::red());
	player2_name = gameUI->addText(app->debugFont, 12, Vector2(710, 30), "Player 2", Color3::white(), Color3::blue());
	red_text = gameUI->addText(app->debugFont, 12, Vector2(10, 0), "", Color3::red(), Color3::black());

}

void Demo::load_available_players()
{
	ifstream players("conf\\players.tomo");
	alwaysAssertM(players, "CAN'T LOAD PLAYERS FILE!");

	string buf;
	getline(players, buf);
	while (getline(players, buf))
	{
		key_value kv(buf);
		PLAYER_ID id;
		string_to(kv.key, id);
		avail_players.push_back(name_id_pair(kv.value, id));
	}

	
	avail_player_names = new wxString[avail_players.size()];

	for (int i=0; i < avail_players.size(); i++)
		avail_player_names[i] = wxString(avail_players[i].name.c_str());
	
	gui_app->numPlayers = avail_players.size();
	gui_app->availPlayers = avail_player_names;
}

HRESULT Demo::setup_player_commands()
{
	SPSTATEHANDLE	hCommandRuleHandle;

    g_cpCmdGrammar->GetRule(NULL, COMMAND_RULE, 
                    SPRAF_TopLevel | SPRAF_Active | SPRAF_Dynamic, 
                    TRUE, &hCommandRuleHandle);

	g_cpCmdGrammar->ClearRule(hCommandRuleHandle);

	SPPROPERTYINFO prop;
    prop.pszName = L"Id";
    prop.pszValue = L"Property";
	prop.vValue.vt = VT_I4;

	if (player != 0)
	{
		for (int i=0; i < player->moveCount(); i++)
		{
			CSpDynamicString name(player->getMove(i)->name());
			prop.vValue.ulVal = i;
			g_cpCmdGrammar->AddWordTransition(hCommandRuleHandle, NULL, name, L" ", SPWT_LEXICAL, 1, &prop);
		}
	}

	// setup standard voice commands
	prop.vValue.ulVal = POS_REINF_ID;
	g_cpCmdGrammar->AddWordTransition(hCommandRuleHandle, NULL, POS_REINF_TXT, L" ", SPWT_LEXICAL, 1, &prop);

	prop.vValue.ulVal = NEG_REINF_ID;
	g_cpCmdGrammar->AddWordTransition(hCommandRuleHandle, NULL, NEG_REINF_TXT, L" ", SPWT_LEXICAL, 1, &prop);

	prop.vValue.ulVal = NEXT_ROUND_ID;
	g_cpCmdGrammar->AddWordTransition(hCommandRuleHandle, NULL, NEXT_ROUND_TXT, L" ", SPWT_LEXICAL, 1, &prop);

	prop.vValue.ulVal = NEW_MATCH_ID;
	g_cpCmdGrammar->AddWordTransition(hCommandRuleHandle, NULL, NEW_MATCH_TXT, L" ", SPWT_LEXICAL, 1, &prop);

	prop.vValue.ulVal = HELP_ID;
	g_cpCmdGrammar->AddWordTransition(hCommandRuleHandle, NULL, HELP_TXT, L" ", SPWT_LEXICAL, 1, &prop);

	g_cpCmdGrammar->Commit(0);

	// Set rules to active, we are now listening for commands
	return g_cpCmdGrammar->SetRuleIdState(COMMAND_RULE, SPRS_ACTIVE );
}

HRESULT Demo::init_sapi()
{
	HRESULT hr = S_OK;

	while ( 1 )
	{
		WNDCLASS window_class;
		window_class.style         = CS_HREDRAW | CS_VREDRAW;
		window_class.lpfnWndProc   = Demo::Reco_Event;
		window_class.cbClsExtra    = 0; 
		window_class.cbWndExtra    = 0;
		window_class.hInstance     = GetModuleHandle(NULL);
		window_class.hIcon         = LoadIcon(NULL, IDI_APPLICATION); 
		window_class.hCursor       = LoadCursor(NULL, IDC_ARROW);
		window_class.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
		window_class.lpszMenuName  = "KFT";
		window_class.lpszClassName = "CommandMsgWindow";

		if ( RegisterClass(&window_class) == 0 )
		{
			hr = -1;
			break;
		}

		g_hwnd = CreateWindowEx(0, "CommandMsgWindow", "", 0, 0, 0, 
						0, 0, HWND_MESSAGE, 0, GetModuleHandle(NULL), 0);

		if (g_hwnd == 0)
		{
			hr = -1;
			break;
		}

		// create a recognition engine
		hr = g_cpEngine.CoCreateInstance(CLSID_SpSharedRecognizer);
		if ( FAILED( hr ) )
		{
			break;
		}
       
		// create the command recognition context
		hr = g_cpEngine->CreateRecoContext( &g_cpRecoCtxt );
		if ( FAILED( hr ) )
		{
			break;
		}
	
		// Let SR know that window we want it to send event information to, and using
		// what message
		hr = g_cpRecoCtxt->SetNotifyWindowMessage(g_hwnd, WM_RECOEVENT, 0, 0);
		if ( FAILED( hr ) )
		{
			break;
		}

		// Tell SR what types of events interest us.  Here we only care about command
		// recognition.
		hr = g_cpRecoCtxt->SetInterest( SPFEI(SPEI_RECOGNITION), SPFEI(SPEI_RECOGNITION) );
		if ( FAILED( hr ) )
		{
			break;
		}

		// Load our grammar, which is the compiled form of simple.xml bound into this executable as a
		// user defined ("SRGRAMMAR") resource type.
		hr = g_cpRecoCtxt->CreateGrammar(GRAMMAR_ID, &g_cpCmdGrammar);
		if (FAILED(hr))
		{
			break;
		}
	    
		// set the sensitivity of the speech recognizer
		hr = g_cpEngine->SetPropertyNum(L"HighConfidenceThreshold", SPEECH_THRESHOLD);
		break;
	}

	// if we failed and have a partially setup SAPI, close it all down
	if ( FAILED( hr ) )
	{
		cleanup_sapi();
	}

	return ( hr );
}

LRESULT CALLBACK Demo::Reco_Event(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   switch (message) 
	{
        case WM_CREATE:
			return 0;

		case WM_NCCREATE:
			return true;

		case WM_NCCALCSIZE:
			return 0;
                    
        // This is our application defined window message to let us know that a
        // speech recognition event has occurred.
        case WM_RECOEVENT:
		{
			CSpEvent event;  
	
		    // Loop processing events while there are any in the queue
			while (event.GetFrom(g_cpRecoCtxt) == S_OK)
			{	
				// Look at recognition event only
				switch (event.eEventId)
				{
					case SPEI_RECOGNITION:
					g_demo->ExecuteCommand(event.RecoResult());
					break;
				}
			}
			return 0;
		}

        case WM_ERASEBKGND:
			return 1;

		case WM_GETMINMAXINFO:
			return 0;
        
		case WM_DESTROY:
			return 0;

		default:
			break;
   }
   return 0;
}

void Demo::ExecuteCommand(ISpPhrase *pPhrase)
{
	SPPHRASE *pElements;
	wchar_t* pwszText;
	pPhrase->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, &pwszText, NULL);

    if (SUCCEEDED(pPhrase->GetPhrase(&pElements)))
    {        
        switch ( pElements->Rule.ulId )
        {
            case COMMAND_RULE:
            {
				const SPPHRASEPROPERTY *pProp = pElements->pProperties;
				if (pProp->Confidence >= SP_HIGH_CONFIDENCE)
				{
					wcerr << "MOVE: " << pwszText << endl;

					switch(pProp->vValue.ulVal)
					{
						case POS_REINF_ID:
							game->input.reinforce(0, REINF_AMT);
							break;
						case NEG_REINF_ID:
							game->input.reinforce(0, -REINF_AMT);
							break;
						case NEXT_ROUND_ID:
							start_next_round();
							break;
						case NEW_MATCH_ID:
							prev_code = display_code;
							display_code = DISPLAY_SELECTION_SCREEN;
							break;
						case HELP_ID:
							toggle_help();
							break;
						default:
							game->input.give_command(0, pProp->vValue.ulVal);
							handleSelection(pProp->vValue.ulVal);
							break;
					}
				}

            }
			break;
        }
	}

    // Free the pElements memory which was allocated for us
    ::CoTaskMemFree(pElements);
	::CoTaskMemFree(pwszText);
}

void Demo::handleSelection(int move)
{

	num_chosen = move;
	time_left = 2.0;
	check_time = true;

	gameUI->setText(red_text, move_list[num_chosen]);
	gameUI->setPos(red_text, Vector2(10, 70 + 14 * num_chosen));
	//move_handles[num_chosen] = gameUI->addText(app->debugFont, 12, Vector2(10, 70 + 14 * num_chosen), 
	//	move_list[num_chosen], Color3::red(), Color3::black());
}

void Demo::cleanup_sapi()
{
	// Release grammar, if loaded
    if ( g_cpCmdGrammar )
    {
        g_cpCmdGrammar.Release();
    }
    // Release recognition context, if created
    if ( g_cpRecoCtxt )
    {
        g_cpRecoCtxt->SetNotifySink(NULL);
        g_cpRecoCtxt.Release();
    }
    // Release recognition engine instance, if created
	if ( g_cpEngine )
	{
		g_cpEngine.Release();
	}
}


void Demo::incrementGameScore(int amt, int pnum)
{ 
	game->match.incr_score(pnum, amt); 
}

Vector3 Demo::playerStartPosition(int i)
{
	if (i == 0)
		return spawnPosition;
	else
		return spawnPosition - Vector3(0, 0, 4);
}

void Demo::onCleanup() {
    // Called when Demo::run() exits
	delete gameUI;
}


void Demo::onNetwork() {
	// Poll net messages here
}

void Demo::onSimulation(RealTime rdt, SimTime sdt, SimTime idt) {
    DApplet::onSimulation(rdt, sdt, idt);

	if(check_time)
	{
		time_left -= sdt;

		if(time_left < 0.0)
		{
			check_time = false;
			
			gameUI->setText(red_text, "");
		}
	}

	save_time += sdt;

	if (save_time > 30)
	{
		game->save_players();
		save_time = 0;
	}

	if (!round_going)
		return;

	game->match.update_timer(sdt);

	Vector2 mouseXY;
	//pureDeltaMouse is a bool signifying if the camera is in mouse look mode
	if(pureDeltaMouse == false){
		mouseXY = Vector2::ZERO;
	}
	else{
		mouseXY = app->userInput->mouseDXY();
	}

	Vector3 pos;
	if(mouseXY == Vector2::ZERO){
		//if there is no change in the mouse position, place the camera behind the ball
		CoordinateFrame orig = app->debugCamera.getCoordinateFrame();
		orig.translation += (player->frame().translation - previousPlayerPosition);
		pos = orig.translation;
	}
	else{
		//if there is a change ion mouse position, rotate the camera accordingly
		double c = -.02;

		Vector3 up = Vector3::UNIT_Y;

		//create a roation matrix about the Y-axis based on horizontal mouse movement
		Matrix3 lrMat = Matrix3::fromAxisAngle(up, c*mouseXY.x);
		CoordinateFrame orig = app->debugCamera.getCoordinateFrame();

		orig.translation += (player->frame().translation - previousPlayerPosition);

		//update the positon of the camera based on the rotation matrix
		pos = (lrMat*(orig.translation-player->frame().translation)).unit()*3 + player->frame().translation;
		
		//create a rotation matrix about the X-axis of the ball based on vertical mouse movement
		Vector3 right = cross(up,(orig.translation-player->frame().translation).unit());
		
		Matrix3 udMat = Matrix3::fromAxisAngle(right, .25*c*mouseXY.y);
		
		//update the positon of the camera based on the rotation matrix
		pos = (udMat*(pos-player->frame().translation)).unit()*3 + player->frame().translation;

	}

	//player->onSimulation(sdt);
	// Track the player with the camera
	if (true == pureDeltaMouse) {
		app->debugCamera.setPosition(pos);
	}
	app->debugCamera.lookAt(player->frame().translation);
	previousPlayerPosition = player->frame().translation;


}

void Demo::onLogic()
{

	if (!round_going)
		return;

	if(game->match.check_round_over())
	{
		round_going = false;

		game->match.do_end_of_round();
		prev_code = display_code;
		if (game->match.check_game_over())
		{
			match_going = false;
			display_code = DISPLAY_END_OF_MATCH;
		}
		else
		{
			display_code = DISPLAY_END_OF_ROUND;
		}
		
		return;
	} 

	// AI CODE
	if (ai_cycle_pos == 0)
	{
		MOVE_ID move_choice[2];

		// calculate next move, execute it later, to avoid weirdness
		// where AI knows your next move before you perform it
		for (int i=0; i < 2; i++)
		{
			LogicPlayer* cur_player = game->players[i];

			if (cur_player->physics_player->isMoving())
				continue;

			move_choice[i] = cur_player->ai_player->calculate_next_move();
		}

		// perform the next move
		for (int i=0; i < 2; i++)
		{
			LogicPlayer* cur_player = game->players[i];

			if (cur_player->physics_player->isMoving())
				continue;

			STATE_VALUE delta = game->get_state_value(i, "OBJ_DELTA", false);
			STATE_VALUE distance = game->get_state_value(i, "DISTANCE", false);
			STATE_VALUE approach_speed = game->get_state_value(i, "OPP_APPROACH_SPEED", false);
			
			Move* move = cur_player->physics_player->selectMoveById(move_choice[i]);

			cerr << "PLAYER" << i << "\tD: " << distance << " Move: " << move->name() << " Approach Speed: " << approach_speed << " O: " << delta << endl << endl;
			
			G3D::CoordinateFrame f = cur_player->physics_player->frame();
			f.lookAt(game->players[1-i]->physics_player->frame().translation);
			cur_player->physics_player->turnTo(f);
			cur_player->physics_player->playMove();

			cur_player->state_inspector->end_ai_step();
			game->input.reset(i);
		}
	}

	if (ai_timed_decisions)
		ai_cycle_pos = (ai_cycle_pos + 1) % ai_cycle_len;
	else
		ai_cycle_pos = 1;
}

void Demo::onUserInput(UserInput* ui) {
    DApplet::onUserInput(ui);

	MSG message;
	while (PeekMessage(&message, 0, 0, 0, PM_REMOVE)) 
	{
        TranslateMessage(&message);
		DispatchMessage(&message);
	}

	if(app->userInput->keyPressed(SDLK_1))
	{
		game->match.decr_health(0, 5);
	}

	if(app->userInput->keyPressed(SDLK_2))
	{
		game->match.decr_health(1, 5);
	}

	//pureDeltaMouse is a bool signifying if the camera is in mouse look mode
	app->userInput->setPureDeltaMouse(pureDeltaMouse);
	app->debugTabSwitchCamera = false;

    if (app->userInput->keyPressed(SDLK_TAB)) {
        pureDeltaMouse = !pureDeltaMouse;
    }
	
    if (app->userInput->keyPressed(SDLK_g)) {
		game->input.reinforce(0, REINF_AMT);
	} else if (app->userInput->keyPressed(SDLK_b)) {
		game->input.reinforce(0, -REINF_AMT);
	} else if (app->userInput->keyPressed(SDLK_t)) {
		ai_timed_decisions = !ai_timed_decisions;
	} else if (app->userInput->keyPressed(SDLK_d)) {
		ai_cycle_pos = 0;
	} else if (app->userInput->keyPressed(SDLK_SPACE)) {
		if (!match_going)
		{
			prev_code = display_code;
			display_code = DISPLAY_SELECTION_SCREEN;
		}
		else if (!round_going)
		{
			start_next_round();
		}
	} else if (app->userInput->keyPressed(SDLK_h)) {
		toggle_help();
	}
}

void Demo::start_new_match(int p1, int p2, int num_rounds, int round_length)
{
	cur_players[0] = p1;
	cur_players[1] = p2;

	game->save_players();
	game->load(avail_players[p1].id, avail_players[p2].id);
	game->match.set_max_rounds(num_rounds);
	game->match.set_round_length(round_length);
	game->match.start();
	
	game->players[0]->name = avail_players[cur_players[0]].name;
	game->players[1]->name = avail_players[cur_players[1]].name;
	player = game->players[0]->physics_player;
	enemy = game->players[1]->physics_player;
	ai_player = game->players[0]->ai_player;
	ai_enemy = game->players[1]->ai_player;

	alwaysAssertM(SUCCEEDED(setup_player_commands()), "COULDN'T SETUP PLAYERS MOVES!");

	ai_cycle_pos = 0;
	match_going = true;
	round_going = true;

	gameUI->setText(player1_name, game->players[0]->name);
	gameUI->setText(player2_name, game->players[1]->name);

	int length = game->players[1]->name.size();
	gameUI->setPos(player2_name, Vector2(790-length*10, 30));


	for(int i = 0; i < move_handles.size(); i++)
	{
		gameUI->setText(move_handles[i], "");
	}

	gameUI->setText(red_text, "");

	move_list.clear();
	move_handles.clear();
	int y = 70;
	for(int i = 0; i < player->moveCount(); i++)
	{
		move_list.append(player->getMove(i)->name());

		move_handles.append(gameUI->addText(app->debugFont, 12, Vector2(10, y), move_list[i], Color3::white(), Color3::black()));
		y = y + 14;
	}

	red_text = gameUI->addText(app->debugFont, 12, Vector2(10, 0), "", Color3::red(), Color3::black());

	prev_code = display_code;
	display_code = DISPLAY_ROUND;

	app->debugCamera.setPosition(Vector3(0, 10, 0));
	app->debugCamera.lookAt(player->frame().translation);

}

void Demo::start_next_round()
{
	if (match_going && !round_going)
	{
		game->save_players();
		game->load(avail_players[cur_players[0]].id, avail_players[cur_players[1]].id);
		game->match.start_next_round();

		game->players[0]->name = avail_players[cur_players[0]].name;
		game->players[1]->name = avail_players[cur_players[1]].name;
		player = game->players[0]->physics_player;
		enemy = game->players[1]->physics_player;
		ai_player = game->players[0]->ai_player;
		ai_enemy = game->players[1]->ai_player;

		for(int i = 0; i < move_handles.size(); i++)
		{
			gameUI->setText(move_handles[i], "");
		}

		gameUI->setText(red_text, "");

		move_list.clear();
		move_handles.clear();

		int y = 70;
		for(int i = 0; i < player->moveCount(); i++)
		{
			move_list.append(player->getMove(i)->name());

			move_handles.append(gameUI->addText(app->debugFont, 12, Vector2(10, y), move_list[i], Color3::white(), Color3::black()));
			y = y + 14;
		}

		red_text = gameUI->addText(app->debugFont, 12, Vector2(10, 0), "", Color3::red(), Color3::black());


		ai_cycle_pos = 0;
		round_going = true;


		prev_code = display_code;
		display_code = DISPLAY_ROUND;

		app->debugCamera.setPosition(Vector3(0, 10, 0));
		app->debugCamera.lookAt(player->frame().translation);
	}
}

void Demo::return_to_previous()
{
		switch(prev_code)
		{
			case DISPLAY_LOADING_SCREEN:
			case DISPLAY_SELECTION_SCREEN:
			case DISPLAY_HELP_SCREEN:
				match_going = false;
				round_going = false;
				break;

			case DISPLAY_END_OF_ROUND:
				match_going = true;
				round_going = false;
				break;

			case DISPLAY_END_OF_MATCH:
				match_going = false;
				round_going = true;
				break;

			case DISPLAY_ROUND:
				match_going = true;
				round_going = true;
				break;
		}
		display_code = prev_code;
}

void Demo::toggle_help()
{
	if (display_code == DISPLAY_HELP_SCREEN)
	{
		return_to_previous();
	}
	else
	{
		match_going = false;
		round_going = false;
		prev_code = display_code;
		display_code = DISPLAY_HELP_SCREEN;
	}
}

void Demo::onGraphics(RenderDevice* rd) {

    World::world()->activeCamera = &app->debugCamera;
    rd->setProjectionAndCameraMatrix(*World::world()->activeCamera);
    
    World::world()->onGraphics(rd);

    // Draw the Dojo logo
    rd->push2D();

		game->match.display_hud(rd, gameUI);
		
		// display appropriately
		switch(display_code)
		{
			case DISPLAY_LOADING_SCREEN: // MAYBE DO SOMETHING NICE?
				game->match.display_loadscreen(rd);
				break;
			
			case DISPLAY_SELECTION_SCREEN:
			{
				if (!gui_app->selection_done)
				{
					match_going = false;
					round_going = false;
					gui_app->do_select_match = true;
				}
				else
				{
					if (gui_app->selectStatus == wxID_OK)
					{
						start_new_match(gui_app->P1Index, gui_app->P2Index, gui_app->numRounds, gui_app->roundLength);
					}
					else if (gui_app->selectStatus == wxID_CANCEL)
					{
						return_to_previous();
					}
					gui_app->selection_done = false;
				}
				gameUI->doUIGraphics(rd);
				break;
			}

			case DISPLAY_ROUND: // STANDARD STUFF
			
				/*for(int i = 0; i < move_list.size(); i++)
				{
					gameUI->setText(move_handles[i], move_list[i]);
				}*/
				gameUI->doUIGraphics(rd);
				
				break;
			
			case DISPLAY_END_OF_ROUND:
			{
				int winner = game->match.get_winner();
				switch(winner)
				{
					case 0: // PLAYER 1 WON ROUND
						game->match.display_player_win_round(rd, 0);
						break;
					case 1: // PLAYER 2 WON ROUND
						game->match.display_player_win_round(rd, 1);
						break;
					case 2: // ROUND ENDED IN A TIE
						game->match.display_tie(rd);
						break;
				}
				gameUI->doUIGraphics(rd);
				break;
			}

			case DISPLAY_END_OF_MATCH:
			{
				int p1_wins = game->match.get_num_wins(0);
				int p2_wins = game->match.get_num_wins(1);

				if (p1_wins > p2_wins) // PLAYER 1 WON THE MATCH
				{
					game->match.display_player_win_match(rd, 0);
				}
				else	// PLAYER 2 WON THE MATCH
				{
					game->match.display_player_win_match(rd, 1);
				}
				gameUI->doUIGraphics(rd);
				break;
			}

			case DISPLAY_HELP_SCREEN:
				game->match.display_helpscreen(rd);
				break;
		}

    rd->pop2D();
}
