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

// I N C L U D E S ///////////////////////////////////////////////////////////

#include "Core/Asura.h"

// This file's header.
#include "Core/AVP_Settings.h"

// Asura headers
#include "Blueprint/Asura_Blueprint.h"
#include "Blueprint/Asura_Blueprint_System.h"
#include "Core/Asura_String.h"
#include "Network/Asura_NetSocket.h"
#include "Network/Online/Asura_Lobby.h"
#if defined(ASURA_SUPPORT_COMMAND_CONSOLE)
#include "Interface/Asura_CommandConsole.h"
#endif	// defined(ASURA_SUPPORT_COMMAND_CONSOLE)

// Game headers
#include "Multiplayer/AVP_Multiplayer_GameRules.h"

// S T A T I C   C L A S S   D A T A /////////////////////////////////////////
bool AVP_Settings::s_bGotStaticBlueprintValues	= false;
AVP_Profile* AVP_Settings::s_pxCurrentProfile	= NULL;

#if defined(_DEBUG)
bool AVP_Settings::s_bGodMode = true;
#else
bool AVP_Settings::s_bGodMode = false;
#endif	//defined(_DEBUG)

#if defined(_DEBUG)
bool AVP_Settings::s_bInfiniteAmmo = true;
#else
bool AVP_Settings::s_bInfiniteAmmo = false;
#endif

bool AVP_Settings::s_bAcidCheat= false;

#ifdef ASURA_TOOLS
bool AVP_Settings::s_bLevelNameSet = false;
#endif


char						AVP_Settings::s_acAddressToConnectTo[uAVP_MAX_ADDRESS_LEN];
char						AVP_Settings::s_acLevelName[uAVP_MAX_LEVELNAME_LEN]	= AVP_GENERATE_FULL_LEVEL_FILENAME("Demo_SPS");
AVP_Settings::GameType		AVP_Settings::s_eGameType = AVP_GAMETYPE_DEATH_MATCH;
bool 						AVP_Settings::s_bIsServer = true;
bool 						AVP_Settings::s_bExternalNetwork = false;
bool 						AVP_Settings::s_bOnline = false;
AVP_Settings::Species		AVP_Settings::s_ePlayerSpecies = AVP_SPECIES_UNKNOWN;
AVP_Settings::Difficulty	AVP_Settings::s_ePlayerDifficulty = AVP_DIFFICULTY_MEDIUM;
int							AVP_Settings::s_iRequestedMultiplayerTeam = AVP_Settings::AVP_TEAM_NONE; 
u_int 						AVP_Settings::s_uNumberOfLocalPlayers = 1;
u_int 						AVP_Settings::s_uMaxNetPlayers = 8;
u_int                       AVP_Settings::s_uFunctionalityFlags = UINT_MAX;

const Asura_Char* AVP_Settings::s_aszSpeciesNames[AVP_NUM_SPECIES] = 
{
	"Predator",	// AVP_SPECIES_PREDATOR
	"Alien",	// AVP_SPECIES_ALIEN
	"Human",	// AVP_SPECIES_HUMAN
};

const Asura_Char* AVP_Settings::s_aszGameTypeNames[AVP_NUM_GAMETYPES] = 
{
	"Disruption Domination",			// AVP_GAMETYPE_DISRUPTION_DOMINATION,
	"Death Match",						// AVP_GAMETYPE_DEATH_MATCH,
	"Hunt",								// AVP_GAMETYPE_HUNT,
	"Species Team Death Match",			// AVP_GAMETYPE_SPECIES_TEAM_DEATH_MATCH,
	"Survivor",							// AVP_GAMETYPE_SURVIVOR,
	"Mixed Species Team Death Match",	// AVP_GAMETYPE_MIXED_SPECIES_TEAM_DEATH_MATCH
	"Domination",						// AVP_GAMETYPE_DOMINATION,
	//"Instant action",					// AVP_GAMETYPE_INSTANT_ACTION,
};

const char* AVP_Settings::s_aszTeamNames[AVP_NUM_TEAMS] = 
{
	"None",		// AVP_TEAM_NONE,
	"Team1",	// AVP_TEAM_ONE,
	"Team2", 	// AVP_TEAM_TWO, 
	"Team3",	// AVP_TEAM_THREE,
};

#ifdef ASURA_TOOLS
const char* AVP_Settings::s_aszRoleNames[AVP_NUM_ROLES] = 
{
	"Normal",	// AVP_ROLE_NORMAL,
	"Hunter",	// AVP_ROLE_HUNTER,
	"Prey",		// AVP_ROLE_PREY,
};

