#include "QtWindow.h"
#include <BWAPI.h>
#include <BWTA.h>
#include "InformationManager.h"
#include "Search/ActionGenerator.h"
#include "Search/ABCD.h"
#include "Search/EvaluationFunctionBasic.h"

QTextEdit* globalTextEdit;
int regionIdSelected = -1;
ActionGenerator actionGeneration;
GameState test;

myQtApp::myQtApp(QWidget *parent)
{
	// this sets up GUI
	setupUi(this); 

	globalTextEdit = textEdit;

	// -------------------- INITIALIZING VARIABLES --------------------
	// Tab Options
	chkMapAnalysisBWTA->setChecked(false);
	chkBuildMap->setChecked(PRINT_BUILD_MAP);
	chkGroundDPS->setChecked(PRINT_GROUND_DPS);
	chkAirDPS->setChecked(PRINT_AIR_DPS);
	chkBuildOrder->setChecked(PRINT_BUILD_ORDER);
	// Tab Game State
	mapScene = new QGraphicsScene();
	chkRegionIdMap->setChecked(PRINT_REGION_ID_MAP);

	gameStateLabels << tr("Unit type") << tr("Number") << tr("Region") << tr("Order") << tr("Target") << tr("End frame");
	unitsToLocationTable->setColumnCount(6);
	unitsToLocationTable->setHorizontalHeaderLabels(gameStateLabels);
	unitsToLocationTable->setColumnWidth(0,150);

	unitsToLocationTable_2->setColumnCount(6);
	unitsToLocationTable_2->setHorizontalHeaderLabels(gameStateLabels);
	unitsToLocationTable_2->setColumnWidth(0,150);

	unitMapLabels << tr("Unit type") << tr("Number") << tr("Order") << tr("End frame");
	unitsToLocationTable_3->setColumnCount(4);
	unitsToLocationTable_3->setHorizontalHeaderLabels(unitMapLabels);
	unitsToLocationTable_3->setColumnWidth(0,150);

	unitsToLocationTable_4->setColumnCount(4);
	unitsToLocationTable_4->setHorizontalHeaderLabels(unitMapLabels);
	unitsToLocationTable_4->setColumnWidth(0,150);

	// Default data for Effectiveness tab
	QStringList unitTypesLabels;
	unitTypesLabels << tr("SVC") << tr("Marine") << tr("Medic") << tr("Firebat") << tr("Ghost")
					<< tr("Vulture") << tr("Tank") << tr("Goliath") << tr("Wraith") << tr("Science Vessel")
					<< tr("Battlecruiser") << tr("Valkyrie");
	unitEffecTable->setColumnCount(12);
	unitEffecTable->setRowCount(12);
	unitEffecTable->setHorizontalHeaderLabels(unitTypesLabels);
	unitEffecTable->setVerticalHeaderLabels(unitTypesLabels);
	
	// Initialize with tab selected
	gameStateTabChanged(gameStateTab->currentIndex());


	// -------------------- SIGNLAS/SLOTS ------------------------
	// Tab Options
	connect( speedSlider, SIGNAL( valueChanged(int) ), this, SLOT( changeSpeed(int) ) ); 
	connect( pauseButton, SIGNAL( clicked() ), this, SLOT( pauseGame() ) ); 
	connect( resumeButton, SIGNAL( clicked() ), this, SLOT( resumeGame() ) ); 
	connect( chkBuildMap, SIGNAL( stateChanged(int) ), this, SLOT( changeBuildMap(int) ) );
	connect( chkGroundDPS, SIGNAL( stateChanged(int) ), this, SLOT( changeGroundDPS(int) ) );
	connect( chkAirDPS, SIGNAL( stateChanged(int) ), this, SLOT( changeAirDPS(int) ) );
	connect( chkBuildOrder, SIGNAL( stateChanged(int) ), this, SLOT( changeBuildOrder(int) ) );
	// Tab Game State
	connect( chkRegionIdMap, SIGNAL( stateChanged(int) ), this, SLOT( changeRegionId(int) ) );
	connect( informationManager->_GUIsignal, SIGNAL(mapInfoChanged()), this, SLOT(changeBWTAdata()) );
	connect( informationManager->_GUIsignal, SIGNAL(gameStateChanged()), this, SLOT(updateGameStateTable()) );
	connect( gameStateTab, SIGNAL( currentChanged(int) ), this, SLOT( gameStateTabChanged(int) ) );
	// -- SubTab Game Search
	connect( cleanActionsButton, SIGNAL( clicked() ), this, SLOT( cleanActions() ) ); 
	connect( generateActionsButton, SIGNAL( clicked() ), this, SLOT( generateActions() ) ); 
	connect( nextActionButton, SIGNAL( clicked() ), this, SLOT( expandNode() ) ); 
	connect( randomActionButton, SIGNAL( clicked() ), this, SLOT( expandRandomNode() ) ); 
    connect( executeActionButton, SIGNAL( clicked() ), this, SLOT( executeAction() ) ); 
    connect( loadButton, SIGNAL( clicked() ), this, SLOT( loadFile() ) ); 

}


