--[[
	Early Warning Radar Script - 1.5.3 - 07/11/2016
	
	Allows use of units with radars to provide Bearing Range and Altitude information via text display to player aircraft
	
	Features:
		- Uses in-game radar information to detect targets so terrain masking, beaming, low altitude flying, etc is effective for avoiding detection
		- Dynamic. If valid units with radar are created during a mission (eg. via chopper with CTLD), they will be added to the EWRS radar network
		- Can allow / disable BRA messages to fighters or sides
		- Uses player aircraft or mission bullseye for BRA reference, can be changed via F10 radio menu or restricted to one reference in the script settings
		- Can switch between imperial (feet, knots, NM) or metric (meters, km/h, km) measurements using F10 radio menu
		- Ability to change the message display time and automated update interval
		- Can choose to disable automated messages and allow players to request BRA from F10 menu
		- Can allow players to request Bogey Dope at any time through F10 radio menu

	Built and Tested in DCS 1.5 - See https://github.com/Bob7heBuilder/EWRS for the latest version

	This script uses MIST 4.0.57 or later - https://github.com/mrSkortch/MissionScriptingTools
		
	At the moment, because of limitations within DCS to not show messages to individual units, the reference, measurements, and messages
	are done per group. So a group of 4 fighters will each receive 4 BRA messages. Each message however, will have the player's name
	in it, that its refering to. Its unfortunate, but nothing I can do about it.

	Changes:
	- 1.3 - Added Option to allow picture report to be requested thru F10 menu instead of an automated display
			- Fixed bug where a known unit type would sometimes still display as ???
	- 1.4 - Added setting to be able to limit the amount of threats displayed in a picture report
			- Added option to enable Bogey Dopes
				* Mission designer can turn on / off in script settings
				* Pilots can request thru the F10 menu and it will show the BRA to the nearest hostile aircraft that has
				been detected. It will always reference the requesting pilot's own aircraft.
			- Finally implemented a cleaner workaround for some ground units being detected and listed in picture report
	- 1.4.1 - Added some ships to search radar list, you will need to remove the comment markers (--) at the start of the line to activate
	- 1.5 - Added ability to request picture of friendly aircraft positions referencing your own aircraft - Mission designer chooses if this feature is active or not
	- 1.5.1 - Added Gazelle to acCategories
	- 1.5.2 - Added F5E to acCategories
	- 1.5.3 - Fixed bug with maxThreatDisplay set at 0 not displaying any threats
			- Added Mistral Gazelle
			- Added C-101CC
]]

ewrs = {} --DO NOT REMOVE
ewrs.HELO = 1
ewrs.ATTACK = 2
ewrs.FIGHTER = 3

----SCRIPT OPTIONS----

ewrs.messageUpdateInterval = 30 --How often EWRS will update automated BRA messages (seconds)
ewrs.messageDisplayTime = 25 --How long EWRS BRA messages will show for (seconds)
ewrs.restrictToOneReference = false -- Disables the ability to change the BRA calls from pilot's own aircraft or bullseye. If this is true, set ewrs.defaultReference to the option you want to restrict to.
ewrs.defaultReference = "self" --The default reference for BRA calls - can be changed via f10 radio menu if ewrs.restrictToOneReference is false (self or bulls)
ewrs.defaultMeasurements = "imperial" --Default measurement units - can be changed via f10 radio menu (imperial or metric)
ewrs.disableFightersBRA = false -- disables BRA messages to fighters when true
ewrs.enableRedTeam = true -- enables / disables EWRS for the red team
ewrs.enableBlueTeam = true -- enables / disables EWRS for the blue team
ewrs.disableMessageWhenNoThreats = true -- disables message when no threats are detected - Thanks Rivvern - NOTE: If using ewrs.onDemand = true, this has no effect
ewrs.useImprovedDetectionLogic = true --this makes the messages more realistic. If the radar doesn't know the type or distance to the detected threat, it will be reflected in the picture report / BRA message
ewrs.onDemand = false --Setting to true will disable the automated messages to everyone and will add an F10 menu to get picture / BRA message.
ewrs.maxThreatDisplay = 5 -- Max amounts of threats to display on picture report (0 will display all)
ewrs.allowBogeyDope = true -- Allows pilots to request a bogey dope even with the automated messages running. It will display only the cloest threat, and will always reference the players own aircraft.
ewrs.allowFriendlyPicture = true -- Allows pilots to request picture of friendly aircraft
ewrs.maxFriendlyDisplay = 5 -- Limits the amount of friendly aircraft shown on friendly picture

