#include <windows.h>
#include <stdio.h>
#include <bncs_string.h>
#include <bncs_config.h>
#include "TicTacToe.h"

#define PNL_MAIN	1

#define TIMER_SETUP	1

// this nasty little macro to make our class visible to the outside world
EXPORT_BNCS_SCRIPT( TicTacToe )

// constructor - equivalent to ApplCore STARTUP
TicTacToe::TicTacToe( bncs_client_callback * parent, const char * path ) : bncs_script_helper( parent, path )
{
	// show a panel from file p1.bncs_ui and we'll know it as our panel PNL_MAIN
	panelShow( PNL_MAIN, "p1.bncs_ui" );
	xActive = true;
	oActive = false;
	m_selectedButton = "";
	maxClicks = 9;
	clickNumber = 0;
	b1State = "";
	b2State = "";
	b3State = "";
	b4State = "";
	b5State = "";
	b6State = "";
	b7State = "";
	b8State = "";
	b9State = "";
	winner = "";
	statusInfoDriver = 20;
	infoRegister(statusInfoDriver, 1, 10);
	for (int i = 1; i <= 9; i++)
	{
		infoWrite(statusInfoDriver, "", i);
		textPut("notify.released", "true", PNL_MAIN, i);
	}
	infoWrite(statusInfoDriver, "", 10);
	
	infoPoll(statusInfoDriver, 1, 10);


	// you may need this call to set the size of this component 
	//  if it's used in a popup window 
//	setSize( 1024,668 );		// set the size explicitly
//	setSize( PNL_MAIN );		// set the size to the same as the specified panel
}

// destructor - equivalent to ApplCore CLOSEDOWN
TicTacToe::~TicTacToe()
{
}

// all button pushes and notifications come here
void TicTacToe::buttonCallback( buttonNotify *b )
{

	if (b->id() == "Reset")
	{
		
		for (int i = 1; i <= 9; i++)
		{
			infoWrite(statusInfoDriver, "", i);
			textPut("notify.released", "true", PNL_MAIN, i);

		}

		infoWrite(statusInfoDriver, "", 10);
		clickNumber = 0;
		b1State = "";
		b2State = "";
		b3State = "";
		b4State = "";
		b5State = "";
		b6State = "";
		b7State = "";
		b8State = "";
		b9State = "";
		winner = "";
		for (int i = 1; i <= 9; i++)
		{
			textPut("pixmap", "", PNL_MAIN, i);
		}
		
		textPut("text", "Reset", PNL_MAIN, "Reset");
		m_selectedButton = "";
	}
	if ((clickNumber < 9) && (b->id()!="Reset"))
	{
		m_selectedButton = b->id();
		textPut("notify.released", 0, PNL_MAIN, m_selectedButton);
	
		if (xActive == true)
		{
			infoWrite(statusInfoDriver, "x", m_selectedButton);
			infoWrite(statusInfoDriver, "o", 10);

		}
		else
		{
			infoWrite(statusInfoDriver, "o", m_selectedButton);
			infoWrite(statusInfoDriver, "x", 10);
		}
		clickNumber++;

	}

}

// all revertives come here
int TicTacToe::revertiveCallback( revertiveNotify * r )
{
	if (r->device() == statusInfoDriver)
	{
		if (r->index() <= 9)
		{
			textPut("pixmap", r->sInfo() + ".png", PNL_MAIN, r->index());
		}
		switch (r->index())
		{
		case 1:	b1State = r->sInfo();	break;
		case 2:	b2State = r->sInfo();	break;
		case 3:	b3State = r->sInfo();	break;
		case 4:	b4State = r->sInfo();	break;
		case 5:	b5State = r->sInfo();	break;
		case 6:	b6State = r->sInfo();	break;
		case 7:	b7State = r->sInfo();	break;
		case 8:	b8State = r->sInfo();	break;
		case 9:	b9State = r->sInfo();	break;
		case 10:	if (r->sInfo() == "o")
					{
						xActive = false;
						oActive = true;
					}	
					else
					{
						oActive = false;
						xActive = true;
					}

					break;
		default:						break;
		}
		winningGame = stateCheck();
		if (winningGame == true)
		{
			textPut("text", "Winner is " + winner, PNL_MAIN, "Reset");
			clickNumber = 9;
		}
	}
return 0;
}

