#include <time.h>
#include "AICompetitionWindow.h"
#include "TestWin.h"
#include "Muele.h"
#include "LookUpTable.h"
#include "NeuralNetwork.h"

CAICompetitionWindow::CAICompetitionWindow(CMuele *pMueleClass) : pMuele(pMueleClass)
{
	gui::IGUIEnvironment *pGuiEnv = this->pMuele->pGuiEnv;

	pWindow = pGuiEnv->addWindow(core::rect<s32>(pMuele->pDriver->getScreenSize().Width / 2 - 115,
			pMuele->pDriver->getScreenSize().Height / 2 - 240, pMuele->pDriver->getScreenSize().Width / 2 + 115, 
			pMuele->pDriver->getScreenSize().Height / 2 - 80), false, L"AI Competition");

	s32 fontHeight = pMuele->pGuiFont->getDimension(L"X").Height;
	s32 lineHeight = fontHeight + 4;
	s32 yPos = fontHeight + 10;
	s32 xEnd = pWindow->getRelativePosition().getWidth() - 4;

	s32 xPos = 40;
	pWindow->addChild(pGuiEnv->addCheckBox(true, core::rect<s32>(xPos, yPos, xPos + 170, yPos+fontHeight), 0, ID_CHECK_WEAKEN1, L"weaken player 1"));
	yPos+=lineHeight;
	pWindow->addChild(pGuiEnv->addCheckBox(true, core::rect<s32>(xPos, yPos, xPos + 170, yPos+fontHeight), 0, ID_CHECK_WEAKEN2, L"weaken player 2"));
	((gui::IGUICheckBox*)pMuele->pGuiEnv->getRootGUIElement()->getElementFromId(ID_CHECK_WEAKEN2, true))->setChecked(false);
	yPos-=lineHeight / 2;
	xPos=3;
	yPos+=lineHeight*2;
	pWindow->addChild(pGuiEnv->addButton(core::rect<s32>(xPos, yPos, xEnd, yPos+fontHeight), 0, ID_BUTTON_START_COMPETITION, L"start competition"));
	yPos+=lineHeight+5;
	pTextPlayer1=pGuiEnv->addStaticText(L"Player 1 wins: ", core::rect<s32>(xPos, yPos, xEnd, yPos+fontHeight), true, true, 0, -1, false);
	pWindow->addChild(pTextPlayer1);	
	yPos+=lineHeight;
	pTextDraw=pGuiEnv->addStaticText(L"        draws:", core::rect<s32>(xPos, yPos, xEnd, yPos+fontHeight), true, true, 0, -1, false);
	pWindow->addChild(pTextDraw);	
	yPos+=lineHeight;
	pTextPlayer2=pGuiEnv->addStaticText(L"Player 2 wins: ", core::rect<s32>(xPos, yPos, xEnd, yPos+fontHeight), true, true, 0, -1, false);
	pWindow->addChild(pTextPlayer2);	

	pWindow->getCloseButton()->setVisible(false);
	pWindow->addChild(pGuiEnv->addButton(pWindow->getCloseButton()->getRelativePosition(), 0, ID_BUTTON_CLOSE_COMP, L"x"));

	pWindow->updateAbsolutePosition();
}

/********************************************************************/

CAICompetitionWindow::~CAICompetitionWindow(void)
{
}

/********************************************************************/

void CAICompetitionWindow::toggleVisiblility()
{
	pWindow->setVisible(!pWindow->isVisible());
	pMuele->pGuiEnv->getRootGUIElement()->bringToFront(pWindow);
}

/********************************************************************/

void CAICompetitionWindow::onGuiEvent(SEvent &event)
{
	if ( event.EventType == EET_GUI_EVENT )
	{
		s32 id = event.GUIEvent.Caller->getID();
		gui::IGUIElement* root = pMuele->pGuiEnv->getRootGUIElement();

		switch( event.GUIEvent.EventType )
		{
		case gui::EGET_CHECKBOX_CHANGED:
			switch(id)
			{
			case ID_CHECK_WEAKEN1:
				((gui::IGUICheckBox*)root->getElementFromId(ID_CHECK_WEAKEN1, true))->setChecked(true);
				((gui::IGUICheckBox*)root->getElementFromId(ID_CHECK_WEAKEN2, true))->setChecked(false);
				break;
			case ID_CHECK_WEAKEN2:
				((gui::IGUICheckBox*)root->getElementFromId(ID_CHECK_WEAKEN1, true))->setChecked(false);
				((gui::IGUICheckBox*)root->getElementFromId(ID_CHECK_WEAKEN2, true))->setChecked(true);
				break;
			}
		break;
		case gui::EGET_BUTTON_CLICKED:
			if ( id == ID_BUTTON_START_COMPETITION ) competition();
			if ( id == ID_BUTTON_CLOSE_COMP ) toggleVisiblility();
			break;
		}
		if ( pMuele->playerOneType == PLAYER_TYPE_HUMAN || pMuele->playerTwoType == PLAYER_TYPE_HUMAN )
			((gui::IGUIButton*)root->getElementFromId(ID_BUTTON_START_COMPETITION, true))->setVisible(false);
		else 
			((gui::IGUIButton*)root->getElementFromId(ID_BUTTON_START_COMPETITION, true))->setVisible(true);
	}
}

/********************************************************************/