--[[
Units with radar to use as part of the EWRS radar network
If you want to shorten the range of SAM radar detection, use their track radars instead of their search radars
NOTE that track radars require a search radar to detect targets (but the search radars do not need to be included in the list)
I haven't tested detection with ships (that have radar), but should work.
]]
ewrs.validSearchRadars = {
"p-10 s125 sr",			--SA-3 Search Radar
"Kub 1S91 str",			--SA-6 Search and Track Radar
"S-300PS 64H6E sr",		--SA-10 Search Radar
"S-300 PS 40B6MD sr",	--SA-10 Search Radar
"SA-11 Buk SR 9518M1",	--SA-11 Search Radar
"55G6 EWR",				--Early Warning Radar
"1L13 EWR",				--Early Warning Radar
"A-50",					--AWACS
"E-2D",					--AWACS
"E-3A",					--AWACS
"Roland Radar",			--Roland Search Radar
"Hawk sr",				--Hawk SAM Search Radar
"Patriot str",			--Patriot SAM Search and Track Radar

--Ships - I've left these commented out because I don't know which ones have radar
--and which ones don't. Just remove the comment to activate them (the '--' at the start of the line)

--"MOSCOW",				-- CG 1164 Moskva
--"TICONDEROG",			-- CG-60 Normandy
--"PIOTR",				-- CGN 1144.2 Pyotr Velikiy
--"KUZNECOW",			-- CV 1143.5 Admiral Kuzentsov
--"VINSON",				-- CVN-70 Carl Vinson
--"REZKY",				-- FF 1135M Rezky
--"NEUSTRASH",			-- FFG 11540 Neustrashimy
--"PERRY",				-- FFG-7CL Oliver Hazzard Perry
--"ALBATROS",			-- FFL 1124.4 Grisha
--"MOLNIYA",			-- FSG 1241.1MP Molniya
}

--[[
Aircraft Type ENUMs
This is used to restrict BRA messages to fighters
Change the ewrs.TYPE for each aircraft (in ewrs.acCategories) to suit your needs
For now, BRA will be displayed to everyone unless ewrs.disableFightersBRA is true.
When this is true, anything in the list below that == ewrs.FIGHTER will NOT receive BRA messages
]]
ewrs.acCategories = { --Have I left anything out? Please let me know if I have
[ "A-10A"          ] = ewrs.ATTACK  ,
[ "A-10C"          ] = ewrs.ATTACK  ,
[ "Bf-109K-4"      ] = ewrs.ATTACK  ,
[ "C-101EB"        ] = ewrs.ATTACK  ,
[ "C-101CC"		   ] = ewrs.ATTACK  ,
[ "F-15C"          ] = ewrs.FIGHTER ,
[ "F-5E-3"		   ] = ewrs.ATTACK	,
[ "FW-190D9"       ] = ewrs.ATTACK  ,
[ "F-86F Sabre"	   ] = ewrs.FIGHTER ,
[ "Hawk"           ] = ewrs.ATTACK  ,
[ "Ka-50"          ] = ewrs.HELO    ,
[ "L-39C"		   ] = ewrs.ATTACK	,
[ "L-39ZA"         ] = ewrs.ATTACK  ,
[ "Mi-8MT"         ] = ewrs.HELO    ,
[ "MiG-15bis"      ] = ewrs.ATTACK  ,
[ "MiG-21Bis"      ] = ewrs.ATTACK  ,
[ "MiG-29A"		   ] = ewrs.FIGHTER	,
[ "MiG-29S"		   ] = ewrs.FIGHTER	,
[ "M-2000C"		   ] = ewrs.FIGHTER	,
[ "P-51D"          ] = ewrs.ATTACK	,
[ "SA342M"		   ] = ewrs.HELO	,
[ "SA342L"		   ] = ewrs.HELO	,
[ "SA342Mistral"   ] = ewrs.HELO	,
[ "Su-25"          ] = ewrs.ATTACK	,
[ "Su-25T"         ] = ewrs.ATTACK	,
[ "Su-27"          ] = ewrs.FIGHTER	,
[ "Su-33"		   ] = ewrs.FIGHTER ,
[ "TF-51D"         ] = ewrs.ATTACK	,
[ "UH-1H"          ] = ewrs.HELO	,
}

----END OF SCRIPT OPTIONS----


