--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--
-- DEPRECATED FUNCTIONS
-- use these and the big, bad wolf will get you.
--
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------



--------------------------------------------------------------------------------
-- Deprecated on 30th May 2005
--------------------------------------------------------------------------------

function Prox_AllSquadsNearMarker(groupid, markerid)
	
	return _Prox_Private.GroupNearPoint(
				groupid,
				Marker_GetPosition( markerid ),
				Marker_GetProximityRadius( markerid ),
				true,
				SGroupCaller
			)
end

function Prox_AnySquadNearMarker(groupid, markerid)
	
	return _Prox_Private.GroupNearPoint(
				groupid,
				Marker_GetPosition( markerid ),
				Marker_GetProximityRadius( markerid ),
				false,
				SGroupCaller
			)
end

function Prox_AllEntitiesNearMarker(groupid, markerid)
	
	return _Prox_Private.GroupNearPoint(
				groupid,
				Marker_GetPosition( markerid ),
				Marker_GetProximityRadius( markerid ),
				true,
				EGroupCaller
			)
end

function Prox_AnyEntityNearMarker(groupid, markerid)
	
	return _Prox_Private.GroupNearPoint(
				groupid,
				Marker_GetPosition( markerid ),
				Marker_GetProximityRadius( markerid ),
				false,
				EGroupCaller
			)
end




--------------------------------------------------------------------------------
-- Deprecated on 10th June 2005
--------------------------------------------------------------------------------


function Util_CreateEntitiesAtPosition(playerid, egroupid, blueprint, pos, numentities)

	for i = 1, numentities do
		local entityid = nil
		if playerid == nil then
			entityid = Entity_CreateENV(blueprint, pos)								-- create the entity as a world object
		else
			entityid = Entity_Create(blueprint, playerid, pos)						-- create the entity as a player unit
			Entity_Spawn(entityid)													-- spawn it
		end
		EGroup_Add(egroupid, entityid)												-- add to group
		--Entity_SetPosition(entityid, World_GetSpawnablePosition(pos, entityid))		-- find a spawnable position for it

	end

	return egroupid

end


--~ function Util_CreateSquadsAtPosition(...)

--~ 	-- grab the arguments
--~ 	local playerid = arg[1]
--~ 	local sgroupid = arg[2]
--~ 	local blueprint = arg[3]
--~ 	local pos = arg[4]
--~ 	local numsquads = arg[5]
--~ 	local loadout = 0
--~ 	if (table.getn(arg) == 6) then
--~ 		loadout = arg[6]
--~ 	end
--~ 	
--~ 	for i = 1, numsquads do
--~ 		local sbpid = Util_GetSquadBlueprintID( blueprint )
--~ 		local squadid = Squad_Create( sbpid, playerid, pos, loadout )	-- create the squad
--~ 		SGroup_Add(sgroupid, squadid)										-- add to group
--~ 		--local spawnpos = World_GetSpawnableSquadPosition(pos, squadid)		-- find a spawnable position for it
--~ 		local spawnok = Squad_Spawn( squadid,  pos )						-- spawn it
--~ 		if ( spawnok == false ) then
--~ 			fatal( "Failed to spawn after creating squad" )
--~ 		end
--~ 		
--~ 	end

--~ 	return sgroupid

--~ end


function Util_CreateSquadsAtMarkerEx(playerId, squadgroupName, squadBlueprint, markerName, numsquads, loadout)
	return Util_CreateSquadsAtPositionEx(
		playerId,
		squadgroupName,
		squadBlueprint,
		Marker_GetPosition( Marker_FromName( markerName, "basic_marker" ) ),
		numsquads,
		loadout -- use min loadout
	)
end


function Util_ModifySightRadiusForPlayer(playerid, factor)

	local race = Player_GetRace(playerid)

	-- apply modifier to each entity
	for n = 1, World_GetPossibleBuildingsCount(race) do
		
		local ebp = World_GetPossibleBuildingsName(race, n-1)
		local modifier = Modifier_Create(MAT_EntityType, "modifiers\\sight_radius_modifier.lua", MUT_Multiplication, false, factor, ebp)
		Modifier_ApplyToPlayer(modifier, playerid)
		
	end