// all database name changes come back here
void TicTacToe::databaseCallback( revertiveNotify * r )
{
}

// all parent notifications come here i.e. when this script is just one 
//  component of another dialog then our host might want to tell us things
bncs_string TicTacToe::parentCallback( parentNotify *p )
{
	if( p->command() == "return" )
	{
		if( p->value() == "all" )
		{	// Persisting values for bncs_vis_ed
			bncs_stringlist sl;
			
			sl << bncs_string( "statusInfoDriver=%1" ).arg( m_statusInfoDriver );
			
			return sl.toString( '\n' );
		}

		else if( p->value() == "myParam" )
		{	// Specific value being asked for by a textGet
			return( bncs_string( "%1=%2" ).arg( p->value() ).arg( m_myParam ) );
		}

	}
	else if( p->command() == "instance" && p->value() != m_instance )
	{	// Our instance is being set/changed
		m_instance = p->value();
		//Do something instance-change related here
	}

	else if( p->command() == "statusInfoDriver" )
	{	// Persisted value or 'Command' being set here
		m_statusInfoDriver = p->value();
		statusInfoDriver = m_statusInfoDriver.toInt();
	}

	// ***** CONNECTIONS EVENTS HELPER LIST *****
	else if( p->command() == "_events" )
	{	// Helper-list of everything in this component generated by hostNotify's
		bncs_stringlist sl;

		sl << "notify=*";		
		
		return sl.toString( '\n' );
	}

	// ***** CONNECTIONS COMMANDS HELPER LIST *****
	else if( p->command() == "_commands" )
	{	// Helper-list of any commands/parameters you might want to set at run-time
		bncs_stringlist sl;
		
		sl << "myParam=[value]";
		
		return sl.toString( '\n' );
	}

	return "";
}

// timer events come here
void TicTacToe::timerCallback( int id )
{
	switch( id )
	{
	case TIMER_SETUP:
		timerStop(id);
		break;

	default:	// Unhandled timer event
		timerStop(id);
		break;
	}
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////// Callbacks above - Methods below ///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////


bool TicTacToe::stateCheck()
{
	bool winningGame;
	winningGame = false;
	
	if (((b3State == "x") && (b5State == "x") && (b7State == "x")) || ((b1State == "x") && (b2State == "x") && (b3State == "x")) || ((b7State == "x") && (b8State == "x") && (b9State == "x")) || ((b1State == "x") && (b5State == "x") && (b9State == "x")) || ((b1State == "x") && (b4State == "x") && (b7State == "x")) || ((b2State == "x") && (b5State == "x") && (b8State == "x")) || ((b3State == "x") && (b6State == "x") && (b9State == "x")) || ((b4State == "x") && (b5State == "x") && (b6State == "x")))
	{
		winner = "x";
		winningGame = true;
	}

	
	if (((b1State == "o") && (b2State == "o") && (b3State == "o")) || ((b1State == "o") && (b4State == "o") && (b7State == "o")) || ((b2State == "o") && (b5State == "o") && (b8State == "o")) || ((b3State == "o") && (b6State == "o") && (b9State == "o")) || ((b4State == "o") && (b5State == "o") && (b6State == "o")) || ((b7State == "o") && (b8State == "o") && (b9State == "o")) || ((b1State == "o") && (b5State == "o") && (b9State == "o")) || ((b3State == "o") && (b5State == "o") && (b7State == "o")))
	{
		winner = "o";
		winningGame = true;
	}
	//debug(b1State + " - " + b2State + " - " + b3State + "\n");
	//debug(b4State + " - " + b5State + " - " + b6State + "\n");
	//debug(b7State + " - " + b8State + " - " + b9State + "\n");

	return winningGame;
}