//////////////////////////////////////////////////////////////////////////////
//
// AVP_Settings.h
//
// Copyright (c) 2006 Rebellion. All rights reserved.
//
// A class for handling general game settings - the current difficulty
// setting, level, game type, etc.
//
//////////////////////////////////////////////////////////////////////////////

// B E G I N   F I L E   W R A P P E R ///////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef AVP_SETTINGS_H___
#define AVP_SETTINGS_H___ 1

// I N C L U D E S ///////////////////////////////////////////////////////////
#include "Core/Asura_PlatformBasics.h"

#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
#include "Network/Asura_NetSocket.h"
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK

// AVP
#include "Profile/AVP_Profile.h"
#include "Entity/AVP_entity_Classification.h"

// C O N S T A N T S /////////////////////////////////////////////////////////
static const u_int uAVP_MAX_ADDRESS_LEN = 32; // e.g. "xxx.xxx.xxx.xxx:xxxxx" or "xx:xx:xx:xx:xx:xx:xxxxx"
static const u_int uAVP_MAX_LEVELNAME_LEN = 64;

static const u_int uAVP_MAX_NET_PLAYERS_MIN = 8;
static const u_int uAVP_MAX_NET_PLAYERS_MAX = 18;


// C L A S S E S /////////////////////////////////////////////////////////////

class AVP_Settings
{

public:

	enum Difficulty
	{
		AVP_DIFFICULTY_EASY	= 0,
		AVP_DIFFICULTY_MEDIUM,
		AVP_DIFFICULTY_HARD,

		AVP_NUM_DIFFICULTIES
	};

	enum Species
	{
		AVP_SPECIES_UNKNOWN		= -1,
		AVP_SPECIES_PREDATOR	= 0,
		AVP_SPECIES_ALIEN,
		AVP_SPECIES_HUMAN,

		AVP_NUM_SPECIES
	};

	enum Team
	{
		AVP_TEAM_NONE		= 0,
		AVP_TEAM_ONE		= 1,
		AVP_TEAM_TWO, 
		AVP_TEAM_THREE,

		AVP_NUM_TEAMS
	};

	enum GameType
	{
		// since these must match up with the values set up in the 360 XLAST file
		// and they are also used in the GUIMenu stuff, the values should not be 
		// changed without taking care to update all of that at the same time.
		AVP_GAMETYPE_DISRUPTION_DOMINATION			= 0,
		AVP_GAMETYPE_DEATH_MATCH					= 1,
		AVP_GAMETYPE_HUNT							= 2,
		AVP_GAMETYPE_SPECIES_TEAM_DEATH_MATCH		= 3,
		AVP_GAMETYPE_SURVIVOR						= 4,
		AVP_GAMETYPE_MIXED_SPECIES_TEAM_DEATH_MATCH	= 5,
		AVP_GAMETYPE_DOMINATION						= 6,
		//AVP_GAMETYPE_SKIRMISH						= 7,
		//AVP_GAMETYPE_DUEL							= 8,
		
		AVP_NUM_GAMETYPES
	};

	enum Role
	{
		AVP_ROLE_NORMAL	= 0,
		AVP_ROLE_HUNTER,
		AVP_ROLE_PREY,

		AVP_NUM_ROLES
	};

	enum RespawnType
	{
		AVP_RESPAWNTYPE_TEAM = 0,
		AVP_RESPAWNTYPE_LOCATION,
		AVP_RESPAWNTYPE_RANDOM,
		AVP_RESPAWNTYPE_HUNTER,

		AVP_NUM_RESPAWNTYPES
	};

	enum Functionality
	{
		AVP_FUNCTIONALITY_MOTION_TRACKER = 0x00000001,
		AVP_FUNCTIONALITY_VISION_MODES   = 0x00000002,
		AVP_FUNCTIONALITY_TORCH          = 0x00000004
	};

	static void Initialise (void);
	static void Shutdown (void);

	static void ApplyProfileSettings();

#ifdef ASURA_TOOLS
	static bool HasSetLevelName() { return s_bLevelNameSet; }
#endif

	static const char**	GetSpeciesNames(void)					{ return(s_aszSpeciesNames); }
	static const char*	GetSpeciesName(const Species eSpecies)	{ return(s_aszSpeciesNames[eSpecies]); }
	static Species		GetSpeciesByClassification(const AVP_ENTITY_CLASSIFICATION eClassification); 

