/**
 *	UI Lib
 */
#Const	Version		"2016-06-07"
#Const	ScriptName	"Libs/Nadeo/UI.Script.txt"

#Include "TextLib" as TL
#Include "Libs/Nadeo/XmlRpc2.Script.txt" as XmlRpc

// ---------------------------------- //
// Constants
// ---------------------------------- //
///XmlRpc
#Const C_Callback_Properties	"Shootmania.UIProperties"
#Const C_Method_GetProperties	"Shootmania.GetUIProperties"
#Const C_Method_SetProperties	"Shootmania.SetUIProperties"

// ---------------------------------- //
// Functions
// ---------------------------------- //
// ---------------------------------- //
// Private
// ---------------------------------- //
// ---------------------------------- //
/** Convert a Boolean to a Text
 *
 *	@param	_Boolean	The Boolean to convert
 *
 *	@return				The Text
 */
Text Private_BooleanToText(Boolean _Boolean) {
	if (_Boolean) return "true";
	return "false";
}

// ---------------------------------- //
/** Convert a Vec2 to a Text
 *
 *	@param	_Vec2		The Vec2 to convert
 *
 *	@return				The Text
 */
Text Private_Vec2ToText(Vec2 _Vec2) {
	return _Vec2.X^" "^_Vec2.Y;
}

// ---------------------------------- //
/** Convert a Vec3 to a Text
 *
 *	@param	_Vec3		The Vec3 to convert
 *
 *	@return				The Text
 */
Text Private_Vec3ToText(Vec3 _Vec3) {
	return _Vec3.X^" "^_Vec3.Y^" "^_Vec3.Z;
}

// ---------------------------------- //
// 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;
}

// ---------------------------------- //
/** Set the number of lines of the chat
 *
 *	@param	_LineCount		The number of lines of the chat
 */
Void SetChatLineCount(Integer _LineCount) {
	if (_LineCount >= 0 && _LineCount <= 40) UIManager.UIAll.OverlayChatLineCount = _LineCount;
	else if (_LineCount < 0) UIManager.UIAll.OverlayChatLineCount = 0;
	else if (_LineCount > 40) UIManager.UIAll.OverlayChatLineCount = 40;
}

// ---------------------------------- //
/** Get the number of lines of the chat
 *
 *	@return			The number of lines of the chat
 */
Integer GetChatLineCount() {
	return UIManager.UIAll.OverlayChatLineCount;
}

// ---------------------------------- //
/** Set the visibility of the UI overlays
 *
 *	@param	_Name			The name of the overlay
 *	@param	_Visible		The visibility of the overlay
 */
Void Private_SetVisibility(Text _Name, Text _Visible) {
	if (_Visible == "") return;
	
	declare Hide = False;
	if (_Visible == "False" || _Visible == "false" || _Visible == "0") Hide = True;
	
	switch (_Name) {
		case "notices"						: UIManager.UIAll.OverlayHideNotices = Hide;
		case "map_info" 					: UIManager.UIAll.OverlayHideMapInfo = Hide;
		case "chat"								: UIManager.UIAll.OverlayHideChat = Hide;
		case "countdown"					: UIManager.UIAll.OverlayHideCountdown = Hide;
		case "crosshair"					: UIManager.UIAll.OverlayHideCrosshair = Hide;
		case "gauges"							: UIManager.UIAll.OverlayHideGauges = Hide;
		case "consumables"				: UIManager.UIAll.OverlayHideConsumables = Hide;
		case "go"									: UIManager.UIAll.OverlayHide321Go = Hide;
		case "chat_avatar"				: UIManager.UIAll.OverlayChatHideAvatar = Hide;
		case "endmap_ladder_recap": UIManager.UIAll.OverlayHideEndMapLadderRecap = Hide;
	}
}

// ---------------------------------- //
/** Set the visibility of the UI overlays
 *
 *	@param	_Name			The name of the overlay
 *	@param	_Position		The position of the overlay
 */
Void Private_SetPosition(Text _Name, Text _Position) {
	if (_Position == "") return;
	
	declare Vec3 Position;
	declare PositionSplit = TL::Split(" ", _Position);
	if (PositionSplit.existskey(0)) Position.X = TL::ToReal(PositionSplit[0]);
	if (PositionSplit.existskey(1)) Position.Y = TL::ToReal(PositionSplit[1]);
	if (PositionSplit.existskey(2)) Position.Z = TL::ToReal(PositionSplit[2]);
	
	switch (_Name) {
		case "chat"			: UIManager.UIAll.OverlayChatOffset = <Position.X, Position.Y>;
		case "countdown": UIManager.UIAll.CountdownCoord = <Position.X, Position.Y>;
	}
}

