/**
 *	MapType for Siege
 *
 *	Only one SpawnAttack. 
 *	Only one Goal. 
 *	Between 1 and 9 SpawnDefense. 
 *	Each SpawnDefense has a unique order number. 
 *	The last SpawnDefense is linked to the Goal. 
 *	The other SpawnDefense are linked to at least one Gate.
 */

#RequireContext CSmMapType
#Const Version			"2014-03-19"
#Const MapTypeVersion	3
#Const ScriptName		"SiegeArena.Script.txt"

#Include "TextLib" as TL
#Include "Libs/Nadeo/Anchor.Script.txt" as Anchor
#Include "Libs/Nadeo/MapType.Script.txt" as MapType

// ---------------------------------- //
// Constants
// ---------------------------------- //
#Const C_MaxSpawnDef 9

// ---------------------------------- //
// Functions
// ---------------------------------- //
// ---------------------------------- //
// Normalize the anchors
Void NormalizeAnchors() {
	Anchor::Count();
	
	declare Ident SiegeArena_AnchorId for ManialinkPage;
	
	declare NeedRenormalize = True;
	while (NeedRenormalize) {
		NeedRenormalize = False;
		
		foreach (Anchor in AnchorData) {
			if (Anchor.DefaultTag == "Spawn") {
				if (Anchor.Tag != "SpawnAttack" && Anchor.Tag != "SpawnDefense") {
					Anchor::Count();
					NeedRenormalize = True;
					if (Anchor::GetCount("SpawnAttack") > 0) Anchor.Tag = "SpawnDefense";
					else Anchor.Tag = "SpawnAttack";
				}
				
				if (Anchor.Tag == "SpawnAttack" && Anchor.Order != 0) {
					Anchor.Order = 0;
				}
				
				if (Anchor.Tag == "SpawnDefense") {
					if (Anchor.Order < 1 || Anchor.Order > C_MaxSpawnDef) {
						Anchor::Count();
						NeedRenormalize = True;
						Anchor.Order = 1;
						for (I, 1, C_MaxSpawnDef) {
							if (Anchor::GetCount("SpawnDefense", I) <= 0) {
								Anchor.Order = I;
								break;
							}
						}
					}
				}
			} else if (Anchor.DefaultTag == "Gate") {
				Anchor.Tag = Anchor.DefaultTag;
				if (Anchor.Order < 1 || Anchor.Order > C_MaxSpawnDef) {
					Anchor::Count();
					NeedRenormalize = True;
					Anchor.Order = 1;
					for (I, 1, C_MaxSpawnDef) {
						if (Anchor::GetCount(Anchor.Tag, I) <= 0) {
							Anchor.Order = I;
							break;
						}
					}
				}
			} else if (Anchor.DefaultTag == "Goal") {
				Anchor.Tag = Anchor.DefaultTag;
				Anchor.Order = Anchor::GetCount("SpawnDefense");
			} else {
				Anchor.Tag = Anchor.DefaultTag;
				Anchor.Order = Anchor.DefaultOrder;
			}
			
			if (Anchor.Id == SiegeArena_AnchorId) {
				declare Text SiegeArena_AnchorTag for ManialinkPage;
				declare Integer SiegeArena_AnchorOrder for ManialinkPage;
				SiegeArena_AnchorTag = Anchor.Tag;
				SiegeArena_AnchorOrder = Anchor.Order;
			}
		}
	}
}

// ---------------------------------- //
// Check if the map is valid
Void UpdateValidability() {
	Anchor::Count();
	
	// At least one SpawnDefense
	if (!Anchor::HasAtLeastOneAnchor("SpawnDefense", 1, _("You must place at least one SpawnDefense."))) return;
	// Maximum C_MaxSpawnDef SpawnDefense
	if (!Anchor::HasLessThanXAnchor("SpawnDefense", C_MaxSpawnDef + 1, _("There's too many SpawnDefense on the map."))) return;
	// Only one SpawnAttack
	if (!Anchor::HasExactlyOneAnchor("SpawnAttack", 0, _("You must place one SpawnAttack."))) return;
	// Only one Goal
	if (!Anchor::HasExactlyOneAnchor("Goal", Anchor::GetCount("SpawnDefense"), _("You must place one Goal."))) return;
	// Only one SpawnDefense with the same order
	declare SpawnDefenseCount = Anchor::GetCount("SpawnDefense");
	for (I, 1, SpawnDefenseCount) {
		if (!Anchor::HasExactlyOneAnchor("SpawnDefense", I, TL::Compose(_("You must place one SpawnDefense %1."), TL::ToText(I)))) return;
		
		// At least one Gate for each SpawnDefense
		if (I < SpawnDefenseCount) {
			if (!Anchor::HasAtLeastOneAnchor("Gate", I, TL::Compose(_("You must place at least one Gate #%1."), TL::ToText(I)))) return;
		}
		//
		else if (I == SpawnDefenseCount) {
			if (!Anchor::HasNoAnchor("Gate", I, TL::Compose(_("The last SpawnDefense must be linked to the Goal and not a Gate."), TL::ToText(I)))) return;
		}
	}
	// Exactly one SpawnDefense for each Gate order
	foreach (Anchor in AnchorData) {
		if (Anchor.Tag != "Gate") continue;
		if (!Anchor::HasExactlyOneAnchor("SpawnDefense", Anchor.Order, TL::Compose(_("You must place one SpawnDefense %1."), TL::ToText(Anchor.Order)))) return;
	}
	
	ValidationStatus = CMapType::ValidationStatus::Validated;	
}