----INTERNAL FUNCTIONS ***** Be Careful changing things below here ***** ----


function ewrs.getDistance(obj1PosX, obj1PosZ, obj2PosX, obj2PosZ)
	local xDiff = obj1PosX - obj2PosX
	local yDiff = obj1PosZ - obj2PosZ
	return math.sqrt(xDiff * xDiff + yDiff * yDiff) -- meters
end

function ewrs.getBearing(obj1PosX, obj1PosZ, obj2PosX, obj2PosZ)
    local bearing = math.atan2(obj2PosZ - obj1PosZ, obj2PosX - obj1PosX)
    if bearing < 0 then
        bearing = bearing + 2 * math.pi
    end
    bearing = bearing * 180 / math.pi
    return bearing    -- degrees
end

function ewrs.getHeading(vec)
    local heading = math.atan2(vec.z,vec.x)
    if heading < 0 then
        heading = heading + 2 * math.pi
    end
    heading = heading * 180 / math.pi
    return heading -- degrees
end

function ewrs.getSpeed(velocity)
	local speed = math.sqrt(velocity.x^2 + velocity.y^2 + velocity.z^2) --m/s
	return speed -- m/s
end

function ewrs.update()
	timer.scheduleFunction(ewrs.update, nil, timer.getTime() + 5)
	ewrs.buildActivePlayers()
	ewrs.buildF10Menu()
end

function ewrs.buildThreatTable(activePlayer, bogeyDope)
	local function sortRanges(v1,v2)
		return v1.range < v2.range
	end

	local targets = {}
	if activePlayer.side == 2 then
		targets = ewrs.currentlyDetectedRedUnits
	else
		targets = ewrs.currentlyDetectedBlueUnits
	end
	
	local bogeyDope = bogeyDope or false
	local referenceX
	local referenceZ
	if ewrs.groupSettings[tostring(activePlayer.groupID)].reference == "self" or bogeyDope then
		local _self = Unit.getByName(activePlayer.unitname)
		local selfpos = _self:getPosition()
		referenceX = selfpos.p.x
		referenceZ = selfpos.p.z
	else
		local bullseye = coalition.getMainRefPoint(activePlayer.side)
		referenceX = bullseye.x
		referenceZ = bullseye.z
	end
	
	local threatTable = {}
	
	for k,v in pairs(targets) do
		local velocity = v["object"]:getVelocity()
		local bogeypos = v["object"]:getPosition()
		local bogeyType = nil
		if ewrs.useImprovedDetectionLogic then
			if v["type"] then
				bogeyType = v["object"]:getTypeName()
			else
				bogeyType = "  ???  "
			end
		else
			bogeyType = v["object"]:getTypeName()
		end

		local bearing = ewrs.getBearing(referenceX,referenceZ,bogeypos.p.x,bogeypos.p.z)
		local heading = ewrs.getHeading(velocity)
		local range = ewrs.getDistance(referenceX,referenceZ,bogeypos.p.x,bogeypos.p.z) -- meters
		local altitude = bogeypos.p.y --meters
		local speed = ewrs.getSpeed(velocity) --m/s

		if ewrs.groupSettings[tostring(activePlayer.groupID)].measurements == "metric" then
			range = range / 1000 --change to KM
			speed = mist.utils.mpsToKmph(speed)
			--altitude already in meters
		else
			range = mist.utils.metersToNM(range)
			speed = mist.utils.mpsToKnots(speed)
			altitude = mist.utils.metersToFeet(altitude)
		end

		if ewrs.useImprovedDetectionLogic then
			if not v["distance"] then
				range = ewrs.notAvailable
			end
		end
		
		local j = #threatTable + 1
		threatTable[j] = {}
		threatTable[j].unitType = bogeyType
		threatTable[j].bearing = bearing
		threatTable[j].range = range
		threatTable[j].altitude = altitude
		threatTable[j].speed = speed
		threatTable[j].heading = heading
	end

	table.sort(threatTable,sortRanges)
	
	return threatTable
end