const char* AVP_Settings::s_aszRespawnTypeNames[AVP_NUM_RESPAWNTYPES] = 
{
	"Team",		// AVP_RESPAWNTYPE_TEAM,
	"Location",	// AVP_RESPAWNTYPE_LOCATION,
	"Random",	// AVP_RESPAWNTYPE_RANDOM,
	"Hunter",	// AVP_RESPAWNTYPE_HUNTER,
};

#endif //#ifdef ASURA_TOOLS

// C L A S S   I M P L E M E N T A T I O N ///////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Settings::Initialise
// Author       : Andy Tate
// Date         : 25-Oct-2006
////////////////////////////////////////////////////////////////////////////////

void AVP_Settings::Initialise (void)
{
	// AJK
	// This form of profile initialisation is temporary for now
	s_pxCurrentProfile	= new AVP_Profile;
	
#ifdef ASURA_SUPPORT_COMMAND_CONSOLE
	if (!Asura_CommandConsole::VarExists(L"AVP.Player.Team"))
	{
		Asura_CommandConsole::AddVar(L"AVP.Player.Team", &s_iRequestedMultiplayerTeam, 0, AVP_Settings::AVP_NUM_TEAMS-1, Asura_CommandConsole::REMOVE_AT_SHUTDOWN);
	}
#endif //#ifdef ASURA_SUPPORT_COMMAND_CONSOLE
}

/// End of function 'AVP_Settings::Initialise'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Settings::Shutdown
// Author       : Andy Tate
// Date         : 25-Oct-2006
////////////////////////////////////////////////////////////////////////////////

void AVP_Settings::Shutdown (void)
{
	s_pxCurrentProfile->Shutdown();
	delete(s_pxCurrentProfile);
	s_pxCurrentProfile	= NULL;
}

/// End of function 'AVP_Settings::Shutdown'. ///


void AVP_Settings::ApplyProfileSettings()
{
	s_pxCurrentProfile->ApplySettings();
}


void AVP_Settings::SetLevelName( const char* szLevelName )
{
#ifdef ASURA_TOOLS
	s_bLevelNameSet = true;
#endif
	Asura_PrintfToBfr(s_acLevelName, "%s", uAVP_MAX_LEVELNAME_LEN, true, szLevelName);
}

#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
void AVP_Settings::SetAddressToConnectTo(const char* szAddress)
{
	Asura_PrintfToBfr(s_acAddressToConnectTo, "%s", uAVP_MAX_ADDRESS_LEN, true, szAddress);
}

void AVP_Settings::SetAddressToConnectTo(const Asura_NetAddress& xAddress, u_int uPort)
{

	const char* szString = Asura_NetTransport_System::GetStringFromAddress(xAddress, static_cast<u_short>(uPort));
	Asura_PrintfToBfr(s_acAddressToConnectTo, "%s", uAVP_MAX_ADDRESS_LEN, true, szString);

}


void AVP_NetworkSession::Set()
{
	m_uSize = sizeof(*this);

	Asura_PrintfToBfr( m_acLevelName, "%s", uAVP_MAX_LEVELNAME_LEN, true, AVP_Settings::GetLevelName() );
	SetGameType( AVP_Settings::GetGameType() ); 

	SetNumberOfTeams( AVP_Multiplayer_GameRules::GetNumberOfTeams() ); 
	SetMaxNumberOfPlayers( AVP_Multiplayer_GameRules::GetMaxNumberOfPlayers() ); 
	SetTeamOneSpecies( AVP_Multiplayer_GameRules::GetTeamOneSpecies() ); 
	SetTeamTwoSpecies( AVP_Multiplayer_GameRules::GetTeamTwoSpecies() ); 
	SetTeamThreeSpecies( AVP_Multiplayer_GameRules::GetTeamThreeSpecies() ); 
	SetMutuallyExclusiveTeams( AVP_Multiplayer_GameRules::GetMutuallyExclusiveTeams() ); 
	SetAllowMixedTeams( AVP_Multiplayer_GameRules::GetAllowMixedTeams() ); 
	SetRespawnUponDeath( AVP_Multiplayer_GameRules::GetRespawnUponDeath() ); 
	SetRespawnType( AVP_Multiplayer_GameRules::GetRespawnType() );
	SetLivesAvailablePerTeam( AVP_Multiplayer_GameRules::GetLivesAvailablePerTeam() ); 
	SetSpeciesRatioAlien( AVP_Multiplayer_GameRules::GetPlayerRatioAlien() ); 
	SetSpeciesRatioHuman( AVP_Multiplayer_GameRules::GetPlayerRatioHuman() ); 
	SetSpeciesRatioPredator( AVP_Multiplayer_GameRules::GetPlayerRatioPredator() ); 
	SetFriendlyFireOn( AVP_Multiplayer_GameRules::GetFriendlyFireOn() ); 
	SetScoreLimit( AVP_Multiplayer_GameRules::GetPlayerScoreLimit() ); 
	SetScoreLimit( AVP_Multiplayer_GameRules::GetTeamScoreLimit() ); 
	SetTimeLimit( AVP_Multiplayer_GameRules::GetTimeLimit() ); 
}

