// words.cpp : Defines the class behaviors for the application.
//

#include "stdafx.h"
#include "words.h"
#include "mainDlg.h"
#include "dict.h"
#include "aboutbox.h"
#include "hostgamedlg.h"
#include "joingamedlg.h"
#include "game.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMain

BEGIN_MESSAGE_MAP(CMain, CWinApp)
	//{{AFX_MSG_MAP(CMain)
	ON_COMMAND(ID_GAME_ENDGAME, OnGameEndgame)
	ON_COMMAND(ID_GAME_EXIT, OnGameExit)
	ON_COMMAND(ID_HELP_ABOUTTHISGAME, OnHelpAbout)
	ON_COMMAND(ID_GAME_HOSTGAME, OnGameHostgame)
	ON_COMMAND(ID_GAME_JOINNETWORKGAME, OnGameJoingame)
	//}}AFX_MSG_MAP
	ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMain construction

CMain::CMain()
{

	// Initialise End Game handles
	m_hEventGameFinished = CreateEvent(NULL, FALSE, FALSE, NULL); // auto reset, initially reset
	m_hEventFinishGame = CreateEvent(NULL, TRUE, FALSE, NULL); // Manual reset, initially reset

	// Initialise gametype to none
	m_cTheGame.m_eGameType = NONE;

}
/////////////////////////////////////////////////////////////////////////////
// The one and only CMain object

CMain theApp;

/////////////////////////////////////////////////////////////////////////////
// CMain initialization

BOOL CMain::InitInstance()
{
	TRACE( "In initinstance\n " );

	if (!AfxSocketInit())
	{
		AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
		return FALSE;
	}

	AfxEnableControlContainer();

	// Standard initialization
	// If you are not using these features and wish to reduce the size
	//  of your final executable, you should remove from the following
	//  the specific initialization routines you do not need.

#ifdef _AFXDLL
	Enable3dControls();			// Call this when using MFC in a shared DLL
#else
	Enable3dControlsStatic();	// Call this when linking to MFC statically
#endif

	CMainDlg dlg;
	m_pMainWnd = &dlg;
	m_pcMainDlg = &dlg;

	int nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		// TODO: Place code here to handle when the dialog is
		//  dismissed with OK
	}
	else if (nResponse == IDCANCEL)
	{
		// TODO: Place code here to handle when the dialog is
		//  dismissed with Cancel
	}

	
	// Nullify pointer to main dialog, as it has been destroyed
	m_pcMainDlg = NULL;

	// Since the dialog has been closed, return FALSE so that we exit the
	//  application, rather than start the application's message pump.
	return FALSE;
}

