#include <irrlicht.h>
#include "PreferencesWindow.h"
#include "AICompetitionWindow.h"
#include "Muele.h"
#include "NeuralNetwork.h"
#include "NeuralNetworkWindow.h"

using namespace irr;

CPreferencesWindow::CPreferencesWindow(CMuele *pMueleClass, int yPosition) : pMuele(pMueleClass)
{
	gui::IGUIEnvironment *pGuiEnv = this->pMuele->pGuiEnv;

	pWindow = pGuiEnv->addWindow(core::rect<s32>(pMuele->pDriver->getScreenSize().Width - 300,
					yPosition, pMuele->pDriver->getScreenSize().Width, 400), false, L"Game Preferences");
	s32 yPos = 22;
	s32 yHeight = 20;
	s32 xStart = 3;
	s32 xEnd = pWindow->getRelativePosition().getWidth() - xStart - 1;
	s32 xPos = xStart + 50;
	pWindow->addChild(pGuiEnv->addStaticText(L"Board size:", core::rect<s32>(xStart, yPos, xEnd, yPos + 3 * yHeight + 15), true, true, 0, -1, false ));
	yPos+=yHeight;
	pWindow->addChild(pGuiEnv->addStaticText(L"X:", core::rect<s32>(xPos, yPos, xPos + 20, yPos + yHeight)));
	xPos+=20;
	pWindow->addChild(pGuiEnv->addEditBox(L"3", core::rect<s32>(xPos, yPos - 3, xPos + 30, yPos+yHeight), true, 0, ID_EDIT_X ));
	xPos+=40;
	pWindow->addChild(pGuiEnv->addStaticText(L"Y:", core::rect<s32>(xPos, yPos, xPos + 20, yPos + yHeight) ));
	xPos+=20;
	pWindow->addChild(pGuiEnv->addEditBox(L"3", core::rect<s32>(xPos, yPos - 3, xPos + 30, yPos+yHeight), true, 0, ID_EDIT_Y ));
	xPos+=40;
	pWindow->addChild(pGuiEnv->addStaticText(L"Z:", core::rect<s32>(xPos, yPos, xPos + 20, yPos + yHeight) ));
	xPos+=20;
	pWindow->addChild(pGuiEnv->addEditBox(L"3", core::rect<s32>(xPos, yPos - 3, xPos + 30, yPos+yHeight), true, 0, ID_EDIT_Z ));
	xPos+=40;
	pWindow->addChild(pGuiEnv->addButton(core::rect<s32>(xPos, yPos, xPos + 40, yPos+yHeight*2+3), 0, ID_BUTTON_SET, L"set"));
	yPos+=yHeight+7;
	xPos=xStart + 30;
	pWindow->addChild(pGuiEnv->addStaticText(L"fields to connect:", core::rect<s32>(xPos, yPos, xPos + 145, yPos + yHeight)));
	xPos+=160;
	pWindow->addChild(pGuiEnv->addEditBox(L"3", core::rect<s32>(xPos, yPos - 3, xPos + 30, yPos+yHeight), true, 0, ID_EDIT_CONNECT ));
	yPos+=yHeight+10;
	pWindow->addChild(pGuiEnv->addStaticText(L"Player 1(first move):", core::rect<s32>(xStart, yPos, xEnd, yPos + 4 * yHeight + 7), true, true, 0, -1, true ));
	yPos+=yHeight;
	xPos=xStart + 20;
	pWindow->addChild(pGuiEnv->addCheckBox(true, core::rect<s32>(xPos, yPos, xPos + 170, yPos+yHeight), 0, ID_CHECK_HUMAN1, L"human"));
	yPos+=yHeight;
	pWindow->addChild(pGuiEnv->addCheckBox(false, core::rect<s32>(xPos, yPos, xPos + 170, yPos+yHeight), 0, ID_CHECK_AINN1, L"AI(neural network)"));
	yPos+=yHeight;
	pWindow->addChild(pGuiEnv->addCheckBox(false, core::rect<s32>(xPos, yPos, xPos + 160, yPos+yHeight), 0, ID_CHECK_AILT1, L"AI(lookup table)"));
	yPos+=yHeight + 9;
	pWindow->addChild(pGuiEnv->addStaticText(L"Player 2:", core::rect<s32>(xStart, yPos, xEnd, yPos + 4 * yHeight + 7), true, true, 0, -1, true ));
	yPos+=yHeight;
	xPos=xStart + 20;
	pWindow->addChild(pGuiEnv->addCheckBox(true, core::rect<s32>(xPos, yPos, xPos + 170, yPos+yHeight), 0, ID_CHECK_HUMAN2, L"human"));
	yPos+=yHeight;
	pWindow->addChild(pGuiEnv->addCheckBox(false, core::rect<s32>(xPos, yPos, xPos + 170, yPos+yHeight), 0, ID_CHECK_AINN2, L"AI(neural network)"));
	yPos+=yHeight;
	pWindow->addChild(pGuiEnv->addCheckBox(false, core::rect<s32>(xPos, yPos, xPos + 160, yPos+yHeight), 0, ID_CHECK_AILT2, L"AI(lookup table)"));
	yPos+=yHeight + 9;
	pWindow->addChild(pGuiEnv->addStaticText(L"AI Setup:", core::rect<s32>(xStart, yPos, xEnd, 395 - yPosition), true, true, 0, -1, true ));
	yPos+=yHeight;
	pWindow->addChild(pGuiEnv->addButton(core::rect<s32>(xPos, yPos, xEnd - 20, yPos+yHeight), 0, ID_BUTTON_AICOMPETITION, L"AI Competition"));
	yPos+=yHeight;
	pWindow->addChild(pGuiEnv->addButton(core::rect<s32>(xPos, yPos, xEnd - 20, yPos+yHeight), 0, ID_BUTTON_NNSETUP, L"Neural Network Setup"));
	yPos+=yHeight+7;
	pWindow->addChild(pCheckProbabilities=pGuiEnv->addCheckBox(false, core::rect<s32>(xPos, yPos, xPos + 170, yPos+yHeight), 0, -1, L"show probabilities"));
	
	pWindow->getCloseButton()->setVisible(false);
	pWindow->addChild(pGuiEnv->addButton(pWindow->getCloseButton()->getRelativePosition(), 0, ID_BUTTON_CLOSE_PREF, L"x"));

	pWindow->updateAbsolutePosition();
	resetWindow();
}

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