// ---------------------------------- //
// Return the manialink for anchor edition
Text EditAnchorManialink() {
	return """
<frame>
	<frame posn="120 35" hidden="1" id="Frame_AnchorEdition">
		<quad posn="0 0 2" sizen="74 15" halign="center" valign="bottom" style="Bgs1InRace" substyle="BgTitle3_5"/>
		<label posn="0 5 3" halign="center" valign="bottom" style="TextTitle3" textprefix="$fff" text="{{{_("Edit Anchor")}}}" />
		<quad posn="0 0 -1" sizen="70 28" halign="center" style="Bgs1" substyle="BgWindow2"/>
		<frame posn="0 -6 1">
			<frame>
				<format textcolor="222" textemboss="1" />
				<label posn="0 0" sizen="40 6" halign="center" valign="center2" hidden="1" id="Label_AnchorTag" />
				<label posn="0 -8" sizen="40 5" halign="center" valign="center2" hidden="1" id="Label_AnchorOrder" />
			</frame>
			<frame>
				<frame id="Frame_ListAnchorTag">
					<quad posn="-20 0 1" sizen="6 6" halign="right" valign="center" style="Icons64x64_1" substyle="ManiaLinkPrev" scriptevents="1" id="Button_AnchorTagPrev" />
					<label posn="0 0" sizen="40 6" halign="center" valign="center2" focusareacolor1="2224" focusareacolor2="0005" scriptevents="1" id="List_AnchorTag" />
					<quad posn="20 0 1" sizen="6 6" valign="center" style="Icons64x64_1" substyle="ManiaLinkNext" scriptevents="1" id="Button_AnchorTagNext" />
				</frame>
				<frame posn="0 -8" id="Frame_ListAnchorOrder">
					<quad posn="-20 0 1" sizen="6 6" halign="right" valign="center" style="Icons64x64_1" substyle="ManiaLinkPrev" scriptevents="1" id="Button_AnchorOrderPrev" />
					<label posn="0 0" sizen="40 5" halign="center" valign="center2" focusareacolor1="2224" focusareacolor2="0005" scriptevents="1" id="List_AnchorOrder" />
					<quad posn="20 0 1" sizen="6 6" valign="center" style="Icons64x64_1" substyle="ManiaLinkNext" scriptevents="1" id="Button_AnchorOrderNext" />
				</frame>
			</frame>
		</frame>
		<frame posn="0 -19 1">
			<label posn="0 0" halign="center" style="CardButtonSmallL" text="{{{_("Close")}}}" scriptevents="1" id="Button_Close" />
		</frame>
	</frame>
	<frame posn="120 25" hidden="1" id="Frame_NoAnchorEdition">
		<quad posn="0 0 2" sizen="74 15" halign="center" valign="bottom" style="Bgs1InRace" substyle="BgTitle3_5"/>
		<label posn="0 5 3" halign="center" valign="bottom" style="TextTitle3" textprefix="$fff" text="{{{_("Edit Anchor")}}}" />
		<quad posn="0 0 -1" sizen="70 18" halign="center" style="Bgs1" substyle="BgWindow2"/>
		<frame posn="0 -5 1">
			<format textcolor="222" style="TextCardSmallScores2" />
			<label posn="0 0" sizen="40 6" halign="center" valign="center2" text="{{{_("This anchor is not editable")}}}" />
		</frame>
		<frame posn="0 -9 1">
			<label posn="0 0" halign="center" style="CardButtonSmallL" text="{{{_("Close")}}}" scriptevents="1" id="Button_Close" />
		</frame>

	</frame>
	<frame posn="120 -8" hidden="1" id="Frame_Rules">
		<quad posn="0 0 2" sizen="74 15" halign="center" valign="bottom" style="Bgs1InRace" substyle="BgTitle3_5"/>
		<label posn="0 5 3" halign="center" valign="bottom" style="TextTitle3" textprefix="$fff" text="{{{_("Rules")}}}" />
		<quad posn="0 0 -1" sizen="70 45" halign="center" style="Bgs1" substyle="BgWindow2"/>
		<frame posn="-30 -3">
			<format textcolor="222" style="TextCardSmallScores2" />
			<label posn="0 0" sizen="60 5" text="{{{_("Only one SpawnAttack.")}}}" />
			<label posn="0 -5" sizen="60 5" text="{{{_("Only one Goal.")}}}" />
			<label posn="0 -10" sizen="60 5" text="{{{_("Between 1 and 9 SpawnDefense.")}}}" />
			<label posn="0 -15" sizen="60 5" text="{{{_("Each SpawnDefense has a unique order number.")}}}" autonewline="1" maxline="3" />
			<label posn="0 -25" sizen="60 5" text="{{{_("The last SpawnDefense is linked to the Goal.")}}}" />
			<label posn="0 -30" sizen="60 5" text="{{{_("The other SpawnDefense are linked to at least one Gate.")}}}" autonewline="1" maxline="3" />
		</frame>
	</frame>
</frame>
<script><!--
#Include "TextLib" as TL

Void SetAnchorOrder(Integer _Order) {
	declare List_AnchorOrder <=> (Page.GetFirstChild("List_AnchorOrder") as CMlLabel);
	declare Label_AnchorOrder <=> (Page.GetFirstChild("Label_AnchorOrder") as CMlLabel);
	declare Integer SiegeArena_AnchorOrder for Page;
	
	List_AnchorOrder.Value = TL::ToText(_Order);
	Label_AnchorOrder.Value = TL::ToText(_Order);
	SiegeArena_AnchorOrder = _Order;
}

Void SetAnchorTag(Text _Tag) {
	declare List_AnchorTag <=> (Page.GetFirstChild("List_AnchorTag") as CMlLabel);
	declare Label_AnchorTag <=> (Page.GetFirstChild("Label_AnchorTag") as CMlLabel);
	declare Text SiegeArena_AnchorTag for Page;
	
	List_AnchorTag.Value = _Tag;
	Label_AnchorTag.Value = _Tag;
	SiegeArena_AnchorTag = _Tag;
}

main() {
	declare Frame_AnchorEdition		<=> (Page.GetFirstChild("Frame_AnchorEdition")	as CMlFrame);
	declare Frame_NoAnchorEdition	<=> (Page.GetFirstChild("Frame_NoAnchorEdition")as CMlFrame);
	declare Frame_Rules				<=> (Page.GetFirstChild("Frame_Rules")			as CMlFrame);
	declare Label_AnchorTag			<=> (Page.GetFirstChild("Label_AnchorTag")		as CMlLabel);
	declare Label_AnchorOrder		<=> (Page.GetFirstChild("Label_AnchorOrder")	as CMlLabel);
	declare Frame_ListAnchorTag		<=> (Page.GetFirstChild("Frame_ListAnchorTag")	as CMlLabel);
	declare Frame_ListAnchorOrder	<=> (Page.GetFirstChild("Frame_ListAnchorOrder")as CMlLabel);
	declare List_AnchorTag			<=> (Page.GetFirstChild("List_AnchorTag")		as CMlLabel);
	declare List_AnchorOrder		<=> (Page.GetFirstChild("List_AnchorOrder")		as CMlLabel);
	
	declare Boolean	SiegeArena_RulesShow			for Page;
	declare Boolean	SiegeArena_NoAnchorEditionShow	for Page;
	declare Boolean	SiegeArena_AnchorEditionShow	for Page;
	declare Ident	SiegeArena_AnchorId				for Page;
	declare Text	SiegeArena_AnchorTag			for Page;
	declare Integer	SiegeArena_AnchorOrder			for Page;
	
	declare Boolean PrevRulesShow = False;
	declare Boolean PrevAnchorEditionShow = False;
	declare Boolean PrevNoAnchorEditionShow = False;
	declare Ident PrevAnchorId = NullId;
	declare Text PrevAnchorTag = "";
	declare Integer PrevAnchorOrder = 0;
	
	declare AnchorTag = "";
	declare AnchorOrder = 0;
	
	while (True) {
		yield;
		
		if (PrevAnchorEditionShow != SiegeArena_AnchorEditionShow || PrevNoAnchorEditionShow != SiegeArena_NoAnchorEditionShow) {
			PrevAnchorEditionShow = SiegeArena_AnchorEditionShow;
			PrevNoAnchorEditionShow = SiegeArena_NoAnchorEditionShow;
			
			if (!Frame_AnchorEdition.Visible && SiegeArena_AnchorEditionShow) Frame_AnchorEdition.Visible = True;
			else if (Frame_AnchorEdition.Visible && !SiegeArena_AnchorEditionShow) Frame_AnchorEdition.Visible = False;
			if (!Frame_NoAnchorEdition.Visible && SiegeArena_NoAnchorEditionShow) Frame_NoAnchorEdition.Visible = True;
			else if (Frame_NoAnchorEdition.Visible && !SiegeArena_NoAnchorEditionShow) Frame_NoAnchorEdition.Visible = False;
		}
		
		if (PrevRulesShow != SiegeArena_RulesShow) {
			PrevRulesShow = SiegeArena_RulesShow;
			
			if (!Frame_Rules.Visible && SiegeArena_RulesShow) Frame_Rules.Visible = True;
			else if (Frame_Rules.Visible && !SiegeArena_RulesShow) Frame_Rules.Visible = False;
		}
		
		if (PrevAnchorId != SiegeArena_AnchorId || PrevAnchorTag != SiegeArena_AnchorTag || PrevAnchorOrder != SiegeArena_AnchorOrder) {
			PrevAnchorId = SiegeArena_AnchorId;
			PrevAnchorTag = SiegeArena_AnchorTag;
			PrevAnchorOrder = SiegeArena_AnchorOrder;
			
			List_AnchorTag.Value = SiegeArena_AnchorTag;
			List_AnchorOrder.Value = TL::ToText(SiegeArena_AnchorOrder);
			Label_AnchorTag.Value = SiegeArena_AnchorTag;
			Label_AnchorOrder.Value = TL::ToText(SiegeArena_AnchorOrder);
			
			AnchorTag = SiegeArena_AnchorTag;
			AnchorOrder = SiegeArena_AnchorOrder;
			
			if (AnchorTag == "SpawnDefense" || AnchorTag == "SpawnAttack") {
				if (Label_AnchorTag.Visible) Label_AnchorTag.Visible = False;
				if (!Frame_ListAnchorTag.Visible) Frame_ListAnchorTag.Visible = True;
				
				if (AnchorTag == "SpawnAttack") {
					if (Frame_ListAnchorOrder.Visible) Frame_ListAnchorOrder.Visible = False;
					if (!Label_AnchorOrder.Visible) Label_AnchorOrder.Visible = True;
				} else {
					if (Label_AnchorOrder.Visible) Label_AnchorOrder.Visible = False;
					if (!Frame_ListAnchorOrder.Visible) Frame_ListAnchorOrder.Visible = True;
				}
				
			} else if (AnchorTag == "Goal") {
				if (Frame_ListAnchorTag.Visible) Frame_ListAnchorTag.Visible = False;
				if (!Label_AnchorTag.Visible) Label_AnchorTag.Visible = True;
				if (Frame_ListAnchorOrder.Visible) Frame_ListAnchorOrder.Visible = False;
				if (!Label_AnchorOrder.Visible) Label_AnchorOrder.Visible = True;
			} else {
				if (Frame_ListAnchorTag.Visible) Frame_ListAnchorTag.Visible = False;
				if (!Label_AnchorTag.Visible) Label_AnchorTag.Visible = True;
				if (!Frame_ListAnchorOrder.Visible) Frame_ListAnchorOrder.Visible = True;
				if (Label_AnchorOrder.Visible) Label_AnchorOrder.Visible = False;
			}
		}
		
		foreach (Event in PendingEvents) {
			if (Event.Type == CMlEvent::Type::MouseClick) {
				// Close anchor edit
				if (Event.ControlId == "Button_Close") {
					SiegeArena_AnchorEditionShow = False;
					SiegeArena_NoAnchorEditionShow = False;
					if (Frame_AnchorEdition.Visible) Frame_AnchorEdition.Visible = False;
					if (Frame_NoAnchorEdition.Visible) Frame_NoAnchorEdition.Visible = False;
				}
				// Edit anchor tag
				else if (Event.ControlId == "List_AnchorTag" || Event.ControlId == "Button_AnchorTagNext" || Event.ControlId == "Button_AnchorTagPrev") {
					if (AnchorTag == "SpawnDefense") {
						AnchorTag = "SpawnAttack";
						AnchorOrder = 0;
						SetAnchorOrder(AnchorOrder);
					} else if (AnchorTag == "SpawnAttack") {
						AnchorTag = "SpawnDefense";
					}
					SetAnchorTag(AnchorTag);
				}
				// Edit anchor order
				else if (Event.ControlId == "List_AnchorOrder" || Event.ControlId == "Button_AnchorOrderNext") {
					AnchorOrder += 1;
					if (AnchorOrder > {{{C_MaxSpawnDef}}}) AnchorOrder = 1;
					SetAnchorOrder(AnchorOrder);
				} else if (Event.ControlId == "Button_AnchorOrderPrev") {
					AnchorOrder -= 1;
					if (AnchorOrder < 1) AnchorOrder = {{{C_MaxSpawnDef}}};
					SetAnchorOrder(AnchorOrder);
				}
			}
		}
	}
}
--></script>""";
}