end


function Util_ModifySightRadiusForSGroup(sgroupid, factor)

	local modifier = Modifier_Create(MAT_Squad, "modifiers\\sight_radius_modifier.lua", MUT_Multiplication, false, factor, "")
	local _ModifyMe = function(gid, idx, sid)
		Modifier_ApplyToSquad(modifier, sid)
	end
	
	SGroup_ForEach(sgroupid, _ModifyMe)

end


function Util_ModifySightRadiusForEGroup(egroupid, factor)

	local modifier = Modifier_Create(MAT_Entity, "modifiers\\sight_radius_modifier.lua", MUT_Multiplication, false, factor, "")
	local _ModifyMe = function(gid, idx, eid)
		Modifier_ApplyToEntity(modifier, eid)
	end
	
	EGroup_ForEach(egroupid, _ModifyMe)

end


function Util_ModifyWeaponRanges(sgroupid, hardpoint, factor)

	local modifier = Modifier_Create(MAT_Weapon, "modifiers\\range_weapon_modifier.lua", MUT_Multiplication, false, factor, hardpoint)
	local _ModifyMe = function(gid, idx, sid)
		Modifier_ApplyToSquad(modifier, sid)
	end
	
	SGroup_ForEach(sgroupid, _ModifyMe)

end


function Util_ModifyWeaponAccuracy(group, hardpoint, factor)

	-- create the appropriate modifier
	modifier = Modifier_Create(MAT_Weapon, "modifiers\\accuracy_weapon_modifier.lua", MUT_Multiplication, true, factor, hardpoint)
	
	-- apply this to each squad in the group
	local _ApplyModifier = function (gid, idx, sid)
		Modifier_ApplyToSquad(modifier, sid)
	end
	SGroup_ForEach(group, _ApplyModifier)
	
end


function Util_ModifyWeaponCooldown(group, hardpoint, factor)

	-- create the appropriate modifier
	modifier = Modifier_Create(MAT_Weapon, "modifiers\\cooldown_weapon_modifier.lua", MUT_Multiplication, true, factor, hardpoint)
	
	-- apply this to each squad in the group
	local _ApplyModifier = function (gid, idx, sid)
		Modifier_ApplyToSquad(modifier, sid)
	end
	SGroup_ForEach(group, _ApplyModifier)
	
end


function Util_ModifyWeaponBurst(group, hardpoint, factor)

	-- create the appropriate modifier
	modifier = Modifier_Create(MAT_Weapon, "modifiers\\burst_weapon_modifier.lua", MUT_Multiplication, true, factor, hardpoint)
	
	-- apply this to each squad in the group
	local _ApplyModifier = function (gid, idx, sid)
		Modifier_ApplyToSquad(modifier, sid)
	end
	SGroup_ForEach(group, _ApplyModifier)
	
end


function Util_ModifyWeaponDamage(group, hardpoint, factor)

	-- create the appropriate modifier
	modifier = Modifier_Create(MAT_Weapon, "modifiers\\damage_weapon_modifier.lua", MUT_Multiplication, true, factor, hardpoint)
	
	-- apply this to each squad in the group
	local _ApplyModifier = function (gid, idx, sid)
		Modifier_ApplyToSquad(modifier, sid)
	end
	SGroup_ForEach(group, _ApplyModifier)
	
end


function Util_ModifyReceivedDamage(group, factor)

	-- create the appropriate modifier
	modifier = Modifier_Create(MAT_Entity, "modifiers\\received_damage_modifier.lua", MUT_Multiplication, true, factor, "")
	
	-- apply this to each squad in the group
	local _ApplyModifier = function (gid, idx, sid)
		Modifier_ApplyToSquad(modifier, sid)
	end
	SGroup_ForEach(group, _ApplyModifier)
	
end



----------------------------------------------------------------------------------------------------------------
-- Modifier tables -- Store your custom modifiers here

SquadModifiers = {}

EntityModifiers = {}

PlayerModifiers = {}


----------------------------------------------------------------------------------------------------------------
-- Private Implementation