void AVP_NetworkSession::CopyToSettings() const
{
	Asura_Assert(m_uSize == sizeof(*this), "invalid network session");
	AVP_Settings::SetLevelName( m_acLevelName );
	AVP_Settings::SetGameType( GetGameType() );

	// After receiving a new game type, make sure we are playing by the dame default rules than the server
	// (before overriding some values with the host's settings)
	AVP_Multiplayer_GameRules::Refresh(); 

	AVP_Multiplayer_GameRules::SetNumberOfTeams( GetNumberOfTeams() ); 
	AVP_Multiplayer_GameRules::SetMaxNumberOfPlayers( GetMaxNumberOfPlayers() ); 
	AVP_Multiplayer_GameRules::SetTeamOneSpecies( GetTeamOneSpecies() ); 
	AVP_Multiplayer_GameRules::SetTeamTwoSpecies( GetTeamTwoSpecies() ); 
	AVP_Multiplayer_GameRules::SetTeamThreeSpecies( GetTeamThreeSpecies() ); 
	AVP_Multiplayer_GameRules::SetMutuallyExclusiveTeams( GetMutuallyExclusiveTeams() ); 
	AVP_Multiplayer_GameRules::SetAllowMixedTeams( GetAllowMixedTeams() ); 
	AVP_Multiplayer_GameRules::SetRespawnUponDeath( GetRespawnUponDeath() ); 
	AVP_Multiplayer_GameRules::SetRespawnType( GetRespawnType() );
	AVP_Multiplayer_GameRules::SetLivesAvailablePerTeam( GetLivesAvailablePerTeam() ); 
	AVP_Multiplayer_GameRules::SetPlayerRatioAlien( GetSpeciesRatioAlien() ); 
	AVP_Multiplayer_GameRules::SetPlayerRatioHuman( GetSpeciesRatioHuman() ); 
	AVP_Multiplayer_GameRules::SetPlayerRatioPredator( GetSpeciesRatioPredator() ); 
	AVP_Multiplayer_GameRules::SetFriendlyFireOn( GetFriendlyFireOn() ); 
	AVP_Multiplayer_GameRules::SetPlayerScoreLimit( GetScoreLimit() ); 
	AVP_Multiplayer_GameRules::SetTeamScoreLimit( GetScoreLimit() ); 
	AVP_Multiplayer_GameRules::SetTimeLimit( GetTimeLimit() ); 
}

bool AVP_NetworkSession::IsValid() const
{
	return m_uSize == sizeof(AVP_NetworkSession);
}

const char*	AVP_NetworkSession::GetLevelName() const
{
	if (IsValid())
	{
		return m_acLevelName;
	}
	return "invalid";
}

#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK

void AVP_Settings::SetMaxNetPlayers( u_int uNum )
{ 
	Asura_Assert(uNum >= uAVP_MAX_NET_PLAYERS_MIN && uNum <= uAVP_MAX_NET_PLAYERS_MAX, "invalid max players value");
	s_uMaxNetPlayers = uNum;
}

void AVP_Settings::RefreshBlueprintData(const char* szFilename)
{
#ifndef ASURA_TOOLS
	// Only want to keep these up-to-date in a tools environment, save a little processing in retail builds
	if(s_bGotStaticBlueprintValues)
	{
		return;
	}
	s_bGotStaticBlueprintValues = true;
#endif

#if 0
	//////////////////////////////////
	// Level specific Blueprints
	//////////////////////////////////
	{
		Asura_Blueprint* pxBlueprint = NULL;
		Asura_Hash_ID uTypeHash = Asura_GetHashID("Levels");

		Asura_String xFileNameString(szFilename);
		Asura_String xFileNameOutput;

		xFileNameString.SplitFilename(NULL, &xFileNameOutput, NULL);

		Asura_Hash_ID uBlueprintHash = Asura_GetHashID(xFileNameOutput.GetString());
		bool bGotBlueprint = Asura_Blueprint_System::GetBlueprint(uTypeHash, uBlueprintHash, pxBlueprint);

		if(bGotBlueprint && pxBlueprint)
		{
			Asura_Value xValue;

			// The level specific data should only be set if it is not being overridden...
			if(AVP_Settings::GetPlayerSpecies() == AVP_Settings::AVP_SPECIES_LEVEL_DEFAULT)
			{
				if(pxBlueprint->GetParameterValueByHashID(Asura_GetHashID("Character Type"), xValue))
				{
					AVP_Settings::SetPlayerSpecies(static_cast<AVP_Settings::Species>(xValue.GetIntValue()));
				}
			}
			
		}
	}
#endif
}