function ewrs.outText(activePlayer, threatTable, bogeyDope, greeting)
	local status, result = pcall(function()
		
		local message = {}
		local altUnits
		local speedUnits
		local rangeUnits
		local bogeyDope = bogeyDope or false
		if ewrs.groupSettings[tostring(activePlayer.groupID)].measurements == "metric" then
			altUnits = "m"
			speedUnits = "Km/h"
			rangeUnits = "Km"
		else
			altUnits = "ft"
			speedUnits = "Knts"
			rangeUnits = "NM"
		end
		
		if #threatTable >= 1 then
			local maxThreats = nil
			local messageGreeting = nil
			if greeting == nil then
				if bogeyDope then
					maxThreats = 1
					messageGreeting = "EWRS Bogey Dope for: " .. activePlayer.player
				else
					if ewrs.maxThreatDisplay == 0 then
						maxThreats = 999
					else
						maxThreats = ewrs.maxThreatDisplay
					end
					messageGreeting = "EWRS Picture Report for: " .. activePlayer.player .. " -- Reference: " .. ewrs.groupSettings[tostring(activePlayer.groupID)].reference
				end
			else
				messageGreeting = greeting
				maxThreats = ewrs.maxFriendlyDisplay
			end
			
			--Display table
			table.insert(message, "\n")
			table.insert(message, messageGreeting)
			table.insert(message, "\n\n")
			table.insert(message, string.format( "%-16s", "TYPE"))
			table.insert(message, string.format( "%-12s", "BRG"))
			table.insert(message, string.format( "%-12s", "RNG"))
			table.insert(message, string.format( "%-21s", "ALT"))
			table.insert(message, string.format( "%-15s", "SPD"))
			table.insert(message, string.format( "%-3s", "HDG"))
			table.insert(message, "\n")
				
			for k = 1, maxThreats do
				if threatTable[k] == nil then break end
				table.insert(message, "\n")
				table.insert(message, string.format( "%-16s", threatTable[k].unitType))
				if threatTable[k].range == ewrs.notAvailable then
					table.insert(message, string.format( "%-12s", " "))
					table.insert(message, string.format( "%-12s", "POSITION"))
					table.insert(message, string.format( "%-21s", " "))
					table.insert(message, string.format( "%-15s", "UNKNOWN"))
					table.insert(message, string.format( "%-3s", " "))
				else
					table.insert(message, string.format( "%03d", threatTable[k].bearing))
					table.insert(message, string.format( "%8.1f %s", threatTable[k].range, rangeUnits))
					table.insert(message, string.format( "%9d %s", threatTable[k].altitude, altUnits))
					table.insert(message, string.format( "%9d %s", threatTable[k].speed, speedUnits))
					table.insert(message, string.format( "         %03d", threatTable[k].heading))
				end
				table.insert(message, "\n")
			end
			trigger.action.outTextForGroup(activePlayer.groupID, table.concat(message), ewrs.messageDisplayTime)
		else
			if (not ewrs.disableMessageWhenNoThreats) or (ewrs.onDemand) and greeting == nil then
				trigger.action.outTextForGroup(activePlayer.groupID, "\nEWRS Picture Report for: " .. activePlayer.player .. "\n\nNo targets detected", ewrs.messageDisplayTime)
			end
			if greeting ~= nil then
				trigger.action.outTextForGroup(activePlayer.groupID, "\nEWRS Friendly Picture for: " .. activePlayer.player .. "\n\nNo friendlies detected", ewrs.messageDisplayTime)
			end
		end
	end)
	if not status then
		env.error(string.format("EWRS outText Error: %s", result))
	end
end

function ewrs.displayMessageToAll()
	local status, result = pcall(function()
		timer.scheduleFunction(ewrs.displayMessageToAll, nil, timer.getTime() + ewrs.messageUpdateInterval)
		ewrs.findRadarUnits()
		ewrs.getDetectedTargets()
		for i = 1, #ewrs.activePlayers do
			if ewrs.groupSettings[tostring(ewrs.activePlayers[i].groupID)].messages then
				if ewrs.activePlayers[i].side == 1 and #ewrs.redEwrUnits > 0 or ewrs.activePlayers[i].side == 2 and #ewrs.blueEwrUnits > 0 then
					ewrs.outText(ewrs.activePlayers[i], ewrs.buildThreatTable(ewrs.activePlayers[i]))
				end -- if ewrs.activePlayers[i].side == 1 and #ewrs.redEwrUnits > 0 or ewrs.activePlayers[i].side == 2 and #ewrs.blueEwrUnits > 0 then
			end -- if ewrs.groupSettings[tostring(ewrs.activePlayers[i].groupID)].messages then
		end -- for i = 1, #ewrs.activePlayers do
	end)
	if not status then
		env.error(string.format("EWRS displayMessageToAll Error: %s", result))
	end
end