void myQtApp::changeSpeed(int value)
{
	BWAPI::Broodwar->setLocalSpeed(value);
	speedLabel->setText( "Game speed: " + QString::number(value) );
}

void myQtApp::pauseGame()
{
	BWAPI::Broodwar->pauseGame();
}

void myQtApp::resumeGame()
{
	BWAPI::Broodwar->resumeGame();
}

void myQtApp::changeBWTAdata()
{
	mapScene->clear();
	// draw regions
	drawPolygons(&BWTA::getUnwalkablePolygons(),mapScene);
	// draw center of choke points/regions
	double x0, y0, x1, y1;
	QPen qp(QColor(0,0,0));
	qp.setWidth(2);
	const std::set<BWTA::Chokepoint*> chokePoints = BWTA::getChokepoints();
	for(std::set<BWTA::Chokepoint*>::const_iterator c=chokePoints.begin();c!=chokePoints.end();c++) {
		x0 = (double)((*c)->getCenter().x())/8;
		y0 = (double)((*c)->getCenter().y())/8;

		const std::pair<BWTA::Region*,BWTA::Region*> regions = (*c)->getRegions();
		// draw region 1
		x1 = (double)regions.first->getCenter().x()/8;
		y1 = (double)regions.first->getCenter().y()/8;
		mapScene->addLine(QLineF(x0,y0,x1,y1),qp);
		mapScene->addEllipse(QRectF(x1-6,y1-6,12,12),QPen(QColor(0,0,255)),QBrush(QColor(0,0,255)));
		QGraphicsTextItem * io = new QGraphicsTextItem;
		io->setDefaultTextColor(QColor(0,0,255));
		io->setPos(x1,y1+6);
		io->setPlainText(QString::number(informationManager->_regionID[regions.first]));
		mapScene->addItem(io);
		// draw region 2
		x1 = (double)regions.second->getCenter().x()/8;
		y1 = (double)regions.second->getCenter().y()/8;
		mapScene->addLine(QLineF(x0,y0,x1,y1),qp);
		mapScene->addEllipse(QRectF(x1-6,y1-6,12,12),QPen(QColor(0,0,255)),QBrush(QColor(0,0,255)));
		QGraphicsTextItem * io2 = new QGraphicsTextItem;
		io2->setDefaultTextColor(QColor(0,0,255));
		io2->setPos(x1,y1+6);
		io2->setPlainText(QString::number(informationManager->_regionID[regions.second]));
		mapScene->addItem(io2);

		// draw choke point
		QGraphicsTextItem * io3 = new QGraphicsTextItem;
		io3->setDefaultTextColor(QColor(255,0,0));
		io3->setPos(x0,y0+6);
		io3->setPlainText(QString::number(informationManager->_chokePointID[*c]));
		mapScene->addItem(io3);
		mapScene->addEllipse(QRectF(x0-3,y0-3,6,6),QPen(QColor(255,0,0)),QBrush(QColor(255,0,0)));
	}

	textEdit->append( "Scene size " + QString::number(mapScene->width()) + "," + QString::number(mapScene->height()) );

	// Render map
	mapView->setScene(mapScene);
	mapView->setRenderHint(QPainter::Antialiasing);
	mapView->show();
}

