/**
 * Message library
 */

#Const Version		"2013-05-06"
#Const ScriptName	"Message.Script.txt"

// ---------------------------------- //
// Functions
// ---------------------------------- //

// ---------------------------------- //
// Private
// ---------------------------------- //

// ---------------------------------- //
/** Send a big message to one player
 *
 *	@param	_UI				The UI who'll display the message
 *	@param	_Level			The level of the message - 1: Big, 2: Status
 *	@param	_Player			The id of the player who'll receive the message
 *	@param	_Message		The message to display
 *	@param	_Duration		The message to duration
 *	@param	_Sound			The sound to play with the message
 *	@param	_SoundVariant	The sound variant to play
 */
Void Private_DisplayMessage(
	CUIConfig _UI, 
	Integer _Level,
	CSmPlayer _Player, 
	Text _Message, 
	Integer _Duration, 
	CUIConfig::EUISound _Sound, 
	Integer _SoundVariant
) {
	if (_Level == 1) {
		_UI.BigMessageSound = CUIConfig::EUISound::Silence;
		_UI.BigMessageSoundVariant = 0;
		_UI.BigMessage = _Message;
	} else if (_Level == 2) _UI.StatusMessage = _Message;
	
	if (_Sound != CUIConfig::EUISound::Silence) {
		_UI.SendNotice(
			"", 
			CUIConfig::ENoticeLevel::PlayerInfo, 
			Null, CUIConfig::EAvatarVariant::Default, 
			_Sound, _SoundVariant
		);
	}
	
	declare LibMessage_MessageEndTime for _Player = [1 => -1, 2 => -1];
	declare LibMessage_MessageActive for _Player = False;
	LibMessage_MessageEndTime[_Level] = Now + _Duration;
	LibMessage_MessageActive = True;
}

// ---------------------------------- //
/** Send a big message to one player
 *
 *	@param	_Level			The level of the message - 1: Big, 2: Status
 *	@param	_Player			The id of the player who'll receive the message
 *	@param	_Message		The message to display
 *	@param	_Duration		The message to duration
 *	@param	_Priority		The message priority
 *	@param	_Sound			The sound to play with the message
 *	@param	_SoundVariant	The sound variant to play
 */
Void Private_SendMessageTo(
	Integer _Level, 
	CSmPlayer _Player, 
	Text _Message, 
	Integer _Duration, 
	Integer _Priority,
	CUIConfig::EUISound _Sound,
	Integer _SoundVariant
) {	
	// Send message to all players (Players + Spectators)
	if (_Player == Null) {	
		declare AllPlayers = CSmPlayer[];
		foreach (Player in Players) { AllPlayers.add(Player); }
		foreach (Spectator in Spectators) { AllPlayers.add(Spectator); }
		
		foreach (Player in AllPlayers) {
			/* Priority of the current message, 
			 * a lower priority message can't overwrite it. 
			 * It must be a positive value.
			 */
			declare Integer[Integer] LibMessage_Priority for Player;
			if (!LibMessage_Priority.existskey(_Level)) LibMessage_Priority[_Level] = 0;
			if (_Priority >= LibMessage_Priority[_Level]) {
				LibMessage_Priority[_Level] = _Priority;
				
				declare UI <=> UIManager.GetUI(Player);
				
				if (UI != Null) {				
					Private_DisplayMessage(UI, _Level, Player, _Message, _Duration, _Sound, _SoundVariant);
				}
			}
		}
	} 
	// Send message to one player
	else {
		/* Priority of the current message, 
		 * a lower priority message can't overwrite it. 
		 * It must be a positive value.
		 */
		declare Integer[Integer] LibMessage_Priority for _Player;
		if (!LibMessage_Priority.existskey(_Level)) LibMessage_Priority[_Level] = 0;
		if (_Priority >= LibMessage_Priority[_Level]) {
			LibMessage_Priority[_Level] = _Priority;
			declare CUIConfig UI;
			UI <=> UIManager.GetUI(_Player);
			
			if (UI != Null) {			
				Private_DisplayMessage(UI, _Level, _Player, _Message, _Duration, _Sound, _SoundVariant);
			}
		}
	}
}

// ---------------------------------- //
/// Clean all messages
Void Private_CleanMessages(Integer _Level) {
	declare AllPlayers = CSmPlayer[];
	foreach (Player in Players) { AllPlayers.add(Player); }
	foreach (Spectator in Spectators) { AllPlayers.add(Spectator); }
	
	foreach (Player in AllPlayers) {
		declare UI <=> UIManager.GetUI(Player);
		if (UI != Null) {
			if (_Level != 2) UI.BigMessage = "";
			if (_Level != 1) UI.StatusMessage = "";
		}
		declare LibMessage_MessageActive for Player = False;
		declare LibMessage_MessageEndTime for Player = [1 => -1, 2 => -1];
		declare LibMessage_Priority for Player = [1 => 0, 2 => 0];
		if (_Level != 2) {
			LibMessage_MessageEndTime[1] = -1;
			LibMessage_Priority[1] = 0;
		}
		if (_Level != 1) {
			LibMessage_MessageEndTime[2] = -1;
			LibMessage_Priority[2] = 0;
		}
		if (LibMessage_MessageEndTime[1] <= 0 && LibMessage_MessageEndTime[2] <= 0) {
			LibMessage_MessageActive = False;
		}
	}
}

// ---------------------------------- //
// Public
// ---------------------------------- //

// ---------------------------------- //
/** Return the version number of the script
 *
 *	@return		The version number of the script
 */
Text GetScriptVersion() {
	return Version;
}

// ---------------------------------- //
/** Return the name of the script
 *
 *	@return		The name of the script
 */