// ---------------------------------- //
// Show the anchor edition manialink
Void EditAnchorData(Ident _EditedAnchorDataId) {	
	if (AnchorData.existskey(_EditedAnchorDataId)) {
		declare Anchor <=> AnchorData[_EditedAnchorDataId];
		
		declare Boolean SiegeArena_AnchorEditionShow for ManialinkPage;
		declare Ident SiegeArena_AnchorId for ManialinkPage;
		declare Text SiegeArena_AnchorTag for ManialinkPage;
		declare Integer SiegeArena_AnchorOrder for ManialinkPage;
		declare Boolean SiegeArena_NoAnchorEditionShow for ManialinkPage;
		
		if (Anchor.DefaultTag == "Spawn" || Anchor.DefaultTag == "Gate" || Anchor.DefaultTag == "Goal") {
			SiegeArena_AnchorTag = Anchor.Tag;
			SiegeArena_AnchorOrder = Anchor.Order;
			SiegeArena_AnchorId = _EditedAnchorDataId;
			SiegeArena_AnchorEditionShow = True;
			SiegeArena_NoAnchorEditionShow = False;
		} else {
			SiegeArena_NoAnchorEditionShow = True;
			SiegeArena_AnchorEditionShow = False;
		}
	}
}

// ---------------------------------- //
// Main
// ---------------------------------- //
main() {	
	MapType::SetVersion(MapTypeVersion);
	CustomEditAnchorData = True;
	NormalizeAnchors();
	
	ManialinkText = EditAnchorManialink();
	declare Boolean SiegeArena_RulesShow for ManialinkPage;
	declare Boolean SiegeArena_AnchorEditionShow for ManialinkPage;
	declare Ident SiegeArena_AnchorId for ManialinkPage;
	declare Text SiegeArena_AnchorTag for ManialinkPage;
	declare Integer SiegeArena_AnchorOrder for ManialinkPage;
	declare Boolean SiegeArena_NoAnchorEditionShow for ManialinkPage;
	SiegeArena_RulesShow = False;
	SiegeArena_AnchorEditionShow = False;
	SiegeArena_AnchorId = NullId;
	SiegeArena_AnchorTag = "";
	SiegeArena_AnchorOrder = 0;
	SiegeArena_NoAnchorEditionShow = False;
	
	declare PrevAnchorTag = "";
	declare PrevAnchorOrder = 0;
	declare PrevPlaceMode = CEditorPlugin::PlaceMode::Unknown;
	
	UpdateValidability();
	
	while (True) {	
		yield;
		
		// Update block property
		if (PrevAnchorTag != SiegeArena_AnchorTag || PrevAnchorOrder != SiegeArena_AnchorOrder) {
			PrevAnchorTag = SiegeArena_AnchorTag;
			PrevAnchorOrder = SiegeArena_AnchorOrder;
			
			if (AnchorData.existskey(SiegeArena_AnchorId)) {
				declare Anchor <=> AnchorData[SiegeArena_AnchorId];
				Anchor.Order = SiegeArena_AnchorOrder;
				Anchor.Tag = SiegeArena_AnchorTag;
			}
			
			NormalizeAnchors();
			UpdateValidability();
		}
		
		// Display the rules when entering block property edition
		if (PrevPlaceMode != PlaceMode) {
			PrevPlaceMode = PlaceMode;
			
			if (PlaceMode == CEditorPlugin::PlaceMode::BlockProperty) {
				SiegeArena_RulesShow = True;
			} else {
				SiegeArena_RulesShow = False;
				SiegeArena_AnchorEditionShow = False;
				SiegeArena_NoAnchorEditionShow = False;
			}
		}
		
		foreach(Event in PendingEvents) {
			if (Event.Type == CPluginEvent::Type::MapModified) {
				NormalizeAnchors();
				UpdateValidability();
			} else if (Event.Type == CPluginEvent::Type::EditAnchor) {
				EditAnchorData(Event.EditedAnchorDataId);
			}
		}		
	}	
}