void myQtApp::updateGameStateTable()
{
	if (gameStateTab->currentIndex() == 1) {
		updateUnitMap();
	} else {
		WaitForSingleObject(gameStateMutex,INFINITE); // wait for ownership
		std::vector<GameState::unitState_t> friendlyUnits = informationManager->gameState.friendlyUnits;
		int rows = friendlyUnits.size();
		unitsToLocationTable->setRowCount(rows);
		for( int i = 0; i < rows; ++i ) {
			BWAPI::UnitType unitType = BWAPI::UnitType(friendlyUnits[i].unitTypeId);
			//BWAPI::Order unitCommand = BWAPI::Order(friendlyUnits[i].orderId);
			//std::string unitCommand = BWAPI::Order(friendlyUnits[i].orderId).getName();
			std::string unitCommand = informationManager->gameState.getAbstractOrderName(friendlyUnits[i].orderId);
			QTableWidgetItem *item0 = new QTableWidgetItem( tr("%1").arg(unitType.getName().c_str()) );
			QTableWidgetItem *item1 = new QTableWidgetItem( tr("%1").arg(friendlyUnits[i].numUnits) );
			QTableWidgetItem *item2 = new QTableWidgetItem( tr("%1").arg(friendlyUnits[i].regionId) );
			QTableWidgetItem *item3 = new QTableWidgetItem( tr("%1").arg(unitCommand.c_str()) );
			//QTableWidgetItem *item4 = new QTableWidgetItem( tr("%1").arg(informationManager->gameState.getAbstractOrderName(unitCommand).c_str()) );
			QTableWidgetItem *item5 = new QTableWidgetItem( tr("%1").arg(friendlyUnits[i].targetRegionId) );
			int endFrame = friendlyUnits[i].endFrame;
			if (endFrame > 0) endFrame -= BWAPI::Broodwar->getFrameCount();
			QTableWidgetItem *item6 = new QTableWidgetItem( tr("%1").arg(endFrame) );
			unitsToLocationTable->setItem( i, 0, item0 );
			unitsToLocationTable->setItem( i, 1, item1 );
			unitsToLocationTable->setItem( i, 2, item2 );
			unitsToLocationTable->setItem( i, 3, item3 );
			unitsToLocationTable->setItem( i, 4, item5 );
			unitsToLocationTable->setItem( i, 5, item6 );
	// 		unitsToLocationTable->setItem( i, 4, item4 );
	// 		unitsToLocationTable->setItem( i, 5, item5 );
		}
		unitsToLocationTable->sortByColumn(0, Qt::AscendingOrder);

		//enemy
		std::vector<GameState::unitState_t> enemyUnits = informationManager->gameState.enemyUnits;
		rows = enemyUnits.size();
		unitsToLocationTable_2->setRowCount(rows);
		for( int i = 0; i < rows; ++i ) {
			BWAPI::UnitType unitType = BWAPI::UnitType(enemyUnits[i].unitTypeId);
			//BWAPI::Order unitCommand = BWAPI::Order(enemyUnits[i].orderId);
			//std::string unitCommand = BWAPI::Order(enemyUnits[i].orderId).getName();
			std::string unitCommand = informationManager->gameState.getAbstractOrderName(enemyUnits[i].orderId);
			QTableWidgetItem *item0 = new QTableWidgetItem( tr("%1").arg(unitType.getName().c_str()) );
			QTableWidgetItem *item1 = new QTableWidgetItem( tr("%1").arg(enemyUnits[i].numUnits) );
			QTableWidgetItem *item2 = new QTableWidgetItem( tr("%1").arg(enemyUnits[i].regionId) );
			QTableWidgetItem *item3 = new QTableWidgetItem( tr("%1").arg(unitCommand.c_str()) );
			//QTableWidgetItem *item4 = new QTableWidgetItem( tr("%1").arg(informationManager->gameState.getAbstractOrderName(unitCommand).c_str()) );
			QTableWidgetItem *item5 = new QTableWidgetItem( tr("%1").arg(enemyUnits[i].targetRegionId) );
			int endFrame = enemyUnits[i].endFrame;
			if (endFrame > 0) endFrame -= BWAPI::Broodwar->getFrameCount();
			QTableWidgetItem *item6 = new QTableWidgetItem( tr("%1").arg(endFrame) );
			unitsToLocationTable_2->setItem( i, 0, item0 );
			unitsToLocationTable_2->setItem( i, 1, item1 );
			unitsToLocationTable_2->setItem( i, 2, item2 );
			unitsToLocationTable_2->setItem( i, 3, item3 );
			unitsToLocationTable_2->setItem( i, 4, item5 );
			unitsToLocationTable_2->setItem( i, 5, item6 );
	// 		unitsToLocationTable_2->setItem( i, 4, item4 );
	// 		unitsToLocationTable_2->setItem( i, 5, item5 );
		}
		unitsToLocationTable_2->sortByColumn(0, Qt::AscendingOrder);
		ReleaseMutex(gameStateMutex);
	}
}