_ModifiersPrivate =
{

	__skipsave = true,

	-- returns the applierIndex from an ApplierTable, returns zero if not found
	GetApplierIndex = function( ApplierTable, Modifier, gameid )
		for i=1, table.getn( ApplierTable ) do
			--print ( "check index "..i, Modifier, ApplierTable[i][3], itemid, ApplierTable[i][1] );
			if( ( ApplierTable[i][1] == gameid ) and ApplierTable[i][3] == Modifier ) then
				return i
			end
		end
		
		-- not found
		return 0
	end,
	
	-- unapply a modifier and remove it from an applier table
	RemoveModifier = function( ApplierTable, applierIndex )
		-- remove the modifier
		Modifier_Remove( ApplierTable[ applierIndex ][ 2 ] )
		
		-- remove from the applier table
		table.remove( ApplierTable, applierIndex )
	end,
	
	ApplyToGroup = function( groupid, groupcaller, ApplierTable, ApplierIndexFunc, Modifier, apply )
	
		local ApplyModifier = function( groupid, itemindex, itemid )
		
			if( apply == true ) then
				--
				-- apply if it is not already applied
				if( ApplierIndexFunc( Modifier, itemid ) == 0 ) then
					local applierid = groupcaller.ApplyModifier( itemid, Modifier )
					
					-- store entry ( so we can remove modifier later )
					local entry = { groupcaller.GetGameID( itemid ), applierid, Modifier }
					table.insert( ApplierTable, entry )
					
					-- DEBUG
					--print( "Added modifier applier at index: "..ApplierIndexFunc( Modifier, itemid ) )
				else
					print( "Modifier cannot be re-applied.  You must remove it first." )
				end
				
			else
				--
				-- remove if applier exists
				local applierIdx = ApplierIndexFunc( Modifier, itemid )
				if( applierIdx ~= 0 ) then
					_ModifiersPrivate.RemoveModifier( ApplierTable, applierIdx )
					--print( "Removed modifier from index: "..applierIdx );
				else
					print( "Modifier cannot be removed because it has not been applied" )
				end
			
			end
		
		end
	
		groupcaller.ForEach( groupid, ApplyModifier )
	end,

	-- Applier tables
	EntityAppliers = {},
	SquadAppliers = {},
	PlayerAppliers = {},
	--WeaponAppliers = {}, --TODO
}


----------------------------------------------------------------------------------------------------------------
-- Public Implementation


function ModifierUtil_GetSquadApplierIndex( Modifier, squadid )
	local result = _ModifiersPrivate.GetApplierIndex( _ModifiersPrivate.SquadAppliers, Modifier, Squad_GetGameID( squadid ) )
	return result
end


function ModifierUtil_GetEntityApplierIndex( Modifier, entityid )
	local result = _ModifiersPrivate.GetApplierIndex( _ModifiersPrivate.EntityAppliers, Modifier, Entity_GetGameID( entityid ) )
	return result
end


function ModifierUtil_GetPlayerApplierIndex( Modifier, playerid )
	local result = _ModifiersPrivate.GetApplierIndex( _ModifiersPrivate.PlayerAppliers, Modifier, Player_GetID( playerID ) )
	return result
end


function ModifierUtil_IsSquadModifierApplied( Modifier, squadid )
	return ( ModifierUtil_GetSquadApplierIndex( Modifier, squadid ) ~= 0 )
end

function ModifierUtil_IsEntityModifierApplied( Modifier, entityid )
	return ( ModifierUtil_GetEntityApplierIndex( Modifier, entityid ) ~= 0 )
end

function ModifierUtil_IsPlayerModifierApplied( Modifier, playerid )
	return ( ModifierUtil_GetPlayerApplierIndex( Modifier, playerid ) ~= 0 )
end






function ModifierUtil_ApplyToSGroup( groupid, Modifier, apply )
	
	--if( apply == true ) then print( "applying to sgroup" ) else print( "removing from sgroup") end
	
	--ApplyToGroup = function( groupid, groupcaller, ApplierTable, ApplierIndexFunc, Modifier, apply )
	_ModifiersPrivate.ApplyToGroup(
		groupid,
		SGroupCaller,
		_ModifiersPrivate.SquadAppliers,
		ModifierUtil_GetSquadApplierIndex,
		Modifier,
		apply
	)
	