function ewrs.onDemandMessage(args)
	local status, result = pcall(function()
		ewrs.findRadarUnits()
		ewrs.getDetectedTargets()
		for i = 1, #ewrs.activePlayers do
			if ewrs.activePlayers[i].groupID == args[1] then
				ewrs.outText(ewrs.activePlayers[i], ewrs.buildThreatTable(ewrs.activePlayers[i],args[2]),args[2])
			end
		end
	end)
	if not status then
		env.error(string.format("EWRS onDemandMessage Error: %s", result))
	end
end

function ewrs.buildFriendlyTable(friendlyNames,activePlayer)
	local function sortRanges(v1,v2)
		return v1.range < v2.range
	end

	local units = {}
	for i =1, #friendlyNames do
		local unit = Unit.getByName(friendlyNames[i])
		if unit ~= nil and unit:isActive() then
		
			table.insert(units,unit)
		else
			--env.error("Friendly Picture - Unit not found: "..friendlyNames[i]) -- Client Planes that are not active will fall into here.
		end
	end
	
	local _self = Unit.getByName(activePlayer.unitname)
	local selfpos = _self:getPosition()
	local referenceX = selfpos.p.x
	local referenceZ = selfpos.p.z
	
	local friendlyTable = {}
	
	for k,v in pairs(units) do
		local velocity = v:getVelocity()
		local pos = v:getPosition()
		local bogeyType = v:getTypeName()
		if pos.p.x ~= selfpos.p.x and pos.p.z ~= selfpos.p.z then --same position as self, means its you!

			local bearing = ewrs.getBearing(referenceX,referenceZ,pos.p.x,pos.p.z)
			local heading = ewrs.getHeading(velocity)
			local range = ewrs.getDistance(referenceX,referenceZ,pos.p.x,pos.p.z) -- meters
			local altitude = pos.p.y --meters
			local speed = ewrs.getSpeed(velocity) --m/s

			if ewrs.groupSettings[tostring(activePlayer.groupID)].measurements == "metric" then
				range = range / 1000 --change to KM
				speed = mist.utils.mpsToKmph(speed)
				--altitude already in meters
			else
				range = mist.utils.metersToNM(range)
				speed = mist.utils.mpsToKnots(speed)
				altitude = mist.utils.metersToFeet(altitude)
			end
		
			local j = #friendlyTable + 1
			friendlyTable[j] = {}
			friendlyTable[j].unitType = bogeyType
			friendlyTable[j].bearing = bearing
			friendlyTable[j].range = range
			friendlyTable[j].altitude = altitude
			friendlyTable[j].speed = speed
			friendlyTable[j].heading = heading
		else
			--env.info("Friendly Picture - Found Self") 
		end
	end

	table.sort(friendlyTable,sortRanges)
	
	return friendlyTable
end

function ewrs.friendlyPicture(args)
	local status, result = pcall(function()
		for i = 1, #ewrs.activePlayers do
			if ewrs.activePlayers[i].groupID == args[1] then
				local sideString = nil
				if  ewrs.activePlayers[i].side == 1 then
					sideString = "[red]"
				else
					sideString = "[blue]"
				end
				local filter = {sideString.."[helicopter]", sideString.."[plane]"}
				local friendlies = mist.makeUnitTable(filter) --find a way to do this only once if there is more then 1 person in a group
				local friendlyTable = ewrs.buildFriendlyTable(friendlies,ewrs.activePlayers[i])
				local greeting = "EWRS Friendly Picture for: " .. ewrs.activePlayers[i].player
				ewrs.outText(ewrs.activePlayers[i],friendlyTable,false,greeting)
			end
		end
	end)
	if not status then
		env.error(string.format("EWRS friendlyPicture Error: %s", result))
	end
end

function ewrs.buildActivePlayers()
	local status, result = pcall(function()
		local filter = { "[all][plane]","[all][helicopter]"}
		local all_vecs = mist.makeUnitTable(filter)
		ewrs.activePlayers = {}
		for i = 1, #all_vecs do
			local vec = Unit.getByName(all_vecs[i])
			if vec ~= nil and Unit.isActive(vec) then
				playerName = Unit.getPlayerName(vec)
				local groupID = ewrs.getGroupId(vec)
				if playerName ~= nil then
					unitCategory = ewrs.acCategories[Unit.getTypeName(vec)]
					if ewrs.disableFightersBRA and unitCategory == ewrs.FIGHTER then
						--DONT DO ANYTHING
					else
						local group = Unit.getGroup(vec)
						if ewrs.enableBlueTeam and Unit.getCoalition(vec) == 2 then
							ewrs.addPlayer(playerName, groupID, vec)
						elseif ewrs.enableRedTeam and Unit.getCoalition(vec) == 1 then
							ewrs.addPlayer(playerName, groupID, vec)
						end
					end
				end
			end
		end
	end) -- pcall
	
	if not status then
		env.error(string.format("EWRS buildActivePlayers Error: %s", result))
	end