void myQtApp::drawPolygons(const std::set<BWTA::Polygon*>* polygons, QGraphicsScene* scene)
{
	for(std::set<BWTA::Polygon*>::const_iterator i=polygons->begin();i!=polygons->end();i++) {
		BWTA::Polygon boundary = *(*i);
		drawPolygon(boundary,QColor(180,180,180),scene);
		std::vector<BWTA::Polygon> pHoles = boundary.holes;
		for(std::vector<BWTA::Polygon>::iterator h=pHoles.begin();h!=pHoles.end();h++) {
			drawPolygon(*h,QColor(255,100,255),scene);
		}
	}
}

void myQtApp::drawPolygon(BWTA::Polygon& p, QColor qc, QGraphicsScene* scene, double scale)
{
	QVector<QPointF> qp;
	for(int i=0;i<(int)p.size();i++) {
		int j=(i+1)%p.size();
		qp.push_back(QPointF(p[i].x()*scale,p[i].y()*scale));
	}
	scene->addPolygon(QPolygonF(qp),QPen(QColor(0,0,0)),QBrush(qc));  
}

void myQtApp::changeDisplayBWTA(int state)
{
	//textEdit->append( "Display BWTA: " + QString::number(state) );
}

void myQtApp::changeBuildMap(int state)
{
	PRINT_BUILD_MAP = !PRINT_BUILD_MAP;
}

void myQtApp::changeGroundDPS(int state)
{
	PRINT_GROUND_DPS = !PRINT_GROUND_DPS;
}

void myQtApp::changeAirDPS(int state)
{
	PRINT_AIR_DPS = !PRINT_AIR_DPS;
}

void myQtApp::changeBuildOrder(int state)
{
	PRINT_BUILD_ORDER = !PRINT_BUILD_ORDER;
}

void myQtApp::changeRegionId(int state)
{
	PRINT_REGION_ID_MAP = !PRINT_REGION_ID_MAP;
}

void myQtApp::gameStateTabChanged(int tabIndex)
{
	switch (tabIndex) {
		case 1: // Units
			updateUnitMap();
			blueInfo->setText( "Friendly units" );
			redInfo->setText( "Enemy units" );
			break;
		case 2: // Effectiveness
			updateEffectivenessMap();
			blueInfo->setText( "Friendly region effectiveness" );
			redInfo->setText( "Enemy region effectiveness" );
			break;
		case 0: // Region ID
		default:
			changeBWTAdata();
			blueInfo->setText( "Center of the region" );
			redInfo->setText( "Center of the chokepoint" );
			break;
	}
}