	static const char**	GetGameTypeNames(void)						{ return(s_aszGameTypeNames); }
	static const char*	GetGameTypeName(const GameType eGameType)	{ return(s_aszGameTypeNames[eGameType]); }

	static const char**	GetTeamNames(void)					{ return(s_aszTeamNames); }
	static const char*	GetTeamName(const Species eSpecies)	{ return(s_aszTeamNames[eSpecies]); }

#ifdef ASURA_TOOLS
	static const char**	GetRoleNames(void)					{ return(s_aszRoleNames); }
	static const char*	GetRoleName(const Role eRole)	{ return(s_aszRoleNames[eRole]); }

	static const char**	GetRespawnTypeNames(void)					{ return(s_aszRespawnTypeNames); }
	static const char*	GetRespawnTypeName(const RespawnType eRespawnType)	{ return(s_aszRespawnTypeNames[eRespawnType]); }

#endif //#ifdef ASURA_TOOLS

	static void SetLevelName( const char* szLevelName );
	static const char* GetLevelName() { return s_acLevelName; }

#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	static void SetAddressToConnectTo(const char* szAddress);
	static void SetAddressToConnectTo(const Asura_NetAddress& xAddress, u_int uPort);
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	static void SetIsServer(bool bIsServer) { s_bIsServer = bIsServer; }
	static void SetExternalNetworkActive(bool bExternalNetwork) { s_bExternalNetwork = bExternalNetwork; }
	static void SetOnlineGame(bool bOnline) { s_bOnline = bOnline; }
	static void SetNumberOfLocalPlayers( u_int uNum ) { s_uNumberOfLocalPlayers = uNum; }
	static void SetMaxNetPlayers( u_int uNum );
	static void SetGodMode(bool bGodMode) { s_bGodMode = bGodMode; }
	static void SetInfiniteAmmo(bool bInfiniteAmmo) { s_bInfiniteAmmo = bInfiniteAmmo;}
	static void SetPlayerSpecies(const Species eType);
	static void SetPlayerDifficulty( const Difficulty eType);
	static void SetRequestedMultiplayerTeam(const Team eTeam); 
		

	static char* GetAddressToConnectTo() { return s_acAddressToConnectTo; }
	static bool GetIsServer() { return s_bIsServer; }
	static bool GetExternalNetworkActive() { return s_bExternalNetwork; }
	static bool GetOnlineGame() { return s_bOnline; }
	static Species GetPlayerSpecies(void) { return(s_ePlayerSpecies); }
	static Difficulty GetPlayerDifficulty( void ) { return( s_ePlayerDifficulty ); }
	static Team GetRequestedMultiplayerTeam(void) { return static_cast<Team>(s_iRequestedMultiplayerTeam); }

	static u_int GetNumberOfLocalPlayers() { return s_uNumberOfLocalPlayers; }
	static u_int GetMaxNetPlayers() { return s_uMaxNetPlayers; }

#if defined(AVP_ALLOW_MULTIPLAYER)
	static bool IsSinglePlayer( void )	{ return !IsMultiPlayer(); } 
	static bool IsMultiPlayer( void );
#else
	static bool IsSinglePlayer( void )	{ return(true); }
	static bool IsMultiPlayer( void )	{ return(false); } 
#endif	//defined(AVP_ALLOW_MULTIPLAYER)

	static bool GetGodMode( void ) { return s_bGodMode && IsSinglePlayer(); }
	static bool GetInfiniteAmmo( void ) { return s_bInfiniteAmmo; }

	static void RefreshBlueprintData(const char* szFilename);
	static bool s_bGotStaticBlueprintValues;
	
	static void	 SetGameType( GameType eGameType )		{ s_eGameType = eGameType; }
	static GameType GetGameType( void  )				{ return s_eGameType; }
	static AVP_Profile* GetCurrentProfile() { return s_pxCurrentProfile;}

#if defined(AVP_MAX_FRAME_RATE)
	static float	GetMaxFrameRate(void)	{ return(AVP_MAX_FRAME_RATE); }
#else
	static float	GetMaxFrameRate(void)	{ return(0.0f); }
#endif	//!defined(AVP_MAX_FRAME_RATE)
#if defined(AVP_MAX_INGAME_FRAME_RATE)
	static float	GetMaxInGameFrameRate(void)	{ return(AVP_MAX_INGAME_FRAME_RATE); }
#else
	static float	GetMaxInGameFrameRate(void)	{ return(GetMaxFrameRate()); }
#endif	//!defined(AVP_MAX_INGAME_FRAME_RATE)

