-- Adds functions in radio menu F10
--Script attached to mission and executed via trigger
--Functions accessed via LUA Run Script
------------------------------------------------------------------------------------------------------- 
--player can request emergency resupply with S-3B's
-- It is possible to send the whole PACK in RTB to avoid unnecessary losses. 
------------------------------------------------------------------------------------------------------- 
-- last modification  adjustment_g
if not versionDCE then versionDCE = {} end
versionDCE["Mission Scripts\AddCommandRadioF10.lua"] = "1.11.42"
------------------------------------------------------------------------------------------------------- 
-- cleanCode_a				(a: remove RemovePlane)
-- adjustment_g				(g force RTB if bingo)(f ENI table)(e: add SAR_F10)(d GetHeading)(c coalitionIdNumeric)(b group Item Radio)(a: ajust function trigo)
-- debug_f					(f getCategory)(e getHeading Z)(d: tanker exist)n'affiche pas les messages d'error sauf à la fin de mission
-- debug_bonfor_a			RTB from to inversé
-- modification M69_a		getOut (a allows you to remove the pilot from a crashed helicopter, for immediate or later recovery)
-- modification M68_a		add AFAC task
-- modification M60_a		add CTLD (a JTAC)
-- modification M36_e		(e: 1 h) (d: add timer) MenuRadio request manual TurnIntoWind
-- modification M36_e		Help CAP (e: camp rouge et bleu)
-- modification M32_d		E-2C automatic retreat (d only if fighter)(c: debug)
-- modification M29_i		Added MenuRadio F10  (i:escorte to RTB(@bonfor))(h:strike or SEAD only packages to RTB(@bonfor))(g:movePlane) (f: CallTankRefuel camp rouge et bleu)
------------------------------------------------------------------------------------------------------- 
	
if not camp.debugInGamePopup then 
	env.setErrorMessageBoxEnabled(false)
end


coalitionId = {
	["0"] = "neutral",
	["1"] = "red",
	["2"] = "blue",
}

coalitionIdNumeric = {
	[0] = "neutral",
	[1] = "red",
	[2] = "blue",
}

coalitionIdNumericENI = {
	[0] = 1,
	[1] = 2,
	[2] = 1,
}

--variable global
DCS_Side = {"blue", "red", "neutrals"}

DCS_ENI_Side = {
	["blue"] = "red",
	["red"] = "blue"
	}

-- Unit.Category = {
-- 	AIRPLANE      = 0,
-- 	HELICOPTER    = 1,
-- 	GROUND_UNIT   = 2,
-- 	SHIP          = 3,
-- 	STRUCTURE     = 4
--   }
DCS_CategoryById = {
	[0] = Airplane,
	[1] = Helicopters,

}

local commandDB = {}

tabBingoPlane = {}
local tabJockerPlane = {}
	
TPN_alreadyAdded = false
	
groundDamagedFlyingMachine = {} 