void myQtApp::updateUnitMap()
{
	globalTextEdit->append( "Update unit map" );
	mapScene->clear();
	// draw regions
	drawPolygons(&BWTA::getUnwalkablePolygons(),mapScene);

	// draw selected region
	BWTA::Region* region = informationManager->_regionFromID[regionIdSelected];
	if (region != NULL) {
		BWTA::Polygon regionPolygon = region->getPolygon();
		drawPolygon(regionPolygon,QColor(255,100,255),mapScene,0.125);
	}

	// Print circles on center regions
	int rows = 0;
	int printRow = 0;
	WaitForSingleObject(gameStateMutex,INFINITE); // wait for ownership
	std::vector<GameState::unitState_t> friendlyUnits = informationManager->gameState.friendlyUnits;
	for( unsigned int i = 0; i < friendlyUnits.size(); ++i ) {
		BWAPI::Position groupPosition = getCenterRegionId(friendlyUnits[i].regionId);
		if (groupPosition != BWAPI::Positions::None) {
			drawUnitEllipse((int)groupPosition.x()/8, (int)groupPosition.y()/8, 5, Qt::blue, friendlyUnits[i].regionId, mapScene);
		}
		if (regionIdSelected == friendlyUnits[i].regionId) {
			rows++;
		}
	}
	// Update table info
	unitsToLocationTable_3->setRowCount(rows);
	if (rows > 0) {
		for( unsigned int i = 0; i < friendlyUnits.size(); ++i ) {
			if (regionIdSelected == friendlyUnits[i].regionId) {
				BWAPI::UnitType unitType = BWAPI::UnitType(friendlyUnits[i].unitTypeId);
				std::string unitCommand = informationManager->gameState.getAbstractOrderName(friendlyUnits[i].orderId);
				QTableWidgetItem *item0 = new QTableWidgetItem( tr("%1").arg(unitType.getName().c_str()) );
				QTableWidgetItem *item1 = new QTableWidgetItem( tr("%1").arg(friendlyUnits[i].numUnits) );
				QTableWidgetItem *item3 = new QTableWidgetItem( tr("%1").arg(unitCommand.c_str()) );
				int endFrame = friendlyUnits[i].endFrame;
				if (endFrame > 0) endFrame -= BWAPI::Broodwar->getFrameCount();
				QTableWidgetItem *item6 = new QTableWidgetItem( tr("%1").arg(endFrame) );
 				unitsToLocationTable_3->setItem( printRow, 0, item0 );
				unitsToLocationTable_3->setItem( printRow, 1, item1 );
 				unitsToLocationTable_3->setItem( printRow, 2, item3 );
 				unitsToLocationTable_3->setItem( printRow, 3, item6 );
				printRow++;
			}
		}
		unitsToLocationTable_3->sortByColumn(0, Qt::AscendingOrder);
	}
	rows = 0;
	printRow = 0;
	// draw circles in map
	std::vector<GameState::unitState_t> enemyUnits = informationManager->gameState.enemyUnits;
	for( unsigned int i = 0; i < enemyUnits.size(); ++i ) {
		BWAPI::Position groupPosition = getCenterRegionId(enemyUnits[i].regionId);
		if (groupPosition != BWAPI::Positions::None) {
			drawUnitEllipse((int)groupPosition.x()/8, (int)groupPosition.y()/8, -5, Qt::red, enemyUnits[i].regionId, mapScene);
		}
		if (regionIdSelected == enemyUnits[i].regionId) {
			rows++;
		}
	}
	// Update table info
	unitsToLocationTable_4->setRowCount(rows);
	if (rows > 0) {
		for( unsigned int i = 0; i < enemyUnits.size(); ++i ) {
			if (regionIdSelected == enemyUnits[i].regionId) {
				BWAPI::UnitType unitType = BWAPI::UnitType(enemyUnits[i].unitTypeId);
 				std::string unitCommand = informationManager->gameState.getAbstractOrderName(enemyUnits[i].orderId);
				QTableWidgetItem *item0 = new QTableWidgetItem( tr("%1").arg(unitType.getName().c_str()) );
				QTableWidgetItem *item1 = new QTableWidgetItem( tr("%1").arg(enemyUnits[i].numUnits) );
				QTableWidgetItem *item3 = new QTableWidgetItem( tr("%1").arg(unitCommand.c_str()) );
				int endFrame = enemyUnits[i].endFrame;
				if (endFrame > 0) endFrame -= BWAPI::Broodwar->getFrameCount();
				QTableWidgetItem *item6 = new QTableWidgetItem( tr("%1").arg(endFrame) );
				unitsToLocationTable_4->setItem( printRow, 0, item0 );
				unitsToLocationTable_4->setItem( printRow, 1, item1 );
				unitsToLocationTable_4->setItem( printRow, 2, item3 );
				unitsToLocationTable_4->setItem( printRow, 3, item6 );
				printRow++;
			}
		}
		unitsToLocationTable_4->sortByColumn(0, Qt::AscendingOrder);
	}
	ReleaseMutex(gameStateMutex);


	// Render map
	mapView->setScene(mapScene);
	mapView->setRenderHint(QPainter::Antialiasing);
	mapView->show();

}