end

--THANK YOU ciribob http://forums.eagle.ru/showpost.php?p=2499638&postcount=5
--And Stonehouse for pointing me there
function ewrs.getGroupId(_unit) --Temp fix for client groups not being accessable

    local _unitDB =  mist.DBs.unitsById[tonumber(_unit:getID())]
    if _unitDB ~= nil and _unitDB.groupId then
        return _unitDB.groupId
    end

    return nil
end

function ewrs.getGroupCategory(unit)
	local unitDB = mist.DBs.unitsById[tonumber(unit:getID())]
	 if unitDB ~= nil and unitDB.category then
        return unitDB.category
    end

    return nil
end

function ewrs.addPlayer(playerName, groupID, unit )
	local status, result = pcall(function()
		local i = #ewrs.activePlayers + 1
		ewrs.activePlayers[i] = {}
		ewrs.activePlayers[i].player = playerName
		ewrs.activePlayers[i].groupID = groupID
		ewrs.activePlayers[i].unitname = unit:getName()
		ewrs.activePlayers[i].side = unit:getCoalition() 
	
		-- add default settings to settings table if it hasn't been done yet
		if ewrs.groupSettings[tostring(groupID)] == nil then
			ewrs.addGroupSettings(tostring(groupID))
		end
	end)
	if not status then
		env.error(string.format("EWRS addPlayer Error: %s", result))
	end
end

-- filters units so ones detected by multiple radar sites still only get listed once
-- Filters out anything that isn't a plane or helicopter
function ewrs.filterUnits(units)
	local newUnits = {}
	for k,v in pairs(units) do
		local valid = true
		if v["object"]:getCategory() ~= Object.Category.UNIT then --rare but i've had it detect missiles
			valid = false
		end
		if valid then --another check cause it seems AI radar can detected some ground units
			local category = ewrs.getGroupCategory(v["object"])
			if category ~= "plane" and category ~= "helicopter" then valid = false end
		end

		if valid then
			for nk,nv in pairs (newUnits) do --recursive loop, can't see a way around this
				if v["object"]:getName() == nv["object"]:getName() then 
					valid = false
					--update already found unit incase the first detection(s) didn't know type or distance
					if v["type"] then
						nv["type"] = true
					end
					if v["distance"] then
						nv["distance"] = true
					end
				end
			end
		end
		
		if valid then
			table.insert(newUnits, v)
		end
	end
	return newUnits
end

function ewrs.getDetectedTargets()
	if #ewrs.blueEwrUnits > 0 then
		ewrs.currentlyDetectedRedUnits = ewrs.findDetectedTargets("red")
	end
	if #ewrs.redEwrUnits > 0 then
		ewrs.currentlyDetectedBlueUnits = ewrs.findDetectedTargets("blue")
	end
end

function ewrs.findDetectedTargets(side)
	local units = {}
	local ewrUnits = {}

	if side == "red" then
		ewrUnits = ewrs.blueEwrUnits
	elseif side == "blue" then
		ewrUnits = ewrs.redEwrUnits
	end

	for n = 1, #ewrUnits do
		local ewrUnit = Unit.getByName(ewrUnits[n])
		if ewrUnit ~= nil then
			local ewrControl = ewrUnit:getGroup():getController()
			local detectedTargets = ewrControl:getDetectedTargets(Controller.Detection.RADAR)
			for k,v in pairs (detectedTargets) do
				table.insert(units, v)
			end
		end
	end
	return ewrs.filterUnits(units)
end

