/**
*
* \file Asura_Multiplayer_Comms.h
*
* Created by Richard May - 04/08/2003 17:49:29
*
* Copyright (C) 2002 Rebellion, All Rights Reserved.
*
* \brief
*
**/

// Richard May - 29/10/2003 15:22:33 - 
//
// The multiplayer comms system allows client players to communicate using a standard 
// text-based comms method. To use the system, add calls to Initialise, Shutdown, 
// Update and Render as required. 
// 
// The comms system requires a Project_Render function, used to display the message 
// text as it is being entered. It also needs Project_Update and Project_SendMessage.
//
// It is recommended that all player input is ignored whilst a comms session is open. 
// Use the IsSessionOpen() method for this purpose.
// 
// Modes
// -----
//
// The basic system supports three modes - Talk, Tell and Team. Talk is a standard 
// 'broadcast' style message, Tell a 'private message' that can be sent to an individual
// player and Team is a team-members only broadcast. Other project specific modes can be
// added, but these must be handled directly in Project_SendMessage.
//
// Message Handling
// ----------------
//
// If the comms system is enabled, the Asura_Server message handler will deal with both 
// Talk and Tell-style messages. A project-specific handler is required on the server-side
// for 'Team' messages. Other modes may also require their own server-side message handler.
//
// Currently the server will despatch any talk / tell messages directly to the entity that
// they are 'addressed' to. It is up to the project-implementation of that entity to handle
// the message accordingly. Dredd added these messages to it's HUD text display and also 
// the command console, for example, but this isn't the only way of doing things.
//
// Profanity Filtering
// -------------------
// 
// Included in the comms system is the profanity filter, something that is required for many
// console internet games. It works by stripping recognised words (and hopefully phrases too,
// ultimately) and replacing them with randomised punctuation. This isn't actually used
// in the comms system directly, but is provided for you to add to project specific display
// code, so that filtering can be optional, not mandatory.
//

#ifdef ASURA_USE_PRAGMA_ONCE
	#pragma once
#endif

#ifndef __ASURA_MULTIPLAYER_COMMS_H__
#define __ASURA_MULTIPLAYER_COMMS_H__

#ifdef ASURA_SUPPORT_MULTIPLAYER_COMMS

/************/
/* Includes.*/
/************/

// asura
#include "Core/Asura_HashTree.h"
#include "Core/Asura_Maths.h"
#include "Core/Asura_PlatformBasics.h"
#include "Core/Asura_UserInput.h"
#include "Network/Asura_Guid.h"

/***********/
/* Defines */
/***********/

#define  ASURA_MPCOMMS_MAX_MSG_SIZE  256

/************/
/* Classes. */
/************/

/*************************************************************
 *
 * Class Name    : Asura_Multiplayer_Comms_System
 *
 * Author        : Richard May
 *
 * Description   : Communication system for multiplayer games
 *
 *************************************************************/
class Asura_Multiplayer_Comms_System
{
	friend class Asura_Chunk_MPComms_BannedList;	

public:
	/* Public access enums */
	enum ASURA_MPCOMMS_SESSION_MODE
	{
		MPCOMMS_SESSIONMODE_TALK,
		MPCOMMS_SESSIONMODE_TEAM,
		MPCOMMS_SESSIONMODE_TELL,
	};	
	
	/* Public interface functions. */
	static void Initialise(void);
	static void Shutdown(void);
	static void Reset(void);

	// (MH - 12.01.2004) separated out loading / freeing of banned words
	static void LoadBannedWordList(void);
	static void UnloadBannedWordList(void);
	
	static void Update(void);
	static void Render(void);

	// project specific functions
	static void Project_Update(void);
	static void Project_Render(void);

	// session management
	static void OpenCommsSession( Asura_Guid uSender, u_int uMode );	
	static void CloseCommsSession( void );
	static bool IsSessionOpen(void) { return s_bSessionOpen; }

	// the actual message functions
	static bool Talk( const Asura_UnicodeChar* wszMsg );
	static bool Team( const Asura_UnicodeChar* wszMsg );
	static bool Tell( const Asura_UnicodeChar* wszMsg );
	static void SetSenderGuid( Asura_Guid uSenderGuid ) { s_uSenderGuid = uSenderGuid; }; // this is necessary for console talk commands
	static Asura_Guid GetSenderGuid( ) { return s_uSenderGuid; }; // this is necessary for console talk commands
	static bool IsReadyToSendMessage(void) { return (s_fMessageDelayTimer <= 0.0f); }
	static ASURA_MPCOMMS_SESSION_MODE GetSessionMode() { return static_cast<ASURA_MPCOMMS_SESSION_MODE>(s_uSessionMode); }

	// profanity filtering, to stop all those bad people from using naughty words
	static bool FilterProfanities( Asura_UnicodeChar* wszMsg );
	static bool Project_GetProfanityFilterEnabled();		// allows projects to disable the filter. Sniper has a menu option for it.

protected:
	/* Enums */
	enum MATCH_RESULT
	{
		MATCH_NONE,		// definitely not a profanity
		MATCH_POSSIBLE, // possibly a profanity (so far, each word matches)
		MATCH_POSITIVE, // definitely a profanity
	};

protected:
	/* Helper functions. */
	static bool SendMessage( void );
	static bool Project_SendMessage( void );
	static void ClearInputBuffer( void );

	// utilities
	static bool HandleInput( ASURA_KEYID uKey );
	static void MakeLowerCase( Asura_UnicodeChar* wszString );
	static void ConvertUnderscores( Asura_UnicodeChar* wszString );
	
	// profanity filtering
	static MATCH_RESULT MatchProfanity( const Asura_UnicodeChar* wszWord );
	static Asura_UnicodeChar GetRandomPunctuation(void);
	static bool InitialiseProfanityList(void);

protected:	
	/* Data. */
	static Asura_Guid s_uSenderGuid;
	
	// input variables
	static Asura_UnicodeChar s_wszInputBuffer[ASURA_MPCOMMS_MAX_MSG_SIZE];
	static u_int s_uCursorPosition;
	static float s_fCursorFlashTimer;
	static bool  s_bSessionOpen;
	static u_int s_uSessionMode;
	static float s_fMessageDelayTimer;

	// profanity filtering
	static Asura_HashTree s_xProfanityList;

	// constant data
	static const float s_fMessageDelayPeriod;
	static const char* s_szProfanityFile;
};
/* end of class Asura_Multiplayer_Comms_System */


/* Message classes */
class Asura_Msg_MultiPlayerComms_Talk
{
public:
	Asura_Guid m_uFrom;
	Asura_UnicodeChar m_wszMsg[ASURA_MPCOMMS_MAX_MSG_SIZE];
};


class Asura_Msg_MultiPlayerComms_Tell : public Asura_Msg_MultiPlayerComms_Talk
{
public:
	Asura_Guid m_uTo;
};

#endif // ASURA_SUPPORT_MULTIPLAYER_COMMS

/****************/
/* End of file. */
/****************/
#endif//__ASURA_MULTIPLAYER_COMMS_H__