void myQtApp::drawUnitEllipse(int x, int y, int xOffset, QColor color, int regionId, QGraphicsScene* scene)
{
	CustomEllipseItem* item = new CustomEllipseItem;
	item->setRect(x+xOffset, y, 10, 10);
	item->setBrush(QBrush(color));
	item->setPen(QPen(color));
	item->regionId = regionId;

	scene->addItem(item);
}

void myQtApp::drawCircleText(int x, int y, int xOffset, QColor color, int score, QGraphicsScene* scene)
{
	CustomEllipseItem* item = new CustomEllipseItem;
	item->setRect(x+xOffset, y, 20, 20);
	item->setBrush(QBrush(Qt::white));
	item->setPen(QPen(color));
	item->regionId = score;
	scene->addItem(item);

	QGraphicsTextItem * io = new QGraphicsTextItem;
	io->setDefaultTextColor(QColor(0,0,255));
	io->setPos(x+xOffset-1,y-1);
	io->setPlainText(QString::number(score));
	scene->addItem(io);
}


void CustomEllipseItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
	//globalTextEdit->append( "Item pressed!!" );
	regionIdSelected = regionId;
}

// TODO: duplicated from GameState!!!!
BWAPI::Position myQtApp::getCenterRegionId(int regionId)
{
	BWTA::Region* region = informationManager->_regionFromID[regionId];
	if (region != NULL) {
		return region->getCenter();
	} else {
		BWTA::Chokepoint* cp = informationManager->_chokePointFromID[regionId];
		if (cp != NULL) {
			return cp->getCenter();
		} else {
			return BWAPI::Positions::None;
		}
	}
}

void myQtApp::updateEffectivenessMap()
{
	mapScene->clear();
	// draw regions
	drawPolygons(&BWTA::getUnwalkablePolygons(),mapScene);
	// draw center of choke points/regions
	double x0, y0, x1, y1;
	QPen qp(QColor(0,0,0));
	qp.setWidth(2);
	const std::set<BWTA::Chokepoint*> chokePoints = BWTA::getChokepoints();
	for(std::set<BWTA::Chokepoint*>::const_iterator c=chokePoints.begin();c!=chokePoints.end();c++) {
		// draw choke point
		x0 = (double)((*c)->getCenter().x())/8;
		y0 = (double)((*c)->getCenter().y())/8;
		drawCircleText(x0, y0, 10, Qt::blue, 12, mapScene);
		drawCircleText(x0, y0, -10, Qt::red, 12, mapScene);

		const std::pair<BWTA::Region*,BWTA::Region*> regions = (*c)->getRegions();
		// draw region 1
		x1 = (double)regions.first->getCenter().x()/8;
		y1 = (double)regions.first->getCenter().y()/8;
		drawCircleText(x1, y1, 10, Qt::blue, 13, mapScene);
		drawCircleText(x1, y1, -10, Qt::red, 10, mapScene);

		// draw region 2
		x1 = (double)regions.second->getCenter().x()/8;
		y1 = (double)regions.second->getCenter().y()/8;
		drawCircleText(x1, y1, 10, Qt::blue, 10, mapScene);
		drawCircleText(x1, y1, -10, Qt::red, 15, mapScene);
	}

	// Render map
	mapView->setScene(mapScene);
	mapView->setRenderHint(QPainter::Antialiasing);
	mapView->show();
}

// Game Search
// *********************

void myQtApp::cleanActions()
{
	actionGeneration = ActionGenerator(informationManager->gameState);
	//actionGeneration.cleanActions();
	searchLog->append( QString::fromStdString( actionGeneration._gs.toString() ) );
	searchLog->append( QString::fromStdString( actionGeneration.toString() ) );
}

void myQtApp::generateActions()
{
	if (actionGeneration._gs.canExecuteAnyAction(true)) {
		searchLog->append( "Generating actions for friendly" );
		actionGeneration = ActionGenerator(actionGeneration._gs, true);
	} else {
		searchLog->append( "Generating actions for enemy" );
		actionGeneration = ActionGenerator(actionGeneration._gs, false);
	}
	//searchLog->append( QString::fromStdString( actionGeneration._gs.toString() ) );
	searchLog->append( QString::fromStdString( actionGeneration.toString() ) );
}