CPreferencesWindow::~CPreferencesWindow(void)
{
}

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

void CPreferencesWindow::onGuiEvent(SEvent &event)
{
	if ( event.EventType == EET_GUI_EVENT )
	{
		s32 id = event.GUIEvent.Caller->getID();

		switch( event.GUIEvent.EventType )
		{
		case gui::EGET_CHECKBOX_CHANGED:

			switch(id)
			{
			case ID_CHECK_HUMAN1: pMuele->playerOneType=PLAYER_TYPE_HUMAN; break;
			case ID_CHECK_AINN1:  pMuele->playerOneType=PLAYER_TYPE_AINN; break;
			case ID_CHECK_AILT1:
				{
					pMuele->playerOneType=PLAYER_TYPE_AILT;

					if ( !pMuele->pLookUpTable )
					{
						pMuele->pDriver->beginScene(false, false, video::SColor(0, 40, 40, 40));
						gui::IGUIWindow *pWindow =	pMuele->createWindow(280, 70, L"One Moment Please");
						pWindow->addChild( pMuele->pGuiEnv->addStaticText(L"Generating look up table.", core::rect<s32>( 5, 25, 275, 60)));
						pWindow->updateAbsolutePosition();
						pWindow->draw();
						pMuele->pDriver->endScene();
						pMuele->pLookUpTable = new CLookUpTable();
						pWindow->remove();
					}
					break;
				}
			case ID_CHECK_HUMAN2: pMuele->playerTwoType=PLAYER_TYPE_HUMAN; break;
			case ID_CHECK_AINN2:  pMuele->playerTwoType=PLAYER_TYPE_AINN; break;
			case ID_CHECK_AILT2:  
				{
					pMuele->playerTwoType=PLAYER_TYPE_AILT;

					if ( !pMuele->pLookUpTable )
					{
						pMuele->pDriver->beginScene(false, false, video::SColor(0, 40, 40, 40));
						gui::IGUIWindow *pWindow =	pMuele->createWindow(280, 70, L"One Moment Please");
						pWindow->addChild( pMuele->pGuiEnv->addStaticText(L"Generating look up table.", core::rect<s32>( 5, 25, 275, 60)));
						pWindow->updateAbsolutePosition();
						pWindow->draw();
						pMuele->pDriver->endScene();
						pMuele->pLookUpTable = new CLookUpTable();
						pWindow->remove();
					}
					break;
				}
			}
			resetWindow();
			break;
		case gui::EGET_BUTTON_CLICKED:

			switch(id)
			{
			case ID_BUTTON_AICOMPETITION: pMuele->pAICompetitionWindow->toggleVisiblility(); break;
			case ID_BUTTON_CLOSE_PREF:    toggleVisiblility(); break;
			case ID_BUTTON_NNSETUP:		  pMuele->pNeuralNetworkWindow->toggleVisiblility(); break;
			case ID_BUTTON_SET:
			{
				gui::IGUIElement* root = pMuele->pGuiEnv->getRootGUIElement();
				core::stringc s;
				int x,y,z;

				s = root->getElementFromId(ID_EDIT_X, true)->getText();
				x = atoi(s.c_str());
				s = root->getElementFromId(ID_EDIT_Y, true)->getText();
				y = atoi(s.c_str());
				s = root->getElementFromId(ID_EDIT_Z, true)->getText();
				z = atoi(s.c_str());

				s = root->getElementFromId(ID_EDIT_CONNECT, true)->getText();
				pMuele->winFieldCount=atoi(s.c_str());;

				if ( pMuele->boardSizeX != x || pMuele->boardSizeY != y || pMuele->boardSizeZ != z )
				{
					pMuele->boardSizeX = x;
					pMuele->boardSizeY = y;
					pMuele->boardSizeZ = z;
					pMuele->resetBoard(false);

					pMuele->pNeuralNetworkWindow->hiddenNeurons = pMuele->boardFieldCount * 3;
					delete pMuele->pNeuralNetwork;
					pMuele->pNeuralNetwork = new CNeuralNetwork(pMuele->boardSizeX, pMuele->boardSizeY, pMuele->boardSizeZ, pMuele->winFieldCount, pMuele->pNeuralNetworkWindow->hiddenNeurons, pMuele->pNeuralNetworkWindow->pCheckLargeInputVector->isChecked(), pMuele);
					pMuele->pNeuralNetworkWindow->resetWindow(true);
	                
					resetWindow();
					pMuele->pNeuralNetwork->loadNet(NULL);
				}
				break;
			}
			}
		}
	}
}

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