Text GetScriptName() {
	return ScriptName;
}

// ---------------------------------- //
/** Send a big message to all players
 *
 *	@param	_Message	The message to display
 *	@param	_Duration	The message to duration
 *	@param	_Priority		The message priority
 */
Void SendBigMessage(Text _Message, Integer _Duration, Integer _Priority) {
	Private_SendMessageTo(1, Null, _Message, _Duration, _Priority, CUIConfig::EUISound::Silence, 0);
}

// ---------------------------------- //
/** Send a big message to one player
 *
 *	@param	_Player		The player who'll receive the message
 *	@param	_Message	The message to display
 *	@param	_Duration	The message to duration
 *	@param	_Priority		The message priority
 */
Void SendBigMessage(CSmPlayer _Player, Text _Message, Integer _Duration, Integer _Priority) {
	Private_SendMessageTo(1, _Player, _Message, _Duration, _Priority, CUIConfig::EUISound::Silence, 0);
}

// ---------------------------------- //
/** Send a big message with sound to all players
 *
 *	@param	_Message		The message to display
 *	@param	_Duration		The message to duration
 *	@param	_Priority		The message priority
 *	@param	_Sound			The sound to play with the message
 *	@param	_SoundVariant	The sound variant to play
 */
Void SendBigMessage(Text _Message, Integer _Duration, Integer _Priority, CUIConfig::EUISound _Sound, Integer _SoundVariant) {
	Private_SendMessageTo(1, Null, _Message, _Duration, _Priority, _Sound, _SoundVariant);
}

// ---------------------------------- //
/** Send a big message with sound to one player
 *
 *	@param	_Player			The player who'll receive the message
 *	@param	_Message		The message to display
 *	@param	_Duration		The message to duration
 *	@param	_Priority		The message priority
 *	@param	_Sound			The sound to play with the message
 *	@param	_SoundVariant	The sound variant to play
 */
Void SendBigMessage(CSmPlayer _Player, Text _Message, Integer _Duration, Integer _Priority, CUIConfig::EUISound _Sound, Integer _SoundVariant) {
	Private_SendMessageTo(1, _Player, _Message, _Duration, _Priority, _Sound, _SoundVariant);
}

// ---------------------------------- //
/** Send a status message to all players
 *
 *	@param	_Message	The message to display
 *	@param	_Duration	The message to duration
 *	@param	_Priority		The message priority
 */
Void SendStatusMessage(Text _Message, Integer _Duration, Integer _Priority) {
	Private_SendMessageTo(2, Null, _Message, _Duration, _Priority, CUIConfig::EUISound::Silence, 0);
}

// ---------------------------------- //
/** Send a status message to one player
 *
 *	@param	_Player		The player who'll receive the message
 *	@param	_Message	The message to display
 *	@param	_Duration	The message to duration
 *	@param	_Priority		The message priority
 */
Void SendStatusMessage(CSmPlayer _Player, Text _Message, Integer _Duration, Integer _Priority) {
	Private_SendMessageTo(2, _Player, _Message, _Duration, _Priority, CUIConfig::EUISound::Silence, 0);
}

// ---------------------------------- //
/** Send a status message with sound to all players
 *
 *	@param	_Message		The message to display
 *	@param	_Duration		The message to duration
 *	@param	_Priority		The message priority
 *	@param	_Sound			The sound to play with the message
 *	@param	_SoundVariant	The sound variant to play
 */
Void SendStatusMessage(Text _Message, Integer _Duration, Integer _Priority, CUIConfig::EUISound _Sound, Integer _SoundVariant) {
	Private_SendMessageTo(2, Null, _Message, _Duration, _Priority, _Sound, _SoundVariant);
}

// ---------------------------------- //
/** Send a status message with sound to one player
 *
 *	@param	_Player			The player who'll receive the message
 *	@param	_Message		The message to display
 *	@param	_Duration		The message to duration
 *	@param	_Priority		The message priority
 *	@param	_Sound			The sound to play with the message
 *	@param	_SoundVariant	The sound variant to play
 */
Void SendStatusMessage(CSmPlayer _Player, Text _Message, Integer _Duration, Integer _Priority, CUIConfig::EUISound _Sound, Integer _SoundVariant) {
	Private_SendMessageTo(2, _Player, _Message, _Duration, _Priority, _Sound, _SoundVariant);
}

// ---------------------------------- //
/// Clean all big messages
Void CleanBigMessages() {
	Private_CleanMessages(1);
}

// ---------------------------------- //
/// Clean all big messages
Void CleanStatusMessages() {
	Private_CleanMessages(2);
}

// ---------------------------------- //
/// Clean all messages
Void CleanAllMessages() {
	Private_CleanMessages(0);
}

// ---------------------------------- //
/// Main loop
Void Loop() {
	foreach (Player in AllPlayers) {
		if (Player.IsFakePlayer) continue;
		
		declare LibMessage_MessageActive for Player = False;
		
		if (LibMessage_MessageActive) {
			declare LibMessage_MessageEndTime for Player = [1 => -1, 2 => -1];
			for (I, 1, 2) {
				if (Now >= LibMessage_MessageEndTime[I]) {
					declare Integer[Integer] LibMessage_Priority for Player;
					
					LibMessage_Priority[I] = 0;
					LibMessage_MessageEndTime[I] = -1;
				
					declare UI <=> UIManager.GetUI(Player);
					if (UI != Null) {
						if (I == 1) UI.BigMessage = "";
						else if (I == 2) UI.StatusMessage = "";
					}
					
					if (LibMessage_MessageEndTime[1] <= 0 && LibMessage_MessageEndTime[2] <= 0) {
						LibMessage_MessageActive = False;
					}
				}
			}
		}
	}
}