// Function that is run when the user selects Host game on the
// Game menu
void CMain::OnGameHostgame() 
{
	TRACE( "Hosting game\n" );

	CHostGameDlg dlg;
	CNet socket;
	CMesg message;

	int i, j;

	// Check whether there is a game running
	if( m_cTheGame.m_eGameType != NONE ){
		
		// Ask user whether to quit current game
		int nChoice = AfxMessageBox( "End Current Game?", MB_YESNO | MB_ICONQUESTION );

		// Do what user says
		if( nChoice == IDYES ){
			OnGameEndgame();
		}else{
			return;
		}
	}

	// Set default player type selections
	dlg.m_nPlayer1Type = 0;
	dlg.m_nPlayer2Type = 0;
	dlg.m_nPlayer3Type = 0;
	dlg.m_nPlayer4Type = 0;	

	// Exit function if dialog was cancelled
	if( dlg.DoModal() == IDCANCEL ){
		return;
	}
	
	// Reset the game finished event
	ResetEvent( m_hEventFinishGame );

	m_cTheGame.m_eGameType = SERVER;
	
	// Set Window to send messages to
	m_cTheGame.m_pcwndMsgHandler = m_pcMainDlg;
		
	// Set handles
	m_cTheGame.m_hEventGoFinished = m_pcMainDlg->m_hEventGoFinished;
	m_cTheGame.m_hEventUpdateFinished = m_pcMainDlg->m_hEventUpdateFinished;
	m_cTheGame.m_hEventGameFinished = m_hEventGameFinished;
	m_cTheGame.m_hEventFinishGame = m_hEventFinishGame;
	
	// Set Player modes
	m_cTheGame.m_Players[0].PlayerMode = (PlayerMode_t)dlg.m_nPlayer1Type;
	m_cTheGame.m_Players[1].PlayerMode = (PlayerMode_t)(dlg.m_nPlayer2Type + 1);
	m_cTheGame.m_Players[2].PlayerMode = (PlayerMode_t)(dlg.m_nPlayer3Type + 1);
	m_cTheGame.m_Players[3].PlayerMode = (PlayerMode_t)(dlg.m_nPlayer4Type + 1);

	// Set player names
	m_cTheGame.m_Players[0].szPlayerName = dlg.m_szPlayer1Name;
	m_cTheGame.m_Players[1].szPlayerName = dlg.m_szPlayer2Name;
	m_cTheGame.m_Players[2].szPlayerName = dlg.m_szPlayer3Name;
	m_cTheGame.m_Players[3].szPlayerName = dlg.m_szPlayer4Name;

	// Initialise server
	socket.initserver(2000);
	
	// Let Network players join
	TRACE( "Waiting for network players\n" );
	
	// Open a socket to each network player and get player names
	for( i=0; i<4; i++ ){
		if( m_cTheGame.m_Players[i].PlayerMode == NETWORK ){
			
			// Get pointer to connection
			m_cTheGame.m_Players[i].pcNetSocket = socket.wait_accept();
			
			TRACE( "Player %d connected\n", i );
			
			// Get the player name
			message.recv_mesg(m_cTheGame.m_Players[i].pcNetSocket);
			m_cTheGame.m_Players[i].szPlayerName = message.m_playername[0];		
		}
	}

	TRACE( "Network Players connected\n" );
	// Close the server port
	socket.close_sock();
	
	// Send acknowledgements to network players
	
	// Set the player names for the message
	for( i=0; i<4; i++ )
		message.m_playername[i] = m_cTheGame.m_Players[i].szPlayerName;
	
	// Send to each network player
	for( i=0; i<4; i++ ){
		
		if( m_cTheGame.m_Players[i].PlayerMode == NETWORK ){
			
			// Set details for all players
			for( j = 0; j < 4; j++ ){				
				// Convert network player and remote player types so
				// that they are correct on each machine
				if( m_cTheGame.m_Players[j].PlayerMode == LOCAL ){
					message.m_playmode[j] = (int)NETWORK;
				}else if( i == j && m_cTheGame.m_Players[j].PlayerMode == NETWORK ){
					message.m_playmode[j] = (int)LOCAL;
				}else{
					message.m_playmode[j] = (int)m_cTheGame.m_Players[j].PlayerMode;
				}
			}
			
			// Get the player name
			message.send_mesg(m_cTheGame.m_Players[i].pcNetSocket, N_PLAYACK);
		}
	}

	// Initialise the game
	m_cTheGame.InitGame();	
	
	// Start User Interface for game
	m_pcMainDlg->StartGame( &m_cTheGame );

	// Start the new thread
	AfxBeginThread( HostGame, &m_cTheGame );
}