// ---------------------------------- //
/** Parse the properties xml
 *
 *	@param	_Xml	The xml to parse
 */
Void Private_SetProperties(Text _Xml) {
	if (_Xml == "") return;
	declare XmlDoc <=> Xml.Create(_Xml);
	if (XmlDoc == Null || XmlDoc.Root.Name != "ui_properties") {
		Xml.Destroy(XmlDoc);
		return;
	}
	
	foreach (Node in XmlDoc.Root.Children) {
		Private_SetVisibility(Node.Name, Node.GetAttributeText("visible", ""));
		Private_SetPosition(Node.Name, Node.GetAttributeText("pos", ""));
		if (Node.Name == "chat") {
			SetChatLineCount(Node.GetAttributeInteger("linecount", -1));
			Private_SetPosition(Node.Name, Node.GetAttributeText("offset", ""));
		}
	}
	
	Xml.Destroy(XmlDoc);
	
	declare LibUI_PropertiesBackUp for This = "";
	LibUI_PropertiesBackUp = _Xml;
}

// ---------------------------------- //
/** Get the current properties xml
 *
 *	@return		The properties xml
 */
Text Private_GetProperties() {
	return """
<ui_properties>
	<notices visible="{{{Private_BooleanToText(!UIManager.UIAll.OverlayHideNotices)}}}" />
	<map_info visible="{{{Private_BooleanToText(!UIManager.UIAll.OverlayHideMapInfo)}}}" />
	<chat visible="{{{Private_BooleanToText(!UIManager.UIAll.OverlayHideChat)}}}" offset="{{{Private_Vec2ToText(UIManager.UIAll.OverlayChatOffset)}}}" linecount="{{{GetChatLineCount()}}}" />
	<countdown visible="{{{Private_BooleanToText(!UIManager.UIAll.OverlayHideCountdown)}}}" pos="{{{Private_Vec2ToText(UIManager.UIAll.CountdownCoord)}}}" />
	<crosshair visible="{{{Private_BooleanToText(!UIManager.UIAll.OverlayHideCrosshair)}}}" />
	<gauges visible="{{{Private_BooleanToText(!UIManager.UIAll.OverlayHideGauges)}}}" />
	<consumables visible="{{{Private_BooleanToText(!UIManager.UIAll.OverlayHideConsumables)}}}" />
	<go visible="{{{Private_BooleanToText(!UIManager.UIAll.OverlayHide321Go)}}}" />
	<chat_avatar visible="{{{Private_BooleanToText(!UIManager.UIAll.OverlayChatHideAvatar)}}}" />
	<endmap_ladder_recap visible="{{{Private_BooleanToText(!UIManager.UIAll.OverlayHideEndMapLadderRecap)}}}" />
</ui_properties>""";
}

// ---------------------------------- //
/** Send ui properties
 *
 *	@param	_ResponseId								Id to insert in the response callback
 */
Void XmlRpc_SendUIProperties(Text _ResponseId) {
	declare Json = """{
	"responseid": {{{dump(_ResponseId)}}}
}""";
	declare PropsXml = Private_GetProperties();

	XmlRpc::SendCallback(C_Callback_Properties, [Json, PropsXml]);
}

// ---------------------------------- //
/// Update the library
Void Yield() {
	foreach (Event in XmlRpc.PendingEvents) {
		if (Event.Type == CXmlRpcEvent::EType::CallbackArray) {
			switch (Event.ParamArray1) {
				case C_Method_SetProperties: {
					if (Event.ParamArray2.count > 0) {
						Private_SetProperties(Event.ParamArray2[0]);
					}
				}
				case C_Method_GetProperties: {
					declare ResponseId = "";
					if (Event.ParamArray2.existskey(0)) ResponseId = Event.ParamArray2[0];
					XmlRpc_SendUIProperties(ResponseId);
				}
			}
		}
	}
}

// ---------------------------------- //
/// Unload the library
Void Unload() {
	XmlRpc::UnregisterCallback(C_Callback_Properties);
	XmlRpc::UnregisterMethod(C_Method_SetProperties);
	XmlRpc::UnregisterMethod(C_Method_GetProperties);
}