end


function ModifierUtil_ApplyToEGroup( groupid, Modifier, apply )
	
	_ModifiersPrivate.ApplyToGroup(
		groupid,
		EGroupCaller,
		_ModifiersPrivate.EntityAppliers,
		ModifierUtil_GetEntityApplierIndex,
		Modifier,
		apply
	)
	
end







--------------------------------------------------------------------------------
-- Deprecated on 19th July 2005
--------------------------------------------------------------------------------


function Modify_SGroupSightRadius(sgroupid, factor)

	local modifier = Modifier_Create(MAT_Squad, "modifiers\\sight_radius_modifier.lua", MUT_Multiplication, false, factor, "")
	local result = {}
	
	local _ModifyMe = function(gid, idx, sid)
		table.insert(result, Modifier_ApplyToSquad(modifier, sid))
	end
	
	SGroup_ForEach(sgroupid, _ModifyMe)

	return result
	
end


function Modify_EGroupSightRadius(egroupid, factor)

	local modifier = Modifier_Create(MAT_Entity, "modifiers\\sight_radius_modifier.lua", MUT_Multiplication, false, factor, "")
	local result = {}
	
	local _ModifyMe = function(gid, idx, eid)
		table.insert(result, Modifier_ApplyToEntity(modifier, eid))
	end
	
	EGroup_ForEach(egroupid, _ModifyMe)

	return result
	
end




--------------------------------------------------------------------------------
-- Function renamed on 12th August 2005
--------------------------------------------------------------------------------

function Prox_IsPlayerNearMarker(playerid, pos, all, range)
	return Prox_ArePlayersNearMarker(playerid, pos, all, range)
end




--------------------------------------------------------------------------------
-- Function deprecated on 9th September 2005
--------------------------------------------------------------------------------

function SGroup_InstantSetup(sgroupid)

	local _OneSquad = function (gid, idx, sid)
		Squad_InstantSetupTeamWeapon(sid)
	end
	
	SGroup_ForEachEx( sgroupid, _OneSquad, true, true )
	
end






--------------------------------------------------------------------------------
-- Function deprecated on 30th January 2006
--------------------------------------------------------------------------------
 
-- Some keywords for use with these functions
PATH_LOOPED = 0
PATH_NORMAL = 1
PATH_FROMBEGINNING = 0
PATH_FROMCLOSEST = 1

function Path_CreatePath(pathname, pathmarkers, pathloop)
	
	local numberofpaths = table.getn(TableOfPaths)

	-- check the current table for a path of that name, and remove it if present
	if (numberofpaths > 0) then
		for n = numberofpaths, 1, -1 do
			if (TableOfPaths[n].name == pathname) then
				table.remove(TableOfPaths, n)
			end
		end
	end

	-- add the new path to the table
	table.insert(TableOfPaths, {name = pathname, markers = pathmarkers, loop = pathloop})
	
end



function Path_AddSquadsToPath(sgroupid, pathname, startpoint)
	
	local numberofpaths = table.getn(TableOfPaths)
	local thispath = 0
	local waypoint = 0
	
	-- find path in table
	for n = 1, numberofpaths do
		if (TableOfPaths[n].name == pathname) then
			thispath = n
		end
	end
	
	-- work out which point on the path they're going to be starting with
	if (startpoint == PATH_FROMBEGINNING) then
		waypoint = TableOfPaths[thispath].markers[1]
	elseif (startpoint == PATH_FROMCLOSEST) then
		local dest = {}
		-- calculate the distance to each waypoint on the path
		for i = 1, table.getn(TableOfPaths[thispath].markers) do
			local d = Prox_MarkerSGroup(TableOfPaths[thispath].markers[i], sgroupid, PROX_CENTER)
			dest[i] = {waypointindex = i, distance = d}
		end
		-- sort the list of destinations by distance
		table.sort(dest, function(a,b) return (a.distance < b.distance) end)
		waypoint = TableOfPaths[thispath].markers[dest[1].waypointindex]
	end

	-- issue the move order to the group
	Cmd_MoveToMarker(sgroupid, waypoint)
	
	-- build up the sgroup name for people on this stretch of the path
	local ordergroupname = "sg_PATH-"..pathname.."-"..Marker_GetName(waypoint)

	-- find the group's ID, creating the group if necessary
	local ordergroupid = SGroup_CreateIfNotFound(ordergroupname)

	-- add the people to this group
	SGroup_AddGroup(ordergroupid, sgroupid)
	
	if not (Rule_Exists(Rule_PathManager)) then
		Rule_AddInterval(Rule_PathManager, 2)
	end
	