// Function that is run when the user selects Join network
// game on the Game menu
void CMain::OnGameJoingame() 
{
	TRACE( "Joining a network game\n" );

	// Declare local variables
	CJoinGameDlg dlg;
	CNet * socket = new CNet;
	CMesg message;
	LPTSTR pchTemp;
	int i;

	// Check whether there is a game running
	if( m_cTheGame.m_eGameType != NONE ){
		
		// Ask user whether to quit current game
		int nChoice = AfxMessageBox( "End Current Game?", MB_YESNO | MB_ICONQUESTION );

		// Do what user says
		if( nChoice == IDYES ){
			OnGameEndgame();
		}else{
			return;
		}
	}

	// Exit function if dialog was cancelled
	if( dlg.DoModal() == IDCANCEL ){
		return;
	}

	TRACE( "PlayerName = %s, ServerName = %s\n", dlg.m_szPlayerName, dlg.m_szServerName );

	// Reset the game finished event
	ResetEvent( m_hEventFinishGame );

	// Set the game type
	m_cTheGame.m_eGameType = PROXY;
	
	// Set Window to send messages to
	m_cTheGame.m_pcwndMsgHandler = m_pcMainDlg;
		
	// Set handles
	m_cTheGame.m_hEventGoFinished = m_pcMainDlg->m_hEventGoFinished;
	m_cTheGame.m_hEventUpdateFinished = m_pcMainDlg->m_hEventUpdateFinished;
	m_cTheGame.m_hEventGameFinished = m_hEventGameFinished;
	m_cTheGame.m_hEventFinishGame = m_hEventFinishGame;

	// Connect to server
	pchTemp = new TCHAR[dlg.m_szServerName.GetLength()+1];_tcscpy(pchTemp, dlg.m_szServerName);
	socket->initclient(2000, pchTemp);

	TRACE( "Connected, sending player name\n" );
	
	// Tell server player name
	message.m_playername[0] = dlg.m_szPlayerName;
	message.send_mesg(socket, N_PLAYREQ);
	
	// Get acknowledgement, incorporating playernames and playermodes
	TRACE( "Waiting for acknowledgement\n" );
	message.recv_mesg(socket);

	// Set Player modes
	m_cTheGame.m_Players[0].PlayerMode = (PlayerMode_t)message.m_playmode[0];
	m_cTheGame.m_Players[1].PlayerMode = (PlayerMode_t)message.m_playmode[1];
	m_cTheGame.m_Players[2].PlayerMode = (PlayerMode_t)message.m_playmode[2];
	m_cTheGame.m_Players[3].PlayerMode = (PlayerMode_t)message.m_playmode[3];

	// Set player names 
	m_cTheGame.m_Players[0].szPlayerName = message.m_playername[0];
	m_cTheGame.m_Players[1].szPlayerName = message.m_playername[1];
	m_cTheGame.m_Players[2].szPlayerName = message.m_playername[2];
	m_cTheGame.m_Players[3].szPlayerName = message.m_playername[3];

	TRACE( "Stored info sent from server %d\n", socket->sock_num );
	
	// Now we know which player this machine is the socket pointer can
	// be set
	for( i = 1; i <4; i++ ){
		if( m_cTheGame.m_Players[i].PlayerMode == LOCAL ){
			m_cTheGame.m_Players[i].pcNetSocket = socket;
			break;
		}
	}

	// Initialise the game
	m_cTheGame.InitGame();
		
	// Start User Interface for game
	m_pcMainDlg->StartGame( &m_cTheGame );
	
	// Start the new thread
	AfxBeginThread( JoinGame, &m_cTheGame );

}


// Function that is run when end game is selected on the game menu
void CMain::OnGameEndgame() 
{
	TRACE( "Ending Current Game\n" );

	switch( m_cTheGame.m_eGameType ){

	case SERVER :

		// Send end game message to worker thread
		TRACE( "Sending finishGame Event\n" );
		SetEvent( m_hEventFinishGame );

		// Tell Main dialog to Set features to No-Game conditions
		m_pcMainDlg->OnEndGame( (WPARAM)&m_cTheGame, NULL);
		
		// Wait for Thread to signal that it is exiting
		TRACE( "Waiting for Game finished event\n" );
		WaitForSingleObject(m_hEventGameFinished, INFINITE);

		TRACE( "Game finished, worker thread should be toasted\n" );
		break;

	case PROXY :
	
		break;
	
	default :
		// Send Message to say there's no game running
		TRACE( "There's no game running\n" );
		AfxMessageBox( "There's no game running to end", MB_OK |MB_ICONINFORMATION );
	}
	
}

// Function that is run when exit is selected on the game menu
void CMain::OnGameExit() 
{
	// End the current game if there is one
	if( m_cTheGame.m_eGameType != NONE )
		OnGameEndgame();
	
	// Close the main dialog box
	m_pMainWnd->EndModalLoop( IDOK );

	TRACE( "Exiting Program\n" );
}

// Function that is run when about this game is selected on
// the help menu
void CMain::OnHelpAbout() 
{
	CAboutbox dlg;

	// Show dialog box
	dlg.DoModal();
	
}