// ---------------------------------- //
/// Load the library
Void Load() {
	Unload();
	
	// Try to load the latest properties
	declare LibUI_PropertiesBackUp for This = "";
	Private_SetProperties(LibUI_PropertiesBackUp);
	
	// Register callbacks
	XmlRpc::RegisterCallback(C_Callback_Properties, """
* Name: {{{C_Callback_Properties}}}
* Type: CallbackArray
* Description: Information about the default UI components of Maniaplanet (map info, chat, ladder recap, ...).
* Data:
	- Version >=2.0.0: 
	```
	[
		"{
			"responseid": "xyz", //< Facultative id passed by a script event
		}",
		"
		<!--
		  Each node is optional and can be omitted.
		  If it's the case then the previous value will be kept.
		-->
		<ui_properties>
		  <!-- Notifications displayed on the left of the screen -->
		  <notices visible="true" />
		  <!-- The map name and author displayed on the top right of the screen when viewing the scores table -->
		  <map_info visible="true" />
		  <!--
		    The server chat displayed on the bottom right of the screen
		    The offset values range from 0. to -3.2 for x and from 0. to 1.8 for y
		    The linecount property must be between 0 and 40
		  -->
		  <chat visible="true" offset="0. 0." linecount="5" />
		  <!-- Countdown displayed on the top of the screen -->
		  <countdown visible="true" pos="0. 85." />
		  <!-- Crosshair displayed on the center of the screen -->
		  <crosshair visible="true" />
		  <!-- Gauges displayed on the bottom of the screen -->
		  <gauges visible="true" />
		  <!-- Consumables displayed on the bottom of the screen -->
		  <consumables visible="true" />
		  <!-- 3, 2, 1, Go! message displayed on the middle of the screen when spawning -->
		  <go visible="true" />
		  <!-- The avatar of the last player speaking in the chat displayed above the chat -->
		  <chat_avatar visible="true" />
		  <!-- Ladder progression box displayed on the top of the screen at the end of the map -->
		  <endmap_ladder_recap visible="true" />
		</ui_properties>
		"
	]
	```
	""");
	
	// Register methods
	XmlRpc::RegisterMethod(C_Method_GetProperties, """
* Name: {{{C_Method_GetProperties}}}
* Type: TriggerModeScriptEventArray
* Description: Request the current ui properties. This method will trigger the "{{{C_Callback_Properties}}}" callback.
* Data:
	- Version >=2.0.0:
	```
	[
		"responseid" //< Facultative id that will be passed to the "{{{C_Callback_Properties}}}" callback.
	]
	```
	""");
	XmlRpc::RegisterMethod(C_Method_SetProperties, """
* Name: {{{C_Method_SetProperties}}}
* Type: TriggerModeScriptEventArray
* Description: Update the ui properties.
* Data:
	- Version >=2.0.0:
	```
	[
		"
		<!--
		  Each node is optional and can be omitted.
		  If it's the case then the previous value will be kept.
		-->
		<ui_properties>
		  <!-- Notifications displayed on the left of the screen -->
		  <notices visible="true" />
		  <!-- The map name and author displayed on the top right of the screen when viewing the scores table -->
		  <map_info visible="true" />
		  <!--
		    The server chat displayed on the bottom right of the screen
		    The offset values range from 0. to -3.2 for x and from 0. to 1.8 for y
		    The linecount property must be between 0 and 40
		  -->
		  <chat visible="true" offset="0. 0." linecount="5" />
		  <!-- Countdown displayed on the top of the screen -->
		  <countdown visible="true" pos="0. 85." />
		  <!-- Crosshair displayed on the center of the screen -->
		  <crosshair visible="true" />
		  <!-- Gauges displayed on the bottom of the screen -->
		  <gauges visible="true" />
		  <!-- Consumables displayed on the bottom of the screen -->
		  <consumables visible="true" />
		  <!-- 3, 2, 1, Go! message displayed on the middle of the screen when spawning -->
		  <go visible="true" />
		  <!-- The avatar of the last player speaking in the chat displayed above the chat -->
		  <chat_avatar visible="true" />
		  <!-- Ladder progression box displayed on the top of the screen at the end of the map -->
		  <endmap_ladder_recap visible="true" />
		</ui_properties>
		"
	]
	```
	""");
}