function _affiche(_table, titre, prof)


	--export custom mission log
	local logExp = "logExp  " 
	
	-- prof = profondeur de niveau dans la hierarchie
	if not prof or prof == nil then						
		prof = 999
	end 
  	logExp = logExp.."\n"
  
    if titre == nil then logExp = logExp.. string.format(" _affiche() titre = nil ")
    elseif type( titre) == "string" then
		logExp = logExp.. string.format(" _affiche(titre) "..tostring(titre)).."\n"
	end
  
	if type( _table) == "table"  then --and  (table.getn(_table) ~= 0 or table.getn(_table) ~= nil
	
		for a, b in pairs(_table) do --for a, b in pairs(event.initiator) do --for a, b in pairs(_ammo) do
			-- logExp.. " _affiche( a  ) ".. tostring(a).."\n"  
		
			if  type(b) ~= "table" then
				logExp = logExp.." _affiche (a b)     "..tostring(a).." "..tostring(b).."\n"
			elseif type(b) == "table"   and prof >= 2 then
				for c, d in pairs(b) do
					logExp = logExp.. " _affiche(a c)     "..tostring(a).." "..tostring(c).."\n"
					
					
					if type(d)~= "table"  then
						logExp = logExp.. " _affiche(. d)                "..tostring(d).."\n"
					elseif type(d) == "table"  and prof >= 3 then
						for e, f in pairs(d) do
							-- logExp = logExp.. " _affiche( e)                     "..tostring(e).."\n"
							
							
							if type( f ) ~= "table"  then
								logExp = logExp.. " _affiche(e f)                          "..tostring(e).." "..tostring(f).."\n"
							elseif type( f ) == "table"  and prof >= 4 then
								logExp = logExp.. " _affiche( e)                                "..tostring(e).."\n"
								for g, h in pairs(f) do
									logExp = logExp.. " _affiche(Ig)                                 "..tostring(g).."\n"
									
									
									if type( h ) ~= "table"  then
										logExp = logExp.. " _affiche(g h)                                    "..tostring(g).." "..tostring(h).."\n"	
									elseif type( h ) == "table"  and prof >= 5 then
										logExp = logExp.. " _affiche( g)                                         "..tostring(g).."\n"
										for i, j in pairs(h) do
											-- logExp = logExp.. " _affiche(i)                                         "..tostring(i).."\n"
										
										
											if type( j ) ~= "table"  then
												logExp = logExp.. " _affiche(i j)                                              "..tostring(i).." "..tostring(j).."\n"
											elseif type( j ) == "table" and prof >= 6 then									
												logExp = logExp.. " _affiche(i)                                                  "..tostring(i).."\n"
												for k, l in pairs(j) do
													-- logExp = logExp.. " _affiche(k)                                                   "..tostring(k).."\n"
													
													if type( l ) ~= "table"  then
														logExp = logExp.. " _affiche(k l)                                                   "..tostring(k).." "..tostring(l).."\n"
													elseif type( l ) == "table" and prof >= 7 then
														logExp = logExp.. " _affiche(k)                                                       "..tostring(k).."\n"
														for m, n in pairs(l) do
															logExp = logExp.. " _affiche(m)                                                        "..tostring(m).."\n"
														
														
															if type( n ) ~= "table"  then
																logExp = logExp.. " _affiche(m n)                                                   "..tostring(m).." "..tostring(n).."\n"
															elseif type( n ) == "table" and prof >= 7 then
																logExp = logExp.. " _affiche(m)                                                       "..tostring(m).."\n"
																for o, p in pairs(n) do
																	logExp = logExp.. " _affiche(o)                                                        "..tostring(o).."\n"
														
														
																	if type( p ) ~= "table"  then
																		logExp = logExp.. " _affiche(p)                                                             "..tostring(p).."\n"
																	elseif type( p ) == "table"  and prof >= 8 then
																		logExp = logExp.. " p est une table                                                              "..tostring(p).."---------------------------".."\n"
																			
																	end
																end
															end --if
														end --for l
													end --if
												end -- for j
											end --if
										end -- for h
									end --if
								end --for f
							end --elseif
						end -- for d
					end -- if d
				end -- for v
			end -- if v
		end  -- for _table
	
	else logExp = logExp.. "_affiche NoTable==> " ..tostring(_table).."\n"
	
	end -- if if type( _table) == "table"

	
	-- log.write('MIGUEL.EXPORT',log.INFO,logExp)
	
	env.info( logExp )
	
end -- function affiche

-- sorts tables alphabetically, to be used in a "for" loop instead of pairs or ipairs
-- http://www.lua.org/pil/19.3.html
function pairsByKeys (t, f)
    local a = {}
	local initType
	local dontSort = false
    for n in pairs(t) do initType = type(n) break end
	for n in pairs(t) do 
		table.insert(a, n) 
		if type(n) ~= initType then dontSort = true end
	end
	if not dontSort then 
		table.sort(a, f) 
	end
    local i = 0      -- iterator variable
    local iter = function ()   -- iterator function
        i = i + 1
        if a[i] == nil then return nil
        else return a[i], t[a[i]]
        end
    end
    return iter
end
--function to return distance between two vector2 points
function GetDistance(p1, p2)
	local deltax = p2.x - p1.x
	local deltay = p2.y - p1.y
	return math.sqrt(math.pow(deltax, 2) + math.pow(deltay, 2))
end

function radToDeg(_rad)
	Deg = _rad * (180/math.pi)
	return Deg
end 

--function to make a deep copy of a table
function deepcopy(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for orig_key, orig_value in next, orig, nil do
            copy[deepcopy(orig_key)] = deepcopy(orig_value)
        end
        setmetatable(copy, deepcopy(getmetatable(orig)))
    else -- number, string, boolean, etc
        copy = orig
    end
    return copy
end

function GetHeading(p1, p2)
	local deltax = p2.x - p1.x
	local deltay 
	if (p2.z and p1.z) then
		deltay = p2.z - p1.z
	else
		deltay = p2.y - p1.y
	end
	if (deltax > 0) and (deltay == 0) then
		return 0
	elseif (deltax > 0) and (deltay > 0) then
		return math.deg(math.atan(deltay / deltax))
	elseif (deltax == 0) and (deltay > 0) then
		return 90
	elseif (deltax < 0) and (deltay > 0) then
		return 90 - math.deg(math.atan(deltax / deltay))
	elseif (deltax < 0) and (deltay == 0) then
		return 180
	elseif (deltax < 0) and (deltay < 0) then
		return 180 + math.deg(math.atan(deltay / deltax))
	elseif (deltax == 0) and (deltay < 0) then
		return 270
	elseif (deltax > 0) and (deltay < 0) then
		return 270 - math.deg(math.atan(deltax / deltay))
	else
		return 0
	end
end

-- --function to return heading between two vector2 points
-- -- return une valeur en degré par rapport au nord géographique (pas le cercle trigonometrique)
-- function GetHeading(p1, p2)

-- 	-- env.info( "ACRF10  p1.x "..tostring(p1.x).." p1.y: "..tostring(p1.y))
-- 	-- env.info( "ACRF10  p2.x "..tostring(p2.x).." p1.y: "..tostring(p2.y))

-- 	local deltax = p2.x - p1.x
-- 	local deltay = p2.y - p1.y
-- 	local result 
-- 	if (deltax > 0) and (deltay == 0) then
-- 		result =  0
-- 	elseif (deltax > 0) and (deltay > 0) then
-- 		result =  math.deg(math.atan(deltay / deltax))
-- 	elseif (deltax == 0) and (deltay > 0) then
-- 		result =  90
-- 	elseif (deltax < 0) and (deltay > 0) then
-- 		result =  90 - math.deg(math.atan(deltax / deltay))
-- 	elseif (deltax < 0) and (deltay == 0) then
-- 		result =  180
-- 	elseif (deltax < 0) and (deltay < 0) then
-- 		result =  180 + math.deg(math.atan(deltay / deltax))
-- 	elseif (deltax == 0) and (deltay < 0) then
-- 		result =  270
-- 	elseif (deltax > 0) and (deltay < 0) then
-- 		result =  270 - math.deg(math.atan(deltax / deltay))
-- 	else
-- 		result =  0
-- 	end

-- 	-- --https://www.mathepower.com/fr/fonctionslineaires.php
	
-- 	env.info( "ACRF10  result "..tostring(result))

-- 	return result 

-- end

--function to return heading between two vector2 points
-- function GetHeading2(p1, p2)

	-- local dir = math.atan2(p1, p2)
	-- return dir

-- end

--function to return a new point offset from an initial point
	-- angle en degré avec nord geographique (pas trigonometrique)
function GetOffsetPoint(point, heading, distance)
	return {
		x = point.x + math.cos(math.rad(heading)) * distance,
		y = point.y + math.sin(math.rad(heading)) * distance
	}
end

--https://github.com/mrSkortch/MissionScriptingTools/releases
--- Returns heading of given unit.
-- @tparam Unit unit unit whose heading is returned.
-- @param rawHeading
-- @treturn number heading of the unit, in range
-- of 0 to 2*pi.
function getHeadingByPos(unit)
	local unitpos = unit:getPosition()
	local Heading = 0
	if unitpos then
		local Heading = math.atan2(unitpos.x.z, unitpos.x.x)
		if Heading < 0 then
			Heading = Heading + 2*math.pi	-- put heading in range of 0 to 2*pi
		end
		return Heading
	else
		return nil
	end
end

--function to return the angle between two headings
function GetDeltaHeadingIM(h1, h2)
	local delta = h2 - h1
	if delta > 180 then
		delta = delta - 360
	elseif delta <= -180 then
		delta = delta + 360
	end
	return delta
end

--check si un point est dans le polygone
function CheckPointInPoly2(point, poly)
	
    local crossings = 0
	for n = 1, #poly - 1 do
         if (poly[n].y < point.y and poly[n + 1].y > point.y) or (poly[n].y > point.y and poly[n + 1].y < point.y) then
            local dx = poly[n + 1].x - poly[n].x
			local dy = poly[n + 1].y - poly[n].y
			local delta_point_y = point.y - poly[n].y
			local delta_point_x = dx / dy * delta_point_y
			if poly[n].x + delta_point_x > point.x then
				crossings = crossings + 1
			end
		end
	end

	if crossings % 2 ~= 0 then
		return true
	else
		return false
	end
end


function FctRemovePlane(_unit)
	_unit:destroy()
end

function RemovePlane(PlayerGroup)

	local PlayerUnits = PlayerGroup:getUnits()
	local PlayerUnit = PlayerUnits[1]	
	local PlayerUnitPoint = PlayerUnit:getPoint()
	local Coalition = PlayerUnit:getCoalition()
	missionCommands.removeItem( {"nearby aircraft"})
	local requestM = missionCommands.addSubMenu('nearby aircraft'  )
	local RPlane = {}
	local groups = coalition.getGroups(Coalition, Group.Category.AIRPLANE)
	for i, gp in pairs(groups) do	
		local gpName = Group.getName(gp)
		local units = gp:getUnits()
		 
		for n=1, #units do
			local _unit = units[n]
			if  _unit:isActive() and not _unit:inAir() then
				
				local description = _unit:getDesc()	
				
				-- _affiche(description, "description")
				
				local unitPos = _unit:getPoint()
				local  gpGid = Group.getID(gp)
				local  UnitId = Unit.getID(_unit)
				local unitCallsign = _unit:getCallsign()
				local distance = math.floor(math.sqrt(math.pow(unitPos.x - PlayerUnitPoint.x, 2) + math.pow(unitPos.z - PlayerUnitPoint.z, 2)))
				if distance <= 900 then
					env.info(gpName.." "..unitCallsign.." "..distance.."m ")
					-- trigger.action.outText(gpName.." "..unitCallsign.." "..distance.."m ", 15)	--FOR DEBUG
					-- local subN1 = missionCommands.addSubMenu(gpName.." "..UnitId, requestM)
					RPlane[UnitId] = missionCommands.addCommand(gpName.." "..unitCallsign, requestM, FctRemovePlane, _unit)
				end
			end
		end
	end
end


-- modification M32	E-2C automatic retreat 
function AirRetreat()
	
	local current_time = timer.getTime()
	
	local groups = coalition.getGroups(coalition.side.BLUE, Group.Category.AIRPLANE)
	
	for i, gp in pairs(groups) do	
	
		local gpName = Group.getName(gp)
		
		if   string.find(gpName,"AWACS") then
			local units = gp:getUnits()
			local _unit = units[1]
	
			if _unit and _unit:getTypeName() == "E-2C" and _unit:isActive() and _unit:inAir() then
				local awacs_point = _unit:getPoint()
				local  gpGid = Group.getID(gp)
				local nameAwacs =  _unit:getName()
				if not RetreatTimeGp then RetreatTimeGp = {} end
				if not RetreatTimeGp[gpGid] then RetreatTimeGp[gpGid] = {} end
				if not RetreatTimeGp[gpGid].rTime then RetreatTimeGp[gpGid].rTime = 0  end
				
				if _unit and current_time >  RetreatTimeGp[gpGid].rTime then							--if _unit exists
					local ctr = _unit:getGroup():getController()										--get _unit controller
					local targets = ctr:getDetectedTargets()											--get detected targets of this EWR
					for t = 1, #targets do																--iterate through detected targets
						if targets[t].object and current_time >  RetreatTimeGp[gpGid].rTime then
							local objCat = Object.getCategory(targets[t].object)								--get object category
							if objCat == 1 then															--object is a _unit
								local desc = targets[t].object:getDesc()								--get descriptor descriptor
								local descAwacs = _unit:getDesc()
								
								-- _affiche(titre) ACRF10 DCE Desc
								-- _affiche (a b)     speedMax0 388.10000610352
								-- _affiche (a b)     massEmpty 10550
								-- _affiche (a b)     range 1950
								-- _affiche(a c)           box min
								-- _affiche(e f)                          y -2.3299200534821
								-- _affiche(e f)                          x -10
								-- _affiche(e f)                          z -9
								-- _affiche(a c)           box max
								-- _affiche(e f)                          y 2.7555100917816
								-- _affiche(e f)                          x 11
								-- _affiche(e f)                          z 9
								-- _affiche (a b)     Hmax 18500
								-- _affiche (a b)     Kmax 0.68999999761581
								-- _affiche (a b)     _origin 
								-- _affiche (a b)     speedMax10K 693.25
								-- _affiche (a b)     NyMin -3
								-- _affiche (a b)     fuelMassMax 3800
								-- _affiche (a b)     speedMax 693.25
								-- _affiche (a b)     NyMax 6.5
								-- _affiche (a b)     massMax 17800
								-- _affiche (a b)     RCS 4
								-- _affiche (a b)     displayName mig-23ml
								-- _affiche (a b)     life 16
								-- _affiche (a b)     VyMax 240
								-- _affiche (a b)     Kab 3
								-- _affiche(a c)           attributes Air
								-- _affiche(d)                true
								-- _affiche(a c)           attributes Fighters
								-- _affiche(d)                true
								-- _affiche(a c)           attributes NonAndLightArmoredUnits
								-- _affiche(d)                true
								-- _affiche(a c)           attributes NonArmoredUnits
								-- _affiche(d)                true
								-- _affiche(a c)           attributes All
								-- _affiche(d)                true
								-- _affiche(a c)           attributes Battle airplanes
								-- _affiche(d)                true
								-- _affiche(a c)           attributes Planes
								-- _affiche(d)                true
								-- _affiche (a b)     typeName MiG-23MLD
								-- _affiche (a b)     category 0
								
								if desc.category == 0 and (desc.attributes["Battle airplanes"] or desc.attributes.Fighters)  then												--descriptor category is airplane 
									--TODO ajouter ici les attributs interressant des chasseurs et non des transports
									--To know what attributes the object type has, look for the unit type script in sub-directories planes/, helicopter/s, vehicles, navy/ of ./Scripts/Database/ directory.
									--and desc.attributs ~= "Battleplane" and desc.attributs ~= "Fighter"
									
									-- attributes Air true
									-- attributes Fighters  true
									-- attributes NonAndLightArmoredUnits true
									-- attributes NonArmoredUnits true
									-- attributes All  true
									-- attributes Battle airplanes true
									-- attributes Planes true

									local target_point = targets[t].object:getPoint()					--get target point					
									local distance = math.sqrt(math.pow(awacs_point.x - target_point.x, 2) + math.pow(awacs_point.z - target_point.z, 2))
									
									if distance < 100000 then
									-- if distance < 150000 then 
										
										local callsign = _unit:getCallsign()
										env.info("ACRF10 DCE AWACS |03b|: Order to Retire "..distance)
										env.info("ACRF10 DCE AWACS |03c|: Order to Retire "..callsign.." Retreat to the aircraft carrier")
										trigger.action.outText(callsign.." Retreat to the aircraft carrier",10)
										
										--active le waypoint du PA										
										RetreatTimeGp[gpGid].rTime = current_time + 300

										local carrierDistance = 99999999
										local xRetreat = 0
										local yRetreat = 0						
										for coalition_name,coal in pairs(env.mission.coalition) do
											if coalition_name == "blue" then
												for country_n,country in ipairs(coal.country) do
													if country.ship then
														for group_n,group in ipairs(country.ship.group) do			
															local groupCarrier = Group.getByName(group.name)													--get carrier group
															if groupCarrier then																				--group exists
																local carrier = groupCarrier:getUnit(1)															--get group leader (assumed to be the carrier)								
																local Desc = carrier:getDesc()					
																if Desc.attributes.AircraftCarrier or Desc.attributes["Aircraft Carriers"] then 
																	local carrierPos = carrier:getPoint()
																	local distance = math.sqrt(math.pow(carrierPos.x - awacs_point.x, 2) + math.pow(carrierPos.z - awacs_point.z, 2))
																	if distance < carrierDistance then																		
																		xRetreat = carrierPos.x
																		yRetreat = carrierPos.z																
																		carrierDistance =  distance
																	end
																end
															end
														end
													end
												end
											end
										end
										

										for _coalition, coalition in pairs(env.mission.coalition) do
											if _coalition  == "blue" then
												for Ncountry, _country in pairs(coalition.country) do	
													if _country.plane then
														for Ngroup, _group in pairs(_country.plane.group) do
															if _group.groupId == gpGid then 
															
																-- si aucun CVN n'a été trouvé, on prend comme position de retraite l'ID "land"
																if xRetreat == 0 then
																	for key, value in ipairs(_group.route.points) do				-- recherche de la position safe du PA et une alti						
																		if value.type == 'Land' then
																			xRetreat = value.x
																			yRetreat = value.y
																		end
																	end
																end
																local retreatRoute = {}
																
																-- retreatRoute = _group.route.points										--copie de l'ancienne route
																retreatRoute = deepcopy(_group.route.points)
																
																-- ajoute comme premier wpt leur position initial pour garder la fonction AWACS
																local FirstWPT = {
																	['alt'] = awacs_point.y,
																	['type'] = 'Turning Point',
																	['action'] = 'Turning Point',
																	['alt_type'] = 'BARO',
																	['speed_locked'] = true,
																	['y'] = awacs_point.z,
																	['x'] = awacs_point.x,
																	['formation_template'] = '',
																	['speed'] = descAwacs.speedMax,
																	['ETA_locked'] = true,
																	['task'] = {
																		['id'] = 'ComboTask',
																		['params'] = {
																			['tasks'] = {
																				[1] = {
																					['enabled'] = true,
																					['auto'] = false,
																					['id'] = 'ControlledTask',
																					['number'] = 1,
																					['params'] = {
																						['task'] = {
																							['id'] = 'AWACS',
																							['params'] = {
																							},
																						},
																					},
																				},
																				[2] = {
																					['enabled'] = true,
																					['auto'] = false,
																					['id'] = 'WrappedAction',
																					['number'] = 2,
																					['params'] = {
																						['action'] = {
																							['id'] = 'Option',
																							['params'] = {
																								['variantIndex'] = 1,
																								['value'] = 458753,
																								['name'] = 5,
																								['formationIndex'] = 7,
																							},
																						},
																					},
																				},
																				[3] = {
																					['enabled'] = true,
																					['auto'] = true,
																					['id'] = 'WrappedAction',
																					['number'] = 3,
																					['params'] = {
																						['action'] = {
																							['id'] = 'EPLRS',
																							['params'] = {
																								['value'] = true,
																								['groupId'] = 1,
																							},
																						},
																					},
																				},
																				[4] = {
																					['enabled'] = true,
																					['auto'] = false,
																					['id'] = 'WrappedAction',
																					['number'] = 4,
																					['params'] = {
																						['action'] = {
																							['id'] = 'Option',
																							['params'] = {
																								['value'] = 2,
																								['name'] = 1,
																							},
																						},
																					},
																				},
																			},
																		},
																	},
																	['ETA'] = 0,
																}
																
																
																table.insert(retreatRoute, 1, FirstWPT)
																	
																--modifie les coordonées du premier wpt initial
																retreatRoute[2].x = xRetreat
																retreatRoute[2].y = yRetreat
																retreatRoute[2].alt = awacs_point.y
																retreatRoute[2].speed_locked = true
																retreatRoute[2].ETA_locked = false
																retreatRoute[2].speed = descAwacs.speedMax
																retreatRoute[2].ETA = RetreatTimeGp[gpGid].rTime
																
																local idTasks = #retreatRoute[2].task.params.tasks
																local orbitRetreat = {
																			
																			['enabled'] = true,
																			['auto'] = false,
																			['id'] = 'ControlledTask',
																			['number'] = idTasks+2,
																			['params'] = {
																				['task'] = {
																					['id'] = 'Orbit',
																					['params'] = {
																						['altitude'] = 7315.2,
																						['pattern'] = 'Circle',
																						['speed'] = 138.889,
																					},
																				},
																				['stopCondition'] = {
																					['time'] = RetreatTimeGp[gpGid].rTime,
																				},
																			},
																			
																		}
																
																retreatRoute[2].task.params.tasks[idTasks +1] =  orbitRetreat
																
																--ajoute la task awacs au premier wpt pour garder la fonction awacs operationnel
																local TaskAwacs = {
																		
																		['enabled'] = true,
																		['auto'] = false,
																		['id'] = 'ControlledTask',
																		['number'] = 1,
																		['params'] = {
																			['task'] = {
																				['id'] = 'AWACS',
																				['params'] = {
																				},
																			},
																		},
																		
																	}
																table.insert(retreatRoute[2].task.params.tasks, 1, TaskAwacs)																		
															
																--renumerote les number des task																	
																for i=1, #retreatRoute[1].task.params.tasks do															
																	retreatRoute[1].task.params.tasks[i].number = i																																		
																end

																local Mission = {														--define mission for retreat AWACS
																		id = 'Mission', 
																		params = {
																			route = {
																				points = retreatRoute
																			},
																		}
																	}	
																
																	
																-- local logStr = "Mission = " .. TableSerialization(Mission, 0)
																-- local logFile = io.open(path.."_"..nameAwacs.."_".. "Mission_AWACSretreatRoute.lua", "w")
																-- logFile:write(logStr)
																-- logFile:close()	

																Controller.setTask(ctr, Mission)										--activate task with mission for retreat AWACS
															end
														end
													end
												end
											end
										end
									end
								end
							end
						end
					end
				end
			end
		end
	end
	return timer.getTime() + 1
end

function bingo(gpGid, groupMission)
	
	for index, unit in pairs(groupMission:getUnits()) do	
		
		--getPlayerName(unit)

		-- local humainUnit = getPlayerName(unit)


		local humainUnit = ""
		
		if unit and unit:getPlayerName() then
			humainUnit = unit:getPlayerName()
		end

		local callSign = Unit.getCallsign(unit)	
		if not tabBingoPlane[gpGid] then tabBingoPlane[gpGid] = {} end
		if not tabJockerPlane[gpGid] then tabJockerPlane[gpGid] = {} end
		
		local  gpName = Group.getName(groupMission)
		-- env.info( " bingo() gpName  "..tostring(gpName).." groupMission.id_ "..tostring(groupMission.id_) )
		-- _affiche(groupMission, "groupMission function bingo(gpGid, groupMission)")
		

		if tabBingoPlane[gpGid] and not tabBingoPlane[gpGid][callSign] then												-- si le callSign a deja dit qu'il etait Bingo, on l'oublie		
			if Unit.getFuel(unit) <=  0.34 then																			-- Sur F14, 4000lbs/16000lbs = 0.25%
				trigger.action.outTextForGroup(gpGid, callSign .." Bingo Fuel", 15 , true)
				env.info( "DCE_Bingo AA Unit.getFuel(unit)  "..tostring(groupMission.id_).." gpName: "..tostring(gpName).." callSign: "..callSign.." humainUnit? "..tostring(humainUnit) )			
				
				tabBingoPlane[gpGid][callSign] = true																	-- la callSign � d�ja indiqu� qu'il �tait Bingo
			
				-- if not humainUnit or humainUnit == nil then
					local report = " not humainUnit "
					local cntrl = unit:getController()
					
					cntrl:resetTask()

					env.info( "DCE_Bingo BB    hasTask? "..tostring(cntrl:hasTask()))

					cntrl:setOption(AI.Option.Air.id.PROHIBIT_AA, true)

					-- cntrl:setOption(AI.Option.Air.id.RTB_ON_BINGO, true)

					cntrl:setOption(AI.Option.Air.id.PROHIBIT_AB, true)

					cntrl:setOption(AI.Option.Air.id.PROHIBIT_JETT, false)

					cntrl:setOption(AI.Option.Air.id.JETT_TANKS_IF_EMPTY, true)

					

					report = report.." RTB_ON_BINGO & PROHIBIT_AB "
					
					local unitName =  unit:getName()

					env.info( "DCE_Bingo CC      report "..tostring(groupMission.id_).." "..tostring(unitName).." "..callSign.." report "..tostring(report) )

					local description = unit:getDesc()	
					_affiche(description, "description function bingo()")

					local breaktab = false
					local rtbGroup = {
						name = "",
						from = 0,
						to = 0
					}
	
					for _coalition, coalition in pairs(env.mission.coalition) do
						-- if _coalition == camp.player.side then
							for Ncountry, _country in pairs(coalition.country) do	
								if _country.plane then
									for Ngroup, _group in pairs(_country.plane.group) do
										if _group.groupId and _group.groupId == groupMission.id_ then 				
											
											rtbGroup.name = _group.name

											--Split
											for key, value in ipairs(_group.route.points) do						
												if value.name == 'Split' then
													rtbGroup.to = key 
													rtbGroup.from = key - 1
												end				
											end

											if rtbGroup.to == 0 then
												for key, value in ipairs(_group.route.points) do
													if value.type == 'Land' then
														rtbGroup.to = key 
														rtbGroup.from = key - 1
													end					
												end
											end
																
											breaktab = true
											break
										end
									end
								end
								if breaktab then break end
							end
						-- end
						if breaktab then break end
					end

					env.info( "DCE_Bingo DD        rtbGroup from "..tostring( rtbGroup.from).." to "..tostring( rtbGroup.to))

					if rtbGroup.to ~= 0 then
						local switchtask = {
								id = "SwitchWaypoint", 
									params = {
										goToWaypointIndex = rtbGroup.to,
										fromWaypointIndex = rtbGroup.from
								}
							}
					
						cntrl:setCommand(switchtask)

						env.info( "DCE_Bingo EE        goToWaypointIndex "..tostring(unitName).." "..callSign.." goToWaypointIndex "..tostring(rtbGroup.to) )
						_affiche(switchtask, "switchtask function bingo()")
					end

				-- end
			
			end
		end

		if tabJockerPlane[gpGid] and not tabJockerPlane[gpGid][callSign] then												-- si le callSign a deja dit qu'il etait Bingo, on l'oublie
			if Unit.getFuel(unit) <=  0.33 then																			-- Sur F14, 4000lbs/16000lbs = 0.25%
				trigger.action.outTextForGroup(gpGid, callSign .." Jocker Fuel", 15 , true)
				env.info( " Unit.getFuel(unit)  "..callSign.." humainUnit? "..tostring(humainUnit) )		
				tabJockerPlane[gpGid][callSign] = true																	-- la callSign � d�ja indiqu� qu'il �tait Bingo			
			end 
		end
	end

end


LLtool = {}

LLtool.LLstrings = function(pos) -- pos is a Vec3

	local LLposN, LLposE = coord.LOtoLL(pos)
	local LLposfixN, LLposdegN = math.modf(LLposN)
	LLposdegN = LLposdegN * 60
	local LLposdegN2, LLposdegN3 = math.modf(LLposdegN)
	LLposdegN3 = LLposdegN3 * 1000

	local LLposfixE, LLposdegE = math.modf(LLposE)
	LLposdegE = LLposdegE * 60
	local LLposdegE2, LLposdegE3 = math.modf(LLposdegE)
	LLposdegE3 = LLposdegE3 * 1000

	local LLposNstring = string.format('%+.2i %.2i %.3d', LLposfixN, LLposdegN2, LLposdegN3)
	local LLposEstring = string.format('%+.3i %.2i %.3d', LLposfixE, LLposdegE2, LLposdegE3)
	
	return LLposNstring, LLposEstring
end


	--************* AFAC PART ****************************************
function AFAC_com(arg)
	local AFAC_Name = arg[1]
	local gpGid = arg[2]
	local radioOn = arg[3]

	if radioOn == true then
		AFAC_available[AFAC_Name]["gpGid"] = gpGid
		trigger.action.outTextForGroup(gpGid,"AFAC radio On, waiting ...", 15, false)	
		_affiche(AFAC_available, "AFAC_available radioOn")
	elseif radioOn == false then
		if AFAC_available[AFAC_Name]["gpGid"] and AFAC_available[AFAC_Name]["gpGid"] == gpGid  then
			AFAC_available[AFAC_Name]["gpGid"] = nil
		end
		trigger.action.outTextForGroup(gpGid,"AFAC radio Off", 15, false)
		_affiche(AFAC_available, "AFAC_available radioOff")
	end


end

function AFAC_F10(playerGroup)
			
	local gpGid = playerGroup:getID()
	missionCommands.removeItemForGroup(gpGid, {"AFAC"})

	-- AFAC_available[FlightName] = nil
	if AFAC_available then
		for AFAC_Name, AFAC in pairs(AFAC_available) do
			if AFAC_Name and type(AFAC_Name) == "string" then
				menuAFAC = missionCommands.addSubMenuForGroup(gpGid, "AFAC")
				break
			end
		end


		for AFAC_Name, AFAC in pairs(AFAC_available) do
			if AFAC_Name and type(AFAC_Name) == "string" then
				missionCommands.addCommandForGroup(gpGid, "AFAC radio On ", menuAFAC, AFAC_com, {AFAC_Name, gpGid, true}  )
				missionCommands.addCommandForGroup(gpGid, "AFAC radio Off ", menuAFAC, AFAC_com, {AFAC_Name, gpGid, false}  )

				--table missionCommands.addCommandForGroup(number groupId , string name , table/nil path , function functionToRun , any anyArguement)
				--      missionCommands.addCommandForGroup(gpGid, txt, ejctedPilRadioON, activateRadioBeacon, {gpGid, ejectPil}  )
			end
		end

	end

	
end

	--************* SAR ejectedPilot PART ****************************************
function SAR_F10(arg)
	local gpGid = arg[1]
	local playerGroup = arg[2]
	-- local gpGid = playerGroup:getID()

	if not Group.isExist(playerGroup) then
		return
	end

	local playerUnits = playerGroup:getUnits()
	local playerUnit = playerUnits[1]
	local playerPos = playerUnit:getPoint()

	local playerCoal = playerUnit:getCoalition()

	local listEjectPil = {}

	-- missionCommands.addCommandForGroup(gid, "SAR", nil, SAR_F10, Group)
	-- local subR_SAR = missionCommands.addSubMenuForGroup(gpGid, "SAR", nil)

	missionCommands.removeItemForGroup(gpGid, {"SAR"})
	missionCommands.removeItemForGroup(gpGid, {"Activate beacon radios", "SAR"})
	missionCommands.removeItemForGroup(gpGid, {"Turns off beacon radios", "SAR"})

	missionCommands.addSubMenuForGroup(gpGid, "SAR")

	local ejctedPilRadioON = missionCommands.addSubMenuForGroup(gpGid, "Activate beacon radios", {"SAR"})
	local ejctedPilRadioOFF = missionCommands.addSubMenuForGroup(gpGid, "Turns off beacon radios", {"SAR"})

	if camp.SAR and camp.SAR.pilotEjected then
		
		for pilotN, ejectPilot in ipairs(camp.SAR.pilotEjected) do
			
			local pilEjectObj = Unit.getByName(ejectPilot.name)	

			if not ejectPilot.embarked and ejectPilot.side == coalitionIdNumeric[playerCoal] and pilEjectObj:isExist()  then 
				local pilEjectPos = pilEjectObj:getPoint()
				local distance = math.floor(math.sqrt(math.pow(pilEjectPos.x - playerPos.x, 2) + math.pow(pilEjectPos.z - playerPos.z, 2)))
				distance = math.ceil(distance / 1000)

				local tabTemp = {
					name = ejectPilot.name,
					distance = distance,
					position = pilEjectPos,
					MGRS_Chute_10KM = ejectPilot.MGRS_Chute_10KM,
					side = ejectPilot.side,
				}
				table.insert(listEjectPil, tabTemp)

			end
		end
	end

	if listEjectPil and #listEjectPil >=1 then
		table.sort(listEjectPil, function(a,b) return a.distance > b.distance  end)

		for n , ejectPil in ipairs(listEjectPil) do 

			local txt = "..."
			if ejectPil.MGRS_Chute_10KM then
				txt = ejectPil.distance.." Km. "..ejectPil.MGRS_Chute_10KM.." "..txt
			else
				txt = ejectPil.distance.." Km. Activates radio beacon "..ejectPil.name
			end

			-- missionCommands.addCommandForGroup(gpGid, txt, {"Activate beacon radios"}, activateRadioBeacon, {gpGid, ejectPil}  )

			missionCommands.addCommandForGroup(gpGid, txt, ejctedPilRadioON, activateRadioBeacon, {gpGid, ejectPil}  )

		end
	end

	--TODO, A REMETTRE
	-- return timer.getTime() + 1
end


function activateRadioBeacon(arguments)

	local gpGid = arguments[1]
	local ejectedPilot = arguments[2]

	local pilEjectObj = Unit.getByName(ejectedPilot.name)

	if pilEjectObj and camp.ejectedPilotFrequency and camp.ejectedPilotFrequency[ejectedPilot.side] then

		env.info( "AddCRF10:activateRadioBeacon  pilEjectObj:isExist "..tostring(pilEjectObj:isExist()))

		if not ejectedPilot.embarked  and pilEjectObj:isExist()  then 
			local pilEjectPos = pilEjectObj:getPoint()

			env.info( "AddCRF10:activateRadioBeacon  pilEjectPos.y "..tostring(pilEjectPos.y))

			trigger.action.radioTransmission('l10n/DEFAULT/beacon.ogg', ejectedPilot.position, 0, true, camp.ejectedPilotFrequency[ejectedPilot.side].radioBeacon, 1, 'radioBeacon_'..ejectedPilot.name)

			local freqShow = camp.ejectedPilotFrequency[ejectedPilot.side].radioBeacon / 1000000
			trigger.action.outTextForGroup(gpGid, "activate RadioBeacon on : "..freqShow, 45 , true)
		end
	else
		trigger.action.outTextForGroup(gpGid, "Error, no frequency  ", 15 , true)
		env.info( "Error, no frequency  ")
	end
end




function BullsEye(PlayerGroup)

	-- ['coalition'] = {
			-- ['blue'] = {
				-- ['bullseye'] = {
					-- ['y'] = 635639.37385346,
					-- ['x'] = -317948.32727306,
				-- },
	local gpGid = PlayerGroup:getID()
	local PlayerUnits = PlayerGroup:getUnits()
	local PlayerUnit = PlayerUnits[1]
	
	local Coalition = PlayerUnit:getCoalition()
	
	sideT = {
		[0] = "neutral",
		[1] = "red",
		[2] = "blue"
		}
	
	local bullsEye_pos = {
			x = env.mission.coalition[sideT[Coalition]].bullseye.x,
			y = 0,
			z = env.mission.coalition[sideT[Coalition]].bullseye.y
		}

	LLposNstring, LLposEstring = LLtool.LLstrings(bullsEye_pos)    

	trigger.action.outTextForGroup(gpGid, "BullsEye: "..'N ' .. LLposNstring .. '   E ' .. LLposEstring, 45 , true)

end

function FctRtbGroup(rtbGroup)

	trigger.action.outText("RTB "..tostring(rtbGroup.name), 5)	--FOR DEBUG
	
	local gp = Group.getByName(rtbGroup.name) 

	local rtbCtr = Group.getController(gp)


	local switchtask = {
			id = "SwitchWaypoint", 
				params = {
					goToWaypointIndex = rtbGroup.to,
					fromWaypointIndex = rtbGroup.from
			}
		}

	rtbCtr:setCommand(switchtask)
	
end



function RtbPack(PlayerGroup)

	for _coalition, coalition in pairs(env.mission.coalition) do
		if _coalition == camp.player.side then
			for Ncountry, _country in pairs(coalition.country) do	
				if _country.plane then
					for Ngroup, _group in pairs(_country.plane.group) do
						if string.find(_group.name,"Pack "..camp.player.pack_n) then 				
							
							local rtbGroup = {
									name = "",
									from = 0,
									to = 0
								}
				
				
							rtbGroup.name = _group.name
							
							if string.find(_group.name,"Escort") then
								local function Execute()
									local wingman = _group:getUnits()								--get list of units from attacking flights
									for n = 1, #wingman do											--iterate through wingmen in flight
										local cntrl = wingman[n]:getController()					--get controller of individual aircraft in flight
										cntrl:resetTask()											--reset task (wingman will rejoin with leader)
									end
								end
								timer.scheduleFunction(Execute, nil, timer.getTime() + 1)	
							end
							
							for key, value in ipairs(_group.route.points) do						
								if value.type == 'Land' then
									rtbGroup.to = key 
									rtbGroup.from = key - 1
								end

							end
		                      				
							if rtbGroup.name and rtbGroup.to ~= 0 then
								FctRtbGroup(rtbGroup)
							end
							
						end
					end
				end
			end
		end
	end
end


function RtbStrikePack(PlayerGroup)

	for _coalition, coalition in pairs(env.mission.coalition) do
		if _coalition == camp.player.side then
			for Ncountry, _country in pairs(coalition.country) do	
				if _country.plane then
					for Ngroup, _group in pairs(_country.plane.group) do
						if string.find(_group.name,"Pack "..camp.player.pack_n) then 				
							
							local rtbGroup = {
									name = "",
									from = 0,
									to = 0
								}
				
				
							rtbGroup.name = _group.name
							
							if string.find(_group.name,"Strike") then 				
							
								for key, value in ipairs(_group.route.points) do						
									if value.type == 'Land' then
										rtbGroup.to = key  
										rtbGroup.from = key -1 
									end

								end
						
								if rtbGroup.name and rtbGroup.to ~= 0 then
									FctRtbGroup(rtbGroup)
								end
							
							end
						end
					end
				end
			end
		end
	end
end


function RtbSEADPack(PlayerGroup)

	for _coalition, coalition in pairs(env.mission.coalition) do
		if _coalition == camp.player.side then
			for Ncountry, _country in pairs(coalition.country) do	
				if _country.plane then
					for Ngroup, _group in pairs(_country.plane.group) do
						if string.find(_group.name,"Pack "..camp.player.pack_n) then 				
							
							local rtbGroup = {
									name = "",
									from = 0,
									to = 0
								}
				
				
							rtbGroup.name = _group.name
							
							if string.find(_group.name,"SEAD") then 				
							
								for key, value in ipairs(_group.route.points) do						
									if value.type == 'Land' then
										rtbGroup.to = key  
										rtbGroup.from = key -1 
									end

								end
						
								if rtbGroup.name and rtbGroup.to ~= 0 then
									FctRtbGroup(rtbGroup)
								end
							
							end
						end
					end
				end
			end
		end
	end
end


function ReFueling(PlayerGroup)
	
	local player = {
		["point"] = {}
	}

	local tanker = {
		["point"] = {},
		["name"] = "",
		["distance"] = 0, 
		["gpName"] = ""
	}
	
	local PlayerUnits = PlayerGroup:getUnits()
	local PlayerUnit = PlayerUnits[1]	
	local uid = PlayerUnit:getID()
	
	-- fichier miz:
		-- plan haut, droite, alti : x/y/z
	-- vue F10 et vector3d:
		-- plan haut, droite, alti : x/z/y
		
	local PtempPoint = PlayerUnit:getPoint()											
			player.point.x = PtempPoint.x
			player.point.y = PtempPoint.z
			player.point.z = PtempPoint.y
	local Coalition = PlayerUnit:getCoalition()
	local groups = coalition.getGroups(Coalition, Group.Category.AIRPLANE)
	local speed = PlayerUnit:getVelocity()
	player.speed = math.sqrt(speed.x^2 + speed.y^2 + speed.z^2)
	-- local groups = coalition.getGroups(coalition.side.BLUE, Group.Category.AIRPLANE)
	local selected_distance = 99999999
	
	for i, gp in pairs(groups) do		
		local gpName = Group.getName(gp)		
		if   string.find(gpName,"Refueling") then 
			local units = gp:getUnits()
			local _unit = units[1]
			local fuel = _unit:getFuel()
			local callsign = _unit:getCallsign()
			local TankerTypeName = _unit:getTypeName()
			local t = {
						["point"] = {}
						}
						
			local TtempPoint = _unit:getPoint()
					t.point.x = TtempPoint.x
					t.point.y = TtempPoint.z
					t.point.z = TtempPoint.y
					
			local description = _unit:getDesc()	
	
			if (description.attributes.Refuelable or description.attributes.Tankers ) and _unit:isActive() then
			-- if _unit:getTypeName() == "S-3B Tanker" and _unit:isActive() then			
			-- if _unit:getTypeName() == "S-3B Tanker"  and t.point.z > 100 and _unit:isActive() then			
				
				local Tdistance = math.sqrt(math.pow(t.point.x - player.point.x, 2) + math.pow(t.point.y - player.point.y, 2))		--distance between tanker and player
				if Tdistance < selected_distance then
					tanker.point = t.point
					tanker.TypeName = TankerTypeName
					tanker.distance = Tdistance
					tanker.gpName = tostring(gpName)
					tanker.ctr = Group.getController(gp)
					tanker.callsign = callsign
					tanker._unit = _unit
					tanker.Desc = _unit:getDesc()
					selected_distance =  Tdistance					
				end
			end
		end
	end

	local heading  = GetHeading(tanker.point, player.point)		--return heading between two vector2 points
	local dist = tanker.distance / 2
	local interception_pos = GetOffsetPoint(tanker.point, heading, dist)		--function to return a new point offset from an initial point
	local interception_alt = player.point.z 
	local pattern_alt = player.point.z 	
	local pattern_speed = player.speed
	
	if interception_alt < 1000 and dist > 50000 then
		interception_alt = 3000
	elseif interception_alt > 6100  then										-- alti max:6100
		interception_alt = 6100
		pattern_alt = 6100
	end	
	
	if pattern_speed < 130  then
		pattern_speed = 130
	elseif pattern_speed > 200  then											-- vi max:6100
		pattern_speed = 200
	end	
	
	local infoSpeed = math.floor(pattern_speed / 0.51444444444)					-- m/s to Kts
	local infoAlti = math.floor((pattern_alt * 3.2808398950131 )/100)*100		-- m to ft	
	local intercept_pos = {
					x = interception_pos.x,
					y = pattern_alt,
					z = interception_pos.y
					}
					
	local intercept_LL =  coord.LOtoLL(intercept_pos)
	
	LLposNstring, LLposEstring = LLtool.LLstrings(intercept_pos)
	trigger.action.outText(tanker.callsign.." "..tanker.gpName.." Rdv: "..'N ' .. LLposNstring .. '   E ' .. LLposEstring.." Alt: "..infoAlti.." Speed "..infoSpeed, 20)	
	
		local Mission = {														--define mission for interceptor group
			id = 'Mission', 
			params = {
				route = {
					["points"] = {
						[1] = {
							["alt"] = interception_alt,
							["type"] = "Turning Point",
							["action"] = "Turning Point",
							["alt_type"] = "BARO",
							["formation_template"] = "",
							["y"] = interception_pos.y ,
							["x"] = interception_pos.x ,
							["speed"] = 200,
							["ETA_locked"] = false,
							["task"] = {
								["id"] = "ComboTask",
								["params"] = 
								{
									["tasks"] = 
									{
									
										[1] = 
										{
											["number"] = 1,
											["auto"] = false,
											["id"] = "Tanker",
											["enabled"] = true,
											["params"] = 
											{
											}, -- end of ["params"]
										}, -- end of [1]
										[2] = 
										{
											["number"] = 2,
											["auto"] = false,
											["id"] = "ControlledTask",
											["enabled"] = true,
											["params"] = 
											{
												["task"] = 
												{
													["id"] = "Orbit",
													["params"] = 
													{
														["altitude"] = pattern_alt,
														["pattern"] = "Circle",
														["speed"] = pattern_speed,
														["speedEdited"] = true,
													}, -- end of ["params"]
												}, -- end of ["task"]
												["stopCondition"] = 
												{
													["duration"] = 600,
												}, -- end of ["stopCondition"]
											}, -- end of ["params"]
										}, -- end of [2]
									}, -- end of ["tasks"]
								}, -- end of ["params"]
							},
							["speed_locked"] = true,
						},
						[2] = {
							["alt"] = tanker.point.z,
							["type"] = "Turning Point",
							["action"] = "Turning Point",
							["alt_type"] = "BARO",
							["formation_template"] = "",
							-- ["ETA"] = 0,
							["y"] = tanker.point.y,
							["x"] = tanker.point.x,
							["speed"] = 180,
							["ETA_locked"] = false,
							["task"] = {
								["id"] = "ComboTask",
								["params"] = {
									["tasks"] = {
									},
								},
							},
							["speed_locked"] = true,
						},
					},
				}
			}
		}
	
		Controller.setTask(tanker.ctr, Mission)																			--activate task with mission for interceptor group							
end

function RequestCAP(PlayerGroup)
	-- modification M36	Help CAP 
	local player = {
		["point"] = {}
	}

	local CAP = {
		["point"] = {},
		["name"] = "",
		["distance"] = 0, 
		["gpName"] = ""
	}
	
	local PlayerUnits = PlayerGroup:getUnits()
	local PlayerUnit = PlayerUnits[1]	
	local uid = PlayerUnit:getID()
	
	-- fichier miz:
		-- plan haut, droite, alti : x/y/z
	-- vue F10 et vector3d:
		-- plan haut, droite, alti : x/z/y
		
	local PtempPoint = PlayerUnit:getPoint()											
			player.point.x = PtempPoint.x
			player.point.y = PtempPoint.z
			player.point.z = PtempPoint.y			
			
	local Coalition = PlayerUnit:getCoalition()
	local groups = coalition.getGroups(Coalition, Group.Category.AIRPLANE)
	local speed = PlayerUnit:getVelocity()
	player.speed = math.sqrt(speed.x^2 + speed.y^2 + speed.z^2)
	
	-- local groups = coalition.getGroups(coalition.side.BLUE, Group.Category.AIRPLANE)
	local selected_distance = 99999999
	
	for i, gp in pairs(groups) do
		
		local gpName = Group.getName(gp)
		
		if   string.find(gpName,"CAP") then 
			local units = gp:getUnits()
			local _unit = units[1]
			local fuel = _unit:getFuel()
			local callsign = _unit:getCallsign()
			local TankerTypeName = _unit:getTypeName()
			local t = {
						["point"] = {}
						}
						
			local TtempPoint = _unit:getPoint()
					t.point.x = TtempPoint.x
					t.point.y = TtempPoint.z
					t.point.z = TtempPoint.y
	
			if  _unit:isActive() then	
			-- if _unit:getTypeName() == "S-3B Tanker"  and t.point.z > 100 and _unit:isActive() then			
				
				local Tdistance = math.sqrt(math.pow(t.point.x - player.point.x, 2) + math.pow(t.point.y - player.point.y, 2))		--distance between tanker and player

				if Tdistance < selected_distance then

					CAP.point = t.point
					CAP.TypeName = TankerTypeName
					CAP.distance = Tdistance
					CAP.gpName = tostring(gpName)
					CAP.ctr = Group.getController(gp)
					CAP.callsign = callsign
					CAP._unit = _unit
					CAP.Desc = _unit:getDesc()
					selected_distance =  Tdistance
					
				end
			end
		end
	end
	--[[	
		local  gpGid = Group.getID(gp)
		
		for _coalition, coalition in pairs(env.mission.coalition) do
			if _coalition == camp.player.side then
				for Ncountry, _country in pairs(coalition.country) do	
					if _country.plane then
						for Ngroup, _group in pairs(_country.plane.group) do
							if _group.groupId == gpGid then 				
								
								frequencyCAP = _group.frequency	
									
							end
						end
					end
				end
			end
		end
	]]

	--[[
	export in low tick interval to Ikarus
	Example from A-10C
	Get Radio Frequencies
	get data from device
	local lUHFRadio = GetDevice(54)
	ExportScript.Tools.SendData("ExportID", "Format")
	ExportScript.Tools.SendData(2000, string.format("%7.3f", lUHFRadio:get frequency()/1000000)) <- special function for get frequency data
	]]


	local heading  = GetHeading(CAP.point, player.point)					--return heading between two vector2 points
	local dist = CAP.distance / 1.5											-- approche le CAP 
	
	CAP.velocity = CAP._unit:getVelocity() 
	CAP.speed = math.sqrt(CAP.velocity.x^2 + CAP.velocity.y^2 + CAP.velocity.z^2)
	
	local interception_pos = GetOffsetPoint(CAP.point, heading, dist)		--function to return a new point offset from an initial point

	local interception_alt = player.point.z 
	local pattern_speed 													-- ex = player.speed
	
	if interception_alt < 3000 and dist > 50000 then
		interception_alt = 7600
	elseif interception_alt > 6100  then										-- alti max:6100
		interception_alt = 7600		
	end	

	trigger.action.outText(CAP.callsign.." "..CAP.gpName, 20)
	
	
		local Mission = {														--define mission for interceptor group
			id = 'Mission', 
			params = {
				route = {
					["points"] = {
						
						[1] = {
							['alt'] = interception_alt,
							['briefing_name'] = 'Station',
							['action'] = 'Turning Point',
							['alt_type'] = 'BARO',
							-- ['properties'] = {
							-- 	['vnav'] = 1,
							-- 	['scale'] = 0,
							-- 	['angle'] = 0,
							-- 	['vangle'] = 0,
							-- 	['steer'] = 2,
							-- },
							['speed_locked'] = true,
							['speed'] = 290,									-- vitesse du son  295 a 20000m
							['ETA'] = 1,
							["y"] = interception_pos.y ,
							["x"] = interception_pos.x ,
							['formation_template'] = '',
							['name'] = 'Station',
							['ETA_locked'] = false,
							['task'] = {
								['id'] = 'ComboTask',
								['params'] = {
									['tasks'] = {
										[1] = {
											['enabled'] = true,
											['auto'] = false,
											['id'] = 'ControlledTask',
											['number'] = 1,
											['params'] = {
												['task'] = {
													['id'] = 'EngageTargetsInZone',
													['params'] = {
														['targetTypes'] = {
															[1] = 'Air',
															[2] = 'Cruise missiles',
														},
														['x'] = player.point.x,
														['value'] = 'Air;Cruise missiles;',
														['priority'] = 0,
														['y'] = player.point.y,
														['zoneRadius'] = 111000,
													},
												},
												['stopCondition'] = {
													['lastWaypoint'] = 3,
												},
											},
										},
										[2] = {
											['enabled'] = true,
											['auto'] = false,
											['id'] = 'ControlledTask',
											['number'] = 2,
											['params'] = {
												['task'] = {
													['id'] = 'Orbit',
													['params'] = {
														['altitude'] = CAP.point.z,
														['pattern'] = 'Race-Track',
														['speed'] = CAP.speed,
													},
												},
												['stopCondition'] = {
													['time'] = 1000,
												},
											},
										},
									},
								},
							},
							['type'] = 'Turning Point',
						},
					},
				}
			}
		}--local Mission = {	
	
	
		Controller.setTask(CAP.ctr, Mission)																			--activate task with mission for interceptor group
		
		trigger.action.outText("ADD_CR "..CAP.callsign.." "..CAP.gpName, 60)
end


function getOut(gid)
	env.info( "DCE_getOut A function getOut(gid) ")
	
	getOutGDFM(gid)
	
end


function addFuncs(gid, Group)	
	if gid and Group then		
		-- -- supprime les anciens items de la commande F10
		-- missionCommands.removeItemForGroup(gid, {"Urgent_Refueling"})
		-- missionCommands.removeItemForGroup(gid, {"Urgent_RequestCAP"})
		-- missionCommands.removeItemForGroup(gid, {"BullsEye_LongLat"})	
		-- missionCommands.removeItemForGroup(gid, {"Package_All_RTB"})
		-- missionCommands.removeItemForGroup(gid, {"Package_Strike_RTB"})
		-- missionCommands.removeItemForGroup(gid, {"Package_SEAD_RTB"})		
		-- -- missionCommands.removeItemForGroup(gid, {"RemovePlane"})
		-- missionCommands.removeItemForGroup(gid, {"CarrierIntoWind"})		

		-- missionCommands.addCommandForGroup(gid, "Urgent_Refueling", nil, ReFueling, Group)
		-- missionCommands.addCommandForGroup(gid, "Urgent_RequestCAP", nil, RequestCAP, Group)
		-- missionCommands.addCommandForGroup(gid, "BullsEye_LongLat", nil, BullsEye, Group)
		-- missionCommands.addCommandForGroup(gid, "Package_All_RTB", nil, RtbPack, Group)
		-- missionCommands.addCommandForGroup(gid, "Package_Strike_RTB", nil, RtbStrikePack, Group)
		-- missionCommands.addCommandForGroup(gid, "Package_SEAD_RTB", nil, RtbSEADPack, Group)		
		-- -- missionCommands.addCommandForGroup(gid, "RemovePlane", nil, RemovePlane, Group)


		-- supprime les anciens items de la commande F10
		missionCommands.removeItemForGroup(gid, {"BullsEye_LongLat"})		

		missionCommands.removeItemForGroup(gid, {"CarrierIntoWind"})		
		missionCommands.removeItemForGroup(gid, {"Urgent request"})
		
		
		local subR_A = missionCommands.addSubMenuForGroup(gid, "Urgent request", nil)	
		
		missionCommands.addCommandForGroup(gid, "Urgent_Refueling", subR_A, ReFueling, Group )		
		missionCommands.addCommandForGroup(gid, "Urgent_RequestCAP", subR_A, RequestCAP, Group)
		missionCommands.addCommandForGroup(gid, "Package_All_RTB", subR_A, RtbPack, Group)
		missionCommands.addCommandForGroup(gid, "Package_Strike_RTB", subR_A, RtbStrikePack, Group)
		missionCommands.addCommandForGroup(gid, "Package_SEAD_RTB", subR_A, RtbSEADPack, Group)		
		missionCommands.addCommandForGroup(gid, "Get out of the cockpit", subR_A, getOut, gid)	

		missionCommands.addCommandForGroup(gid, "BullsEye_LongLat", nil, BullsEye, Group)


		if camp.SC_CarrierIntoWind == "man" then																					
			missionCommands.removeItemForGroup(gid, {"CarrierIntoWind"})
			local subR = missionCommands.addSubMenuForGroup(gid, "CarrierIntoWind", nil)		
			for coalition_name,coal in pairs(env.mission.coalition) do
				for country_n,country in ipairs(coal.country) do
					if country.ship then
						for group_n,group in ipairs(country.ship.group) do			
							local groupCarrier = Group.getByName(group.name)													--get carrier group
							if groupCarrier then																				--group exists
								local carrier = groupCarrier:getUnit(1)															--get group leader (assumed to be the carrier)								
								local Desc = carrier:getDesc()					
								if Desc.attributes.AircraftCarrier or Desc.attributes["Aircraft Carriers"] then 
									local carrierPos = carrier:getPoint()														--get position of carrier
									local GroupName = group.name
									missionCommands.addCommandForGroup(gid, group.name.." Into Wind 30mn", subR, TurnIntoWind, {GroupName, nil, nil, 30} )	-- modification M36.d	(d: add timer) MenuRadio request manual TurnIntoWind
									missionCommands.addCommandForGroup(gid, group.name.." Into Wind 60mn", subR, TurnIntoWind, {GroupName, nil, nil, 60} )									
									missionCommands.addCommandForGroup(gid, group.name.." Resume Route", subR, ResumeRoute, {group.name, nil} )
								end	
							end
						end
					end
				end
			end
		end

		-- SAR_F10(Group)
		timer.scheduleFunction(SAR_F10, {gid, Group}, timer.getTime() + 2)

		-- AFAC_F10(Group)
		timer.scheduleFunction(AFAC_F10, Group, timer.getTime() + 2)	


		-- The solution is to use env.mission.coalition where you find all object informations even groupId
		-- https://forums.eagle.ru/showthread.php?t=147792&page=15
		
		 -- commandDB['RUR'] = missionCommands.addCommandForGroup(gid,"UrgentRefueling", nil, ReFueling, Group)
		 -- commandDB['speed'] = missionCommands.addCommandForGroup(gid,"Testing", nil, Test, Group)
		 -- commandDB['RTB'] = missionCommands.addCommandForGroup(gid,"Package_RTB", nil, RtbPack, Group)
	end
end


EventHandler2 = {}
function EventHandler2:onEvent(event)
	local idLabel = "inc"
	env.info("DCE_EventHandler2 PASSE 01 event.id "..tostring(event.id))
	
	if event and event.id and info_event and info_event[tonumber(event.id)] then
		idLabel = tostring(info_event[tonumber(event.id)])
		env.info("DCE_EventHandler2 PASSE 02 event.id "..tostring(event.id).." " ..idLabel)
	end

	if event.initiator then
		env.info("DCE_EventHandler2 PASSE 03 event.id "..tostring(event.id).." initiator.id_: "..tostring(event.initiator.id_))
	end
	-- _affiche(event, "DCE_EventHandler2  PASSE 0b event ")

	if event.id == world.event.S_EVENT_BIRTH then
		env.info("DCE_EventHandler2 PASSE 001 BIRTH")	

		if event.initiator and Object.getCategory(event.initiator) ~= Object.Category.STATIC and event.initiator:getPlayerName() then

			local Gname = event.initiator:getPlayerName()
			local Uid = event.initiator:getID()
			local Group = event.initiator:getGroup()
			local gpGid = event.initiator:getGroup():getID()

			if gpGid and Group and Gname  then 
				
				-- trigger.action.outText("RR Passe S_EVENT_BIRTH--"..tostring(Gname).." "..gpGid, 15)	--FOR DEBUG
				
				addFuncs(gpGid, Group)
			end
		end
	elseif not event.place then
		if event.subPlace then 
			env.info("DCE_EventHandler2 PASSE 002 subPlace")																								--debug ET01	
			
			_affiche(event, "event event.subPlace ")
			if event.initiator and event.initiator:getPlayerName() then
				local Gname = event.initiator:getPlayerName()
				local Uid = event.initiator:getID()
				local Group = event.initiator:getGroup()		
				
				if Group then 			
					-- local gpGid = event.initiator:getGroup():getID()		--1299: attempt to index a nil value
					local gpGid =Group:getID()		--1300: attempt to index a nil value
					if gpGid  and Group and Gname then 			
						addFuncs(gpGid, Group)
					end
				end
			end

		elseif event.id == world.event.S_EVENT_LAND or event.id == world.event.S_EVENT_CRASH or event.id == world.event.S_EVENT_DETAILED_FAILURE or event.id == world.event.S_EVENT_AI_ABORT_MISSION
			or event.id == world.event.S_EVENT_POSTPONED_LAND or event.id == world.event.S_EVENT_EMERGENCY_LANDING then
			env.info("DCE_EventHandler2 PASSE 003 LAND or CRASH")	

			if event.initiator  then
				env.info( "DCE_groundDamagedFlyingMachine B getPlayerName detected ? ")

				local initDesc = event.initiator:getDesc()	
				_affiche(initDesc, "DCE_groundDamagedFlyingMachine initDesc")

				local initiatorPilotName = event.initiator:getPlayerName()
				local unitName = event.initiator:getName()
				local life = event.initiator:getLife()
				local init_life = event.initiator:getLife0()
				local lifePourcent = 100
				local isPlayer = false
				if init_life then
					lifePourcent = life/init_life*100
				end

				

				env.info( "DCE_groundDamagedFlyingMachine C1 initiatorPilotName "..tostring(initiatorPilotName).." lifePourcent: "..tostring(lifePourcent))
				env.info( "DCE_groundDamagedFlyingMachine C2 init_life "..tostring(init_life).." life: "..tostring(life))
				env.info( "DCE_groundDamagedFlyingMachine C3 event.initiator._id "..tostring(event.initiator._id))

				if initiatorPilotName and initiatorPilotName ~= "" then
					isPlayer = true
				end

				--TODO ajouter une proximité Base & Farp pour ne pas le faire dessus
				if lifePourcent < 100 then
					env.info( "DCE_groundDamagedFlyingMachine D detected ? event.initiator.id_ "..tostring(event.initiator.id_))

					local Group = event.initiator:getGroup()
					local gpGid = Group:getID()
					local categoryId = event.initiator:getDesc().category
					
					local eventData = {
						initiatorPilotName = initiatorPilotName,
						isPlayer = isPlayer,
						unitName = unitName,
						-- -- unitPlayer = Unit.getByName(unitName),
						-- unitGame = event.initiator,
						Uid = event.initiator:getID(),
						aircraftType = event.initiator:getTypeName(),
						lifePourcent = lifePourcent,
						crashPoint = event.initiator:getPoint(),
						unit = event.initiator,
						gpGid = gpGid,
						idLabel= idLabel,
						categoryId = categoryId,
					}
					
					-- if not groundDamagedFlyingMachine[gpGid] then groundDamagedFlyingMachine[gpGid] = {} end
					-- table.insert(groundDamagedFlyingMachine[gpGid], eventData)

					

					if not groundDamagedFlyingMachine[event.initiator.id_] then groundDamagedFlyingMachine[event.initiator.id_] = {} end
					table.insert(groundDamagedFlyingMachine[event.initiator.id_], eventData)

					-- local current_time = timer.getTime()
					-- if camp.debug then
					-- 	local logStr = "DamagedFM = " .. TableSerialization(groundDamagedFlyingMachine, 0)
					-- 	local grpnameClean = unitName:gsub('[%p%c%s]', '_')
					-- 	local logFile = io.open(path.."Debug\\"..event.initiator.id_.."_"..grpnameClean.."_".. "DamagedFM_"..current_time..".lua", "w")
					-- 	logFile:write(logStr)
					-- 	logFile:close()
					-- end

					-- local gpGid = event.initiator:getGroup():getID()

				end
			end
		end
	end
end

world.addEventHandler(EventHandler2)



function LoopPilot()
	
	local groups = coalition.getGroups(coalition.side.BLUE, Group.Category.AIRPLANE)
	
	for i, gp in pairs(groups) do
		-- local  gpName = Group.getName(gp)
		local  gpGid = Group.getID(gp)
		
		if gpGid  and gp then 
			bingo(gpGid, gp)
		end		
	end

	groups = coalition.getGroups(coalition.side.RED, Group.Category.AIRPLANE)
	
	for i, gp in pairs(groups) do
		-- local  gpName = Group.getName(gp)
		local  gpGid = Group.getID(gp)
		
		if gpGid  and gp then 
			bingo(gpGid, gp)
		end		
	end
			
	
	
	if camp.TableTransportPilotNames and ctld and ctld.alreadyInitialized and not TPN_alreadyAdded then 
		for n=1, #camp.TableTransportPilotNames do
			ctld.transportPilotNames[#ctld.transportPilotNames +1 ] = camp.TableTransportPilotNames[n]
		end
		
		env.info( "AdCR10 add  ctld.transportPilotNames ")
		
		TPN_alreadyAdded = true
	end
	
	return timer.getTime() + 15

end

timer.scheduleFunction(LoopPilot, nil, timer.getTime() + 15)	

timer.scheduleFunction(AirRetreat, nil, timer.getTime() + 5)


env.info( "AdCR10 load fin ")
  