import("ScarUtil.scar")

--? @shortdesc If only one team is alive, players on that team win.  Returns true if one team left.
--? @args String win_condition
--? @result Boolean
function WC_CheckOneTeamLeft( win_condition )
	local count = World_GetPlayerCount();

	local team_first = -1;
	local player_alive;

	for i = 1, count
	do
		local player = World_GetPlayerAt(i);

		if( Player_IsAlive(player) ) then
			if( team_first == -1 ) then
				player_alive = player;
				team_first = Player_GetTeam( player );
			else
				local team = Player_GetTeam( player );
				if( team ~= team_first ) then
					return false;
				end
			end
		end
	end

	World_SetTeamWin( player_alive, win_condition);
	World_SetGameOver();

	return true;
end


function WC_RemoveUnusedObjects()

	-- if this flag exists this means that VP game conditions have been loaded and this function should be skipped
	if (g_VPConditionsLoaded == nil or g_VPConditionsLoaded == false) then
		
		-- get all the VP points
		local count = World_GetNumEntities()
		
		print(count)
		
		for i=0,(count-1) do
			local entityid = World_GetEntity( i )
			
			if (Entity_IsVictoryPoint(entityid)==true) then
				Entity_Destroy( entityid )
			end
		end
	end
	
	TimeRule_RemoveMe()
end


_Annihilate = 
{
}
-- the Allied stuff
_Annihilate[0] = 
{
	EBP.ALLIED_HQ,
	EBP.ALLIED_HQ_2,
	EBP.ALLIED_HQ_3,
	EBP.ALLIED_HQ_4,
	EBP.ALLIED_HQ_5,
	EBP.ALLIED_HQ_6,
	EBP.ALLIED_BARRACKS,
	EBP.ALLIED_ARMOURY,
	EBP.ALLIED_MOTORPOOL,
	EBP.ALLIED_MOTORPOOL2,
	EBP.ALLIED_QUARTERMASTER,
	EBP.ALLIED_TRIAGE,
	EBP.ALLIED_MGPOST,
}
-- the Axis stuff
_Annihilate[1] = 
{
	EBP.AXIS_HQ,
	EBP.AXIS_HQ_2,
	EBP.AXIS_HQ_3,
	EBP.AXIS_HQ_4,
	EBP.AXIS_HQ_5,
	EBP.AXIS_HQ_6,
	EBP.AXIS_BASIC,
	EBP.AXIS_PLATOON,
	EBP.AXIS_COMPANY,
	EBP.AXIS_BATTALION,
	EBP.AXIS_KAMPFKRAFT,
	EBP.AXIS_BUNKER,
	World_GetPropertyBagGroupID("ebps/races/axis/buildings/axis_bunker_starting_position.lua"),
}

function WC_CheckEndGame()
	-- if this flag is set then we care about annihilate
	if (g_CheckAnnihilate ~= nil and g_CheckAnnihilate == true) then
	
		-- initialize team data
		local _anniTeamStatus = {}
		
		-- foreach player, count the number of remaining buildings that we're interested in
		local player_count = World_GetPlayerCount();
		for i = 1, player_count do
			local player = World_GetPlayerAt(i);
			local team = Player_GetTeam( player );
			local race = Player_GetRace(player)
			
			--is the player alive
			if Player_IsAlive(player) then
				
				-- go through all the entities that the player owns and keep the ones we care about
				local interestingBuildings = 0

				local _FilterEntities = function(gid, idx, eid)
					local eidBP = Entity_GetBlueprintID(eid)

					local keep = false

					-- is this an upgraded ambient building
					if Entity_HasUpgrade(eid, UPG.CONVERT_AMBIENT_BUILDING) then
						-- we only care if that building is in supply
						if World_IsInSupply( player, Entity_GetPosition(eid) ) then
							-- yup, count that one
							keep = true
						end
					else
						-- we only care for a few types of 'buildings'
						for k,v in pairs(_Annihilate[race]) do
							if v == eidBP then
								keep = true;
								break
							end
						end
					end
					
					-- keep it?
					if keep then
						-- print("player "..i.." of race "..race.." has a " .. Entity_GetBlueprintName(eid))
						interestingBuildings = interestingBuildings + 1
					end
				end
				
				EGroup_ForEach(Player_GetEntities(player), _FilterEntities)

				-- check if the player still has some buildings that we care about
				if interestingBuildings > 0 then
					-- print("player "..i.." of race "..race.." has " .. interestingBuildings .. " buildings")
					_anniTeamStatus[ team ] = true
				else
					-- print("player "..i.." of race "..race.." has NO buildings")
					--leave the table empty
				end
			end
		end

		-- kill players from teams that have been annihilated
		for i = 1, player_count do
			local player = World_GetPlayerAt(i);
			if Player_IsAlive( player ) then
				local team = Player_GetTeam( player )
				if not _anniTeamStatus[ team ] then
					print("WC_CheckEndGame: Annihilate: killing a player from team: " .. team )
					Player_Kill( player );				
				end
			end
		end		
		
	end

	-- always check if only one team left 
	Util_CheckOneTeamLeft("annihilate");
end

function WC_InitGameCheck()

	-- sign up for death events from all players
	local player_count = World_GetPlayerCount();

	for i = 1,player_count
	do
		local player = World_GetPlayerAt(i);
		EventRule_AddPlayerEvent(WC_OnPlayerKilled, player, GE_PlayerKilled)
	end
	
	-- check to see if the MP map has added an override
	if (WinConditionOverride) then
		WinConditionOverride()
	end

	-- also add a periodic check
	TimeRule_AddInterval(WC_CheckEndGame, 1, 0)
end

function WC_OnPlayerKilled()
	print("WC_OnPlayerKilled")
	WC_CheckEndGame()
end

Scar_AddInit(WC_RemoveUnusedObjects);
Scar_AddInit(WC_InitGameCheck);