	// Functionality flags Get/Set
	static void  SetFunctionalityFlags(u_int uFlags) { s_uFunctionalityFlags = uFlags; }
	static u_int GetFunctionalityFlags()             { return s_uFunctionalityFlags;   }

	static bool  IsMotionTrackerFuncOn()           { return IsFlagged(AVP_FUNCTIONALITY_MOTION_TRACKER); }
	static void  SetMotionTrackerFunc (bool bTrue) { bTrue ? AddFlag(AVP_FUNCTIONALITY_MOTION_TRACKER) : RemoveFlag(AVP_FUNCTIONALITY_MOTION_TRACKER); }
	static bool  IsVisionModesFuncOn  ()           { return IsFlagged(AVP_FUNCTIONALITY_VISION_MODES);   }
	static void  SetVisionModesFunc   (bool bTrue) { bTrue ? AddFlag(AVP_FUNCTIONALITY_VISION_MODES) : RemoveFlag(AVP_FUNCTIONALITY_VISION_MODES); }
	static bool  IsTorchFuncOn        ()           { return IsFlagged(AVP_FUNCTIONALITY_TORCH);          } 
	static void  SetTorchFunc         (bool bTrue) { bTrue ? AddFlag(AVP_FUNCTIONALITY_TORCH) : RemoveFlag(AVP_FUNCTIONALITY_TORCH); }

	static bool s_bGodMode;
	static bool s_bInfiniteAmmo;
	static bool s_bAcidCheat;
private:
	
	// Flag functions
	static void AddFlag    (u_int uFlag) { s_uFunctionalityFlags |= uFlag;               }
	static void RemoveFlag (u_int uFlag) { s_uFunctionalityFlags &= ~uFlag;              }
	static bool IsFlagged  (u_int uFlag) { return ((s_uFunctionalityFlags & uFlag) != 0); }

#ifdef ASURA_TOOLS
	static bool s_bLevelNameSet;
#endif

	static const char*	s_aszSpeciesNames[AVP_NUM_SPECIES]; 
	static const char*	s_aszGameTypeNames[AVP_NUM_GAMETYPES]; 
	static const char*	s_aszTeamNames[AVP_NUM_TEAMS]; 

#ifdef ASURA_TOOLS
	static const char*	s_aszRoleNames[AVP_NUM_ROLES]; 
	static const char*	s_aszRespawnTypeNames[AVP_NUM_RESPAWNTYPES];
#endif //#ifdef ASURA_TOOLS

	static char s_acAddressToConnectTo[uAVP_MAX_ADDRESS_LEN];
 	static char s_acLevelName[uAVP_MAX_LEVELNAME_LEN];

	static GameType	s_eGameType; 
	static bool s_bIsServer;
	static bool s_bExternalNetwork;
	static bool s_bOnline;
	static Species s_ePlayerSpecies;
	static Difficulty s_ePlayerDifficulty;
	static int s_iRequestedMultiplayerTeam; // changed from Team to int to avoid aliasing warning on PS3
	static u_int s_uNumberOfLocalPlayers;
	static u_int s_uMaxNetPlayers;
   
	static AVP_Profile* s_pxCurrentProfile;
	// Functionalities flag
	static u_int       s_uFunctionalityFlags;

};

// AVP_NetworkSession is a class describing the game settings for a network game.
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
class AVP_NetworkSession
{
public:

	const char*					GetLevelName() const;
	AVP_Settings::GameType		GetGameType() const						{ return m_eGameType; }
	int							GetNumberOfTeams() const				{ return m_iNumberOfTeams; }
	int							GetMaxNumberOfPlayers() const			{ return m_iMaxNumberOfPlayers; }
	AVP_Settings::Species		GetTeamOneSpecies() const				{ return m_iTeamOneSpecies; }
	AVP_Settings::Species		GetTeamTwoSpecies() const				{ return m_iTeamTwoSpecies; }
	AVP_Settings::Species 		GetTeamThreeSpecies() const				{ return m_iTeamThreeSpecies; }
	bool						GetAllowMixedTeams() const				{ return m_bAllowMixedTeams; }
	bool 						GetMutuallyExclusiveTeams() const		{ return m_bMutuallyExclusiveTeams; }
	bool						GetRespawnUponDeath() const				{ return m_bRespawnUponDeath; }
	AVP_Settings::RespawnType	GetRespawnType() const					{ return m_iRespawnType; }
	int 						GetLivesAvailablePerTeam() const		{ return m_iLivesAvailablePerTeam; }
	int 						GetSpeciesRatioAlien() const			{ return m_iSpeciesRatioAlien; }
	int 						GetSpeciesRatioHuman() const			{ return m_iSpeciesRatioHuman; }
	int 						GetSpeciesRatioPredator() const			{ return m_iSpeciesRatioPredator; }
	bool 						GetFriendlyFireOn() const				{ return m_bFriendlyFireOn; }
	int 						GetScoreLimit() const					{ return m_iScoreLimit; }
	int 						GetTimeLimit() const					{ return m_iTimeLimit; }