void myQtApp::expandNode()
{
	playerActions_t unitsAction = actionGeneration.getNextAction();
	if (!unitsAction.empty()) {
		searchLog->append( QString::fromStdString( actionGeneration.toString(unitsAction) ) );

// 		searchLog->append( "------------" );
// 		searchLog->append( QString::fromStdString( actionGeneration._gs.toString() ) );
// 		searchLog->append( "------------" );
// 		test = actionGeneration._gs.cloneIssue(unitsAction, actionGeneration._player);
// 		searchLog->append( QString::fromStdString( test.toString() ) );
// 		searchLog->append( "------------" );
// 		searchLog->append( QString::fromStdString( actionGeneration._gs.toString() ) );
// 		searchLog->append( "------------" );

	} else {
		searchLog->append( "No more actions" );
	}
}

void myQtApp::expandRandomNode()
{
	playerActions_t unitsAction = actionGeneration.getRandomAction();
	if (!unitsAction.empty()) {
		searchLog->append( QString::fromStdString( actionGeneration.toString(unitsAction) ) );
	} else {
		searchLog->append( "No more actions" );
	}
}


void myQtApp::executeAction()
{
	actionGeneration._gs.execute(actionGeneration._lastAction, actionGeneration._player);
	searchLog->append( QString::fromStdString( actionGeneration._gs.toString() ) );
	
	searchLog->append( "Forward time:" );
	actionGeneration._gs.moveForward();
	searchLog->append( QString::fromStdString( actionGeneration._gs.toString() ) );
}

void myQtApp::loadFile()
{
    std::string gameStateLog = "bwapi-data\\logs\\gameState.txt";
    searchLog->append( QString("Loading file: %1").arg(gameStateLog.c_str()) );
    LOG( "Loading file: " << gameStateLog );

    // clear lists
    informationManager->gameState.friendlyUnits.clear();
    informationManager->gameState.enemyUnits.clear();

    std::ifstream infile(gameStateLog.c_str());
    std::string line;
    int listID = 1; // 1=friendList 2=enemyList
    while (std::getline(infile, line)) {
        //searchLog->append(line.c_str());
        //LOG(line.c_str());
        std::istringstream iss(line);
        int unitTypeID, numUnits, regionID;
        std::string unitPointer, extraInfo;
        if (!(iss >> unitPointer >> unitTypeID >> numUnits >> regionID >> extraInfo)) { 
            // Error processing line
            if (unitPointer.compare(0,1,"(") == 0) {
                //searchLog->append("Enemies!!!!!!!");
                listID = 2;
            }
        } else {
            //searchLog->append( QString("Extracted: %1 %2 %3 %4").arg(unitPointer.c_str()).arg(unitTypeID).arg(numUnits).arg(regionID) );
            informationManager->gameState.addGroup(unitTypeID, numUnits, regionID, listID);
        }
    }

    //searchLog->append("Game state imported:");
    //searchLog->append( QString::fromStdString( informationManager->gameState.toString() ) );

    //LOG("Game state imported:");
    informationManager->gameState.mergeGroups();
    LOG( informationManager->gameState.toString() );


    /*
    // now that we have all the units in the game state, compute expected end frame
    informationManager->gameState.expectedEndFrame();
    // and forward until next point decision
    informationManager->gameState.resetFriendlyActions();

    // Search algorithm
    EvaluationFunctionBasic ef;
    ABCD minimax = ABCD(3, &ef);
    LOG("ABCD depth 3");
    //LOG( informationManager->gameState.toString() );
    playerActions_t bestActions = minimax.start(true, informationManager->gameState);

    LOG("Best actions: ");
    //std::map<SquadAgent*, BWAPI::Position> bestOrders;
    int groupID;
    uint8_t orderId;
    uint8_t targetRegionId;
    //BWAPI::Position targetPosition;
    for(playerActions_t::const_iterator i = bestActions.begin(); i!=bestActions.end(); ++i) {
        groupID = (*i).first;
        orderId = (*i).second.first;
        targetRegionId = (*i).second.second;
        LOG("  - Group ID: " << groupID << ", action: " << informationManager->gameState.getAbstractOrderName((int)orderId) << " region: " << (int)targetRegionId);
        //targetPosition = informationManager->gameState.getCenterRegionId((int)targetRegionId);
        //bestOrders[_idToSquad[groupID]] = targetPosition;
    }
    */
   
}