function ewrs.findRadarUnits()
	local filter = {}
	if ewrs.enableBlueTeam and ewrs.enableRedTeam then
		filter = { "[all][plane]", "[all][vehicle]", "[all][ship]"}
	elseif ewrs.enableBlueTeam then
		filter = { "[blue][plane]", "[blue][vehicle]", "[blue][ship]"}
	elseif ewrs.enableRedTeam then
		filter = { "[red][plane]", "[red][vehicle]", "[red][ship]"}
	end
	local all_vecs = mist.makeUnitTable(filter)
	local redUnits = {}
	local blueUnits = {}
	
	for i = 1, #all_vecs do
		local vec = Unit.getByName(all_vecs[i])
	
		if vec ~= nil then
			if Unit.isActive(vec) then
				local vec_type = Unit.getTypeName(vec)
				for n = 1, #ewrs.validSearchRadars do
					if ewrs.validSearchRadars[n] == vec_type and Unit.getCoalition(vec) == 2 then
						table.insert(blueUnits, Unit.getName(vec))
						break
					end
					if ewrs.validSearchRadars[n] == vec_type and Unit.getCoalition(vec) == 1 then
						table.insert(redUnits, Unit.getName(vec))
						break
					end
				end --for n = 1, #ewrs.validSearchRadars do
			end --if Unit.isActive(vec) then
		end --if vec ~= nil then
	end --for i = 1, #all_vecs do
	ewrs.blueEwrUnits = blueUnits
	ewrs.redEwrUnits = redUnits
end

function ewrs.addGroupSettings(groupID)
	ewrs.groupSettings[groupID] = {}
	ewrs.groupSettings[groupID].reference = ewrs.defaultReference
	ewrs.groupSettings[groupID].measurements = ewrs.defaultMeasurements
	ewrs.groupSettings[groupID].messages = true
end

function ewrs.setGroupReference(args)
	local groupID = args[1]
	ewrs.groupSettings[tostring(groupID)].reference = args[2]
	trigger.action.outTextForGroup(groupID,"Reference changed to "..args[2],ewrs.messageDisplayTime)
end

function ewrs.setGroupMeasurements(args)
	local groupID = args[1]
	ewrs.groupSettings[tostring(groupID)].measurements = args[2]
	trigger.action.outTextForGroup(groupID,"Measurement units changed to "..args[2],ewrs.messageDisplayTime)
end

function ewrs.setGroupMessages(args)
	local groupID = args[1]
	local onOff
	if args[2] then onOff = "on" else onOff = "off" end
	ewrs.groupSettings[tostring(groupID)].messages = args[2]
	trigger.action.outTextForGroup(groupID,"Picture reports for group turned "..onOff,ewrs.messageDisplayTime)
end

function ewrs.buildF10Menu()
	local status, result = pcall(function()
		for i = 1, #ewrs.activePlayers do
			local groupID = ewrs.activePlayers[i].groupID
			local stringGroupID = tostring(groupID)
			if ewrs.builtF10Menus[stringGroupID] == nil then
				local rootPath = missionCommands.addSubMenuForGroup(groupID, "EWRS")
				
				if ewrs.allowBogeyDope then
					missionCommands.addCommandForGroup(groupID, "Request Bogey Dope",rootPath,ewrs.onDemandMessage,{groupID,true})
				end
				
				if ewrs.onDemand then
					missionCommands.addCommandForGroup(groupID, "Request Picture",rootPath,ewrs.onDemandMessage,{groupID})
				end
				
				if ewrs.allowFriendlyPicture then
					missionCommands.addCommandForGroup(groupID, "Request Friendly Picture",rootPath,ewrs.friendlyPicture,{groupID})
				end
				
				if not ewrs.restrictToOneReference then
					local referenceSetPath = missionCommands.addSubMenuForGroup(groupID,"Set GROUP's reference point", rootPath)
					missionCommands.addCommandForGroup(groupID, "Set to Bullseye",referenceSetPath,ewrs.setGroupReference,{groupID, "bulls"})
					missionCommands.addCommandForGroup(groupID, "Set to Self",referenceSetPath,ewrs.setGroupReference,{groupID, "self"})
				end
			
				local measurementsSetPath = missionCommands.addSubMenuForGroup(groupID,"Set GROUP's measurement units",rootPath)
				missionCommands.addCommandForGroup(groupID, "Set to Imperial (feet, knts)",measurementsSetPath,ewrs.setGroupMeasurements,{groupID, "imperial"})
				missionCommands.addCommandForGroup(groupID, "Set to Metric (meters, km/h)",measurementsSetPath,ewrs.setGroupMeasurements,{groupID, "metric"})

				if not ewrs.onDemand then
					local messageOnOffPath = missionCommands.addSubMenuForGroup(groupID, "Turn Picture Report On/Off",rootPath)
					missionCommands.addCommandForGroup(groupID, "Message ON", messageOnOffPath, ewrs.setGroupMessages, {groupID, true})
					missionCommands.addCommandForGroup(groupID, "Message OFF", messageOnOffPath, ewrs.setGroupMessages, {groupID, false})
				end

				ewrs.builtF10Menus[stringGroupID] = true
			end
		end
	end)
	
	if not status then
		env.error(string.format("EWRS buildF10Menu Error: %s", result))
	end