void CPreferencesWindow::toggleVisiblility()
{
	pWindow->setVisible(!pWindow->isVisible());
}

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

void CPreferencesWindow::resetWindow()
{
	gui::IGUIElement* root = pMuele->pGuiEnv->getRootGUIElement();
	core::stringw s;

	s=pMuele->boardSizeX;
	root->getElementFromId(ID_EDIT_X, true)->setText((const wchar_t*)s.c_str());
	s=pMuele->boardSizeY;
	root->getElementFromId(ID_EDIT_Y, true)->setText((const wchar_t*)s.c_str());
	s=pMuele->boardSizeZ;
	root->getElementFromId(ID_EDIT_Z, true)->setText((const wchar_t*)s.c_str());
	s=pMuele->winFieldCount;
	root->getElementFromId(ID_EDIT_CONNECT, true)->setText((const wchar_t*)s.c_str());
	bool setbool;

	if ( pMuele->boardSizeX != 3 || pMuele->boardSizeY !=3 || pMuele->boardSizeZ != 1) 
	{
		setbool = false;
		if ( pMuele->playerOneType == PLAYER_TYPE_AILT ) pMuele->playerOneType = PLAYER_TYPE_AINN;
		if ( pMuele->playerTwoType == PLAYER_TYPE_AILT ) pMuele->playerTwoType = PLAYER_TYPE_AINN;
	}
	else setbool = true;
	
	((gui::IGUICheckBox*)root->getElementFromId(ID_CHECK_AILT1, true))->setVisible(setbool);
	((gui::IGUICheckBox*)root->getElementFromId(ID_CHECK_AILT2, true))->setVisible(setbool);

	if ( pMuele->playerOneType == PLAYER_TYPE_HUMAN ) setbool=true; else setbool=false;
	((gui::IGUICheckBox*)root->getElementFromId(ID_CHECK_HUMAN1, true))->setChecked(setbool);
	if ( pMuele->playerOneType == PLAYER_TYPE_AINN ) setbool=true; else setbool=false;
	((gui::IGUICheckBox*)root->getElementFromId(ID_CHECK_AINN1, true))->setChecked(setbool);
	if ( pMuele->playerOneType == PLAYER_TYPE_AILT ) setbool=true; else setbool=false;
	((gui::IGUICheckBox*)root->getElementFromId(ID_CHECK_AILT1, true))->setChecked(setbool);
	if ( pMuele->playerTwoType == PLAYER_TYPE_HUMAN ) setbool=true; else setbool=false;
	((gui::IGUICheckBox*)root->getElementFromId(ID_CHECK_HUMAN2, true))->setChecked(setbool);
	if ( pMuele->playerTwoType == PLAYER_TYPE_AINN ) setbool=true; else setbool=false;
	((gui::IGUICheckBox*)root->getElementFromId(ID_CHECK_AINN2, true))->setChecked(setbool);
	if ( pMuele->playerTwoType == PLAYER_TYPE_AILT ) setbool=true; else setbool=false;
	((gui::IGUICheckBox*)root->getElementFromId(ID_CHECK_AILT2, true))->setChecked(setbool);

	if ( pMuele->actualPlayer == PLAYER_2 ) pMuele->actualPlayerType = pMuele->playerTwoType;
	else pMuele->actualPlayerType = pMuele->playerOneType;

	if ( pMuele->lastPlayer == PLAYER_2 ) pMuele->lastPlayerType = pMuele->playerTwoType;
	else pMuele->lastPlayerType = pMuele->playerOneType;
}