end



function Path_GetNumberOfSquadsOnPath(pathname)
	
	local numberofpaths = table.getn(TableOfPaths)
	local total = 0
	
	-- find path in table
	for n = 1, numberofpaths do
		
		if (TableOfPaths[n].name == pathname) then
			
			-- loop through each section, and tally up the counts for each one
			for wp = 1, table.getn(TableOfPaths[n].markers) do
				local section = "sg_PATH-"..TableOfPaths[n].name.."-"..TableOfPaths[n].markers[wp]
				if SGroup_Exists(section) then
					local gID = SGroup_FromName(section)
					total = total + SGroup_Count(gID)
				end
			end
			
		end
		
	end
	
	return total
	
end




-- The manager function
function Rule_PathManager()
	
	local numberofpaths = table.getn(TableOfPaths)
	local numberofmarkers = 0
	
	for path = 1, numberofpaths do
		
		for wp = 1, table.getn(TableOfPaths[path].markers) do
			
			local pathname = TableOfPaths[path].name
			local waypoint = TableOfPaths[path].markers[wp]
			
			-- build up the sgroup name for people on this stretch of the path
			local ordergroupname = "sg_PATH-"..pathname.."-"..Marker_GetName(waypoint)
			
			-- check to see if anyone is on this path section
			if (SGroup_Exists(ordergroupname)) then
				
				-- iteration function to monitor a squad on a path
				local Path_CheckWaypoint = function(gID, idx, sID)
					
					if (Squad_Count(sID) >= 1) then
						
						-- check if they're at their destination waypoint
						if Marker_InProximity(waypoint, Squad_GetPosition(sID)) then
							local nextwaypoint = 0
							-- remove this squad from the path section group
							SGroup_Remove(gID, sID)
							-- find out what their next section is
							if (wp < table.getn(TableOfPaths[path].markers)) then
								nextwaypoint = TableOfPaths[path].markers[wp+1]
							else
								-- end of the path, loop if path says so
								if (TableOfPaths[path].loop == PATH_LOOPED) then
									nextwaypoint = TableOfPaths[path].markers[1]
								end
							end
							if (nextwaypoint ~= 0) then
								local nextordergroupname = "sg_PATH-"..pathname.."-"..Marker_GetName(nextwaypoint)
								local nextordergroupid = 0
								-- send them to the next waypoint
								if (SGroup_Exists(nextordergroupname)) then
									nextordergroupid = SGroup_FromName(nextordergroupname)
								else
									nextordergroupid = SGroup_Create(nextordergroupname)
								end
								pathquickgroup = SGroup_CreateIfNotFound("pathquickgroup")
								SGroup_Single(pathquickgroup, sID)
								Cmd_MoveToMarker(pathquickgroup, nextwaypoint)
								SGroup_Add(nextordergroupid, sID)
							end
						else
							-- check if the squad is idle
							if (Squad_GetActiveCommand(sID) == SQUADSTATEID_Idle) then
								-- reissue move order
								pathquickgroup = SGroup_CreateIfNotFound("pathquickgroup")
								SGroup_Single(pathquickgroup, sID)
								Cmd_MoveToMarker(pathquickgroup, waypoint)
							end
						end
					end
				end
				
				local ordergroupid = SGroup_FromName(ordergroupname)
				SGroup_ForEachEx(ordergroupid, Path_CheckWaypoint, true, false)
				
			end
			
		end
		
	end
	