////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Settings::SetPlayerSpecies
// Author       : Andy Tate
// Date         : 28-Jan-2008
////////////////////////////////////////////////////////////////////////////////

void AVP_Settings::SetPlayerSpecies(const Species eType)
{
	Asura_Assert( eType >= AVP_SPECIES_UNKNOWN && eType < AVP_NUM_SPECIES, "Invalid species set for local player" ); 

	s_ePlayerSpecies	= eType;
}

/// End of function 'AVP_Settings::SetPlayerSpecies'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Settings::SetPlayerDifficulty
// Author       : Callum Hope
// Date         : 2-Sep-2008
////////////////////////////////////////////////////////////////////////////////

void AVP_Settings::SetPlayerDifficulty( const Difficulty eType )
{
	Asura_Assert( eType >= 0 && eType < AVP_NUM_DIFFICULTIES, "Invalid difficulty set for local player" ); 

	s_ePlayerDifficulty	= eType;
}

/// End of function 'AVP_Settings::SetPlayerDifficulty'. ///

////////////////////////////////////////////////////////////////////////////////
//  CLASS    :  AVP_Settings
//  NAME     :  SetRequestedMultiplayerTeam()
//  CREATED  :  JG (22.8.2008)
//  DESC     :  Request to join a multiplayer team
////////////////////////////////////////////////////////////////////////////////
void AVP_Settings::SetRequestedMultiplayerTeam(const Team eTeam)
{
	Asura_Assert( eTeam >= AVP_TEAM_NONE && eTeam < AVP_NUM_TEAMS, "Invalid multiplayer team requested" ); 
	
	s_iRequestedMultiplayerTeam = eTeam; 
}

////////////////////////////////////////////////////////////////////////////////
//  NAME     :  GetSpeciesByClassification()
//  CREATED  :  JG (1.8.2008)
//  DESC     :  Transform the classification enum into one of the species
////////////////////////////////////////////////////////////////////////////////
AVP_Settings::Species AVP_Settings::GetSpeciesByClassification(const AVP_ENTITY_CLASSIFICATION eClassification)
{
	switch( eClassification )
	{
		case AVP_ENTITYCLASS_ALIEN:
		case AVP_ENTITYCLASS_ALIENFACEHUGGER:
		case AVP_ENTITYCLASS_ALIENCHESTBURSTER:
		case AVP_ENTITYCLASS_ALIENQUEEN:
		{
			return AVP_SPECIES_ALIEN; 
		}
		case AVP_ENTITYCLASS_PREDATOR:
		{
			return AVP_SPECIES_PREDATOR; 
		}

		case AVP_ENTITYCLASS_PREDALIEN: // predalien will be "alien" internally
			return AVP_SPECIES_ALIEN;

		case AVP_ENTITYCLASS_HUMAN:
		case AVP_ENTITYCLASS_MARINE:
		case AVP_ENTITYCLASS_ANDROID:
		case AVP_ENTITYCLASS_CIVILIAN:      // AJK, 4/11/08 added AVP_ENTITYCLASS_CIVILIAN
		case AVP_ENTITYCLASS_SENTRYGUN:		// CJW, 20/02/09 added AVP_ENTITYCLASS_SENTRYGUN so smartgun wont target them
		{
			return AVP_SPECIES_HUMAN; 
		}


		default:
		{
			return AVP_SPECIES_UNKNOWN;
		}
	}
}


////////////////////////////////////////////////////////////////////////////////
//  CLASS    :  AVP_Settings
//  NAME     :  IsMultiPlayer()
//  CREATED  :  JG (24.4.2009)
//  DESC     :  Playing or about to play a multiplayer game, including multiplayer
//				menus, Lobby, etc.
////////////////////////////////////////////////////////////////////////////////
#if defined(AVP_ALLOW_MULTIPLAYER)
bool AVP_Settings::IsMultiPlayer()
{
	// Hopefully this should cover all possible ways of getting into the game
	// Navigating multiplayer menus will initialise the Lobby system, and shut it down
	// accordingly before returning to the FrontEnd / Dev FrontEnd
	// Hosting / joining games without using the Lobby will be covered by the external network state
	return ( GetExternalNetworkActive() || Asura_Lobby_System::IsInitialised() );
}
#endif // defined(AVP_ALLOW_MULTIPLAYER)

// end of file