end

--temp fix for ground units being detected by radar - FIXED
--[[ Leaving this here just in case I introduce threat based filtering, saves me writing it again
ewrs.validThreats = {
["A-10A"] = true,
["A-10C"] = true,
["A-50"] = true,
["AH-1W"] = true,
["AH-64A"] = true,
["AH-64D"] = true,
["An-26B"] = true,
["An-30M"] = true,
["B-1B"] = true,
["B-52H"] = true,
["Bf-109K-4"] = true,
["C-101CC"] = true,
["C-101EB"] = true,
["C-130"] = true,
["C-17A"] = true,
["CH-47D"] = true,
["CH-53E"] = true,
["E-2D"] = true,
["E-2C"] = true,
["E-3A"] = true,
["F-111F"] = true,
["F-117A"] = true,
["F-14A"] = true,
["F-15C"] = true,
["F-15E"] = true,
["F-16A"] = true,
["F-16A MLU"] = true,
["F-16C bl.50"] = true,
["F-16C bl.52d"] = true,
["F-4E"] = true,
["F-5E"] = true,
["F-5E-3"] = true,
["F-86F Sabre"] = true,
["F/A-18A"] = true,
["F/A-18C"] = true,
["FW-190D9"] = true,
["Hawk"] = true,
["IL-76MD"] = true,
["IL-78M"] = true,
["KC-135"] = true,
["Ka-27"] = true,
["Ka-50"] = true,
["Ka-52"] = true,
["L-39C"] = true,
["L-39ZA"] = true,
["M-2000C"] = true,
["MQ-9 Reaper"] = true,
["Mi-24V"] = true,
["Mi-26"] = true,
["Mi-28N"] = true,
["Mi-8MT"] = true,
["MiG-15bis"] = true,
["MiG-21Bis"] = true,
["MiG-23MLD"] = true,
["MiG-25PD"] = true,
["MiG-25RBT"] = true,
["MiG-27K"] = true,
["MiG-29A"] = true,
["MiG-29G"] = true,
["MiG-29K"] = true,
["MiG-29S"] = true,
["MiG-31"] = true,
["Mirage 2000-5"] = true,
["OH-58D"] = true,
["P-51D"] = true,
["RQ-1A Predator"] = true,
["S-3B"] = true,
["S-3B Tanker"] = true,
["SH-3W"] = true,
["SH-60B"] = true,
["Su-17M4"] = true,
["Su-24M"] = true,
["Su-24MR"] = true,
["Su-25"] = true,
["Su-25T"] = true,
["Su-25TM"] = true,
["Su-27"] = true,
["Su-30"] = true,
["Su-33"] = true,
["Su-34"] = true,
["TF-51D"] = true,
["Tornado GR4"] = true,
["Tornado IDS"] = true,
["Tu-142"] = true,
["Tu-160"] = true,
["Tu-22M3"] = true,
["Tu-95MS"] = true,
["UH-1H"] = true,
["UH-60A"] = true,
["Yak-40"] = true,
}
]]

--SCRIPT INIT
ewrs.currentlyDetectedRedUnits = {}
ewrs.currentlyDetectedBlueUnits = {}
ewrs.redEwrUnits = {}
ewrs.blueEwrUnits = {}
ewrs.activePlayers = {}
ewrs.groupSettings = {}
ewrs.builtF10Menus = {}
ewrs.notAvailable = 999999

ewrs.update()
if not ewrs.onDemand then
	timer.scheduleFunction(ewrs.displayMessageToAll, nil, timer.getTime() + ewrs.messageUpdateInterval)
end
trigger.action.outText("EWRS by Steggles is now running",15)
env.info("EWRS Running")

--[[
TODO: 
	- Add check on friendly picture to not give one if no AWACS / EWR units are active. Doesn't use radar info anyway. Maybe just leave it to help out people with SA? Feedback Please!!
	- Clean up functions and arguments from bogeyDope and friendly picture additions
	- Threat based filtering if theres interest.
]]