end


-- Path Manager initialisation function
function Path_Init()

	TableOfPaths = {}
	
end
Scar_AddInit(Path_Init)



function MarchTerritoryForwards(playerid, list, regularebp, finalebp)
	
	if (regularebp == nil) then regularebp = "ebps/gameplay/territory_marker_25.lua" end
	if (finalebp == nil) then finalebp = "ebps/gameplay/territory_marker_25.lua" end
	
	table.insert(_MarchTable, {player = playerid, markers = list, regular = regularebp, final = finalebp})

	if (Rule_Exists(MarchTerritoryForwards_Manager) == false) then
		Rule_AddInterval(MarchTerritoryForwards_Manager, 0.3)
	end
	
end


function MarchTerritoryForwards_Manager()

	for n = table.getn(_MarchTable), 1, -1 do
		
		if (table.getn(_MarchTable[n].markers) >= 2) then
			
			Util_CreateEntitiesAtMarker(_MarchTable[n].player, nil, _MarchTable[n].regular, _MarchTable[n].markers[1], 1)
			table.remove(_MarchTable[n].markers, 1)
			
		else
			
			Util_CreateEntitiesAtMarker(_MarchTable[n].player, nil, _MarchTable[n].final, _MarchTable[n].markers[1], 1)
			table.remove(_MarchTable, n)
			
		end
		
	end
	
	if (table.getn(_MarchTable) == 0) then
		Rule_RemoveMe()
	end
	
end




--------------------------------------------------------------------------------
-- Function deprecated on 31st January 2006
--------------------------------------------------------------------------------
 

function Player_GetAllSquadsWithinTerritorySector(playerid, sgroupid, sectorid)
	
	SGroup_Clear(sgroupid)						-- clear the group beforehand
	
	_Player_Private.GetAllWithinTerritorySector( 			-- get all squads in the territory sector
		playerid,
		sgroupid,
		sectorid
	)
end


function Player_GetAllSquadsNearPos(playerid, sgroupid, pos, distance)

	SGroup_Clear(sgroupid)						-- clear the group beforehand
	
	_Player_Private.GetAllNearPoint( 			-- get all squads in proximity of a point
		playerid, 
		sgroupid, 
		pos, 
		distance
	)
end


function Player_GetAllEntitiesWithinTerritorySector(playerid, egroupid, sectorid)
	
	EGroup_Clear(egroupid)						-- clear the group beforehand
	
	_Player_Private.GetAllWithinTerritorySector( 			-- get all entities in the territory sector
		playerid,
		egroupid,
		sectorid
	)
end


function Player_GetAllEntitiesNearPos(playerid, egroupid, pos, distance)
	
	EGroup_Clear(egroupid)						-- clear the group beforehand

	_Player_Private.GetAllNearPoint( 			-- get all entities in proximity of a point
		playerid, 
		egroupid,
		pos, 
		distance
	)
end




function Modify_EntityTargetPriority(group, addition)

	-- create the appropriate modifier
	local modifier = Modifier_Create(MAT_Entity, "modifiers\\target_priority_modifier.lua", MUT_Addition, false, addition, "")
	local result = {}
	
	-- apply this to each squad in the group
	local _ApplyModifier = function (gid, idx, sid)
		local modid = Modifier_ApplyToEntity(modifier, sid)
		table.insert(result, modid)
		Modifier_AddToEntityTable(sid, modid)
	end
	EGroup_ForEachEx(group, _ApplyModifier, true, true)
	
	return result
	
end

-- deprecated April 13th 2006

function Util_GetDifficulty()
	return Game_GetSPDifficulty()
end

function Util_SetDifficulty_Health(player, dif)
	print("**** [Util_SetDifficulty_Health] OBSOLETE FUNCTION! Use Setup_Difficulty instead ****")
end

function Player_SetAvailability(player, item, availability)

	if (scartype(item) == ST_STRING) then
		item = World_GetPropertyBagGroupID(item)
	end
	
	Player_SetItemAvailability(player, item, availability)
	
end