	void SetLevelName(const char* szName);
	void SetGameType(AVP_Settings::GameType eGameType)					{ m_eGameType = eGameType; }
	void SetNumberOfTeams(const int iNumberOfTeams)						{ m_iNumberOfTeams = iNumberOfTeams; }
	void SetMaxNumberOfPlayers(const int iMaxNumberOfPlayers)			{ m_iMaxNumberOfPlayers = iMaxNumberOfPlayers; }
	void SetTeamOneSpecies(const AVP_Settings::Species iSpecies)		{ m_iTeamOneSpecies = iSpecies; }
	void SetTeamTwoSpecies(const AVP_Settings::Species iSpecies)		{ m_iTeamTwoSpecies = iSpecies; }
	void SetTeamThreeSpecies(const AVP_Settings::Species iSpecies)		{ m_iTeamThreeSpecies = iSpecies; }
	void SetAllowMixedTeams(const bool bAllowMixedTeams)				{ m_bAllowMixedTeams = bAllowMixedTeams; }
	void SetMutuallyExclusiveTeams(const bool bMutuallyExclusive)		{ m_bMutuallyExclusiveTeams = bMutuallyExclusive; }
	void SetRespawnUponDeath(const bool bRespawnUponDeath)				{ m_bRespawnUponDeath = bRespawnUponDeath; }
	void SetRespawnType(const AVP_Settings::RespawnType iRespawnType)	{ m_iRespawnType = iRespawnType; }
	void SetLivesAvailablePerTeam(const int iLivesPerTeam)				{ m_iLivesAvailablePerTeam = iLivesPerTeam; }
	void SetSpeciesRatioAlien(const int iRatio)							{ m_iSpeciesRatioAlien = iRatio; }
	void SetSpeciesRatioHuman(const int iRatio)							{ m_iSpeciesRatioHuman = iRatio; }
	void SetSpeciesRatioPredator(const int iRatio)						{ m_iSpeciesRatioPredator = iRatio; }
	void SetFriendlyFireOn(const bool bFriendlyFireOn)					{ m_bFriendlyFireOn = bFriendlyFireOn; }
	void SetScoreLimit(const int iScoreLimit)							{ m_iScoreLimit = iScoreLimit; }
	void SetTimeLimit(const int iTimeLimit)								{ m_iTimeLimit = iTimeLimit; }

	// Set from AVP_Settings and AVP_Multiplayer_GameRules
	void Set();

	// Copy data to settings and game rules
	void CopyToSettings() const;

private:

	bool IsValid() const;

	u_int						m_uSize;
	char						m_acLevelName[uAVP_MAX_LEVELNAME_LEN];
	AVP_Settings::GameType		m_eGameType;
	int							m_iNumberOfTeams;
	int							m_iMaxNumberOfPlayers;
	AVP_Settings::Species		m_iTeamOneSpecies;
	AVP_Settings::Species		m_iTeamTwoSpecies;
	AVP_Settings::Species		m_iTeamThreeSpecies;
	bool						m_bAllowMixedTeams;
	bool						m_bMutuallyExclusiveTeams;
	bool						m_bRespawnUponDeath;
	AVP_Settings::RespawnType	m_iRespawnType;
	int							m_iLivesAvailablePerTeam;
	int							m_iSpeciesRatioAlien;
	int							m_iSpeciesRatioHuman;
	int							m_iSpeciesRatioPredator;
	bool						m_bFriendlyFireOn;
	int							m_iScoreLimit;
	int							m_iTimeLimit;
};

#endif

// E N D   F I L E   W R A P P E R ///////////////////////////////////////////

#endif // #ifndef AVP_SETTINGS_H___