void CAICompetitionWindow::competition()
{
	gui::IGUIElement* root = pMuele->pGuiEnv->getRootGUIElement();
	char weakPlayer = ((gui::IGUICheckBox*)root->getElementFromId(ID_CHECK_WEAKEN1, true))->isChecked()?PLAYER_1:PLAYER_2;

//	s = root->getElementFromId(ID_EDIT_WEAKEN, true)->getText();
//	weakenValue = atoi(s.c_str());

	register char *pBoard  = new char[pMuele->boardFieldCount];

	CTestWin testWinPlayer1( pBoard , NULL, pMuele->boardSizeX, pMuele->boardSizeY, pMuele->boardSizeZ, PLAYER_1, pMuele->winFieldCount, 1);
	CTestWin testWinPlayer2( pBoard , NULL, pMuele->boardSizeX, pMuele->boardSizeY, pMuele->boardSizeZ, PLAYER_2, pMuele->winFieldCount, 1);

	char actualPlayer;
	int move;
	int wonPlayer1=0;
	int wonPlayer2=0;
	int draws=0;
	core::stringw str;
	int randomField;
   	
	srand( (unsigned)time( NULL ) );
   
	for ( long loopCount = 0; loopCount < 10000; loopCount ++ )
	{
		// show progress
		if ( loopCount % 500 == 0 )
		{
			str = int(loopCount / 100);
			str+="%";
			((gui::IGUIButton*) pMuele->pGuiEnv->getRootGUIElement()->getElementFromId(ID_BUTTON_START_COMPETITION, true))->setText(str.c_str());
			pMuele->pDriver->beginScene(false, false, video::SColor(0, 40, 40, 40));
			str = "Player 1 wins: ";
			str += wonPlayer1;
			if ( weakPlayer == PLAYER_2 && wonPlayer2 == 0 ) str+="(great!)";
			pTextPlayer1->setText(str.c_str());
			str = "        draws: ";
			str += draws;
			this->pTextDraw->setText(str.c_str());
			str = "Player 2 wins: ";
			str += wonPlayer2;
			if ( weakPlayer == PLAYER_1 && wonPlayer1 == 0 ) str+="(great!)";
			pTextPlayer2->setText(str.c_str());
			pMuele->pAICompetitionWindow->pWindow->draw();
			pMuele->pDriver->endScene();
			((gui::IGUIButton*) pMuele->pGuiEnv->getRootGUIElement()->getElementFromId(ID_BUTTON_START_COMPETITION, true))->setText(L"start competition");
		}

		memset(pBoard, 0, pMuele->boardFieldCount );
		actualPlayer = PLAYER_1;

		// play one complete game
		for ( move = 0; move < pMuele->boardFieldCount; move++ )
		{
			// make a random move sometimes
			if ( weakPlayer == actualPlayer && (rand() % ( ( pMuele->boardFieldCount  ) - ( move ) ) == 0) )
			{
				for ( int j = 0; j < pMuele->boardFieldCountPlain; j++ )
				{
					randomField =(rand()%(pMuele->boardFieldCountPlain));
					for ( int k = randomField; k < pMuele->boardFieldCount; k+=pMuele->boardFieldCountPlain )
						if ( pBoard[k] == EMTY_FIELD )
						{
							pBoard[k] = actualPlayer;
							goto weiter;
						}
				}
				for ( int j = 0; j < pMuele->boardFieldCountPlain; j++ )
					for ( int k = j; k < pMuele->boardFieldCount; k+=pMuele->boardFieldCountPlain )
						if ( pBoard[k] == EMTY_FIELD) 
						{
							pBoard[k] = actualPlayer;
							goto weiter;
						}
				weiter:;
			}
			else // make the best rated move
			switch ( actualPlayer )
			{
			case PLAYER_1:
				switch ( pMuele->playerOneType )
				{
				case PLAYER_TYPE_AILT:
					pBoard[pMuele->pLookUpTable->getBestMove(pBoard, actualPlayer)] = actualPlayer;
					break;
				case PLAYER_TYPE_AINN:
					pBoard[pMuele->pNeuralNetwork->getBestMove(pBoard, actualPlayer)] = actualPlayer;
					break;
				}
				break;
			case PLAYER_2:
				switch ( pMuele->playerTwoType )
				{
				case PLAYER_TYPE_AILT:
					pBoard[pMuele->pLookUpTable->getBestMove(pBoard, actualPlayer)] = actualPlayer;
					break;
				case PLAYER_TYPE_AINN:
					pBoard[pMuele->pNeuralNetwork->getBestMove(pBoard, actualPlayer)] = actualPlayer;
					break;
				}
				break;
			}

			// test for a winner
			if ( actualPlayer == PLAYER_1 )
			{
				if ( testWinPlayer1.testWin() )
					{
						wonPlayer1++;
						goto endLoop;
					}
			}
			else
			{
				if ( testWinPlayer2.testWin() )
					{
						wonPlayer2++;
						goto endLoop;
					}
			}

			if ( actualPlayer == PLAYER_1 ) actualPlayer = PLAYER_2; else actualPlayer = PLAYER_1; 
		} // play one complete game loop
		draws++;
		endLoop:;
	}
			
	str = "Player 1 wins: ";
	str += wonPlayer1;
	if ( weakPlayer == PLAYER_2 && wonPlayer2 == 0 ) str+="(great!)";
	pTextPlayer1->setText(str.c_str());
	str = "        draws: ";
	str += draws;
	this->pTextDraw->setText(str.c_str());
	str = "Player 2 wins: ";
	str += wonPlayer2;
	if ( weakPlayer == PLAYER_1 && wonPlayer1 == 0 ) str+="(great!)";
	pTextPlayer2->setText(str.c_str());

   	delete[] pBoard;
}
