attack_mission.helpers = {}

--- picks one zone out of all available mission zones with predetermined logic
---
--- INFO: function will yield nil if no nonactive mission zones are available
--- @param TYPE string difficulty level. If nil all difficultys are allowed (should be present in name)
--- @return table | nil
function attack_mission.helpers.pickZone(TYPE)
    TYPE = type(TYPE) == "string" and TYPE or ""

    local zonepool = attack_mission.helpers.getUnusedAttackZones(TYPE)
    zonepool = util.misc.filter(zonepool, function(v, k) return v.name:lower():find(TYPE:lower()) ~= nil end)

    if zonepool == nil or #zonepool <= 0 then return nil end

    local zone = zonepool[math.random(1, #zonepool)]

    return zone
end

--- returns a table of all currently unused mission zones wich qualify as an attack zone
--- @return table
function attack_mission.helpers.getUnusedAttackZones()
    DIFF = type(DIFF) == "string" and DIFF or ""

    -- create a deep copy of the table (just to be safe)
    local zones = util.misc.deepCopy(util.trigger.getMissionZones())
    zones = util.misc.filter(zones, function(v, k) return not util.misc.find(attack_mission.active, v.name) end)

    return zones
end

--- checks if a type has a partner and if so adds all nessacary partners in a small radius to its original
--- @param typ string original type. (if it has partners it shall be located attack_mission.DATA.COLLECTION as a key)
--- @param pos table position of the original unit (used for relative spawn)
--- @param att table attributes for spawning a unit (currently unused)
--- @return table @contains all partner units + its original unit
function attack_mission.helpers.partnerCheck(typ, pos, att)
    if type(typ) ~= "string" then error(util.error.argErr(typ, "string", 1)) end
    if type(pos) ~= "table" then error(util.error.argErr(pos, "table", 2)) end
    att = att or {minDist = 20, maxDist = 50}

    -- if the unit has no partner units no further action is required
    if attack_mission.DATA.COLLECTION[typ] == nil then
        return { typ }, { pos } -- returning as table so we have consistent retun type
    end

    -- saving position of original object and making pointer to partner table (easy accesss)
    local typs, positions, partners = { typ }, { pos }, attack_mission.DATA.COLLECTION[typ]

    -- for every partner generate amount and location
    for partner, prob in pairs(partners) do
        -- random amount in range
        local amount = math.random(prob.min, prob.max)

        for i=1, amount do
            -- generate new position (randomized)
            local phi, r = math.random() * 2*math.pi, math.random(att.minDist, att.maxDist)
            local x, y = util.math.polToCar(phi, r)

            -- add to tables
            typs[#typs+1], positions[#positions+1] = partner, { x = pos.x + x, y = pos.y + y }
        end
    end

    return typs, positions
end

--- generates a types and a positions table (tuple) used for unit generation
--- @param zone table the zone used to retrieve information for position generation (see DCS trigger zone)
--- @param DIFF string difficulty of the unit selection (must coalate with DATA name)
--- @return string[], table[] @types, positions
function attack_mission.helpers.getTypPos(zone, DIFF)
    -- locate the difficulty table
    local D_TABLE = attack_mission.DATA[DIFF]

    -- generate amount of generated units out of max and min
    local amount = math.random(D_TABLE.COUNT.MIN, D_TABLE.COUNT.MAX)
    local typs, poss = {}, {}

    -- add all special units wich have to be present in a certain quanitity min and max
    for typ, amt in pairs(D_TABLE.DEFINITION.SPECIAL) do
        -- generate a random quanitity amount
        local c =  math.random(amt.min, amt.max)

        -- add this quanitity to the units
        for i=1, c do
            -- find a random spawn inside the zone
            local x, y = util.trigger.getRndInZone(zone)

            -- get all partner check if nessacary
            local t, p = attack_mission.helpers.partnerCheck(typ, {x = x, y = y}, amt.att)
            util.misc.append(typs, t)
            util.misc.append(poss, p)
        end
    end

    -- get the names of all possible main types (used for random index)
    local mainTypes = util.misc.getKeys(D_TABLE.DEFINITION.MAIN)

    -- generate main part of the attack_mission until it is full
    repeat
        -- random type and probability to spawn
        local typ, c = mainTypes[math.random(1, #mainTypes)], math.random()

        -- check if the probability meets condition or not and add unit if it meets
        if c <= D_TABLE.DEFINITION.MAIN[typ].prob then
            local x, y = util.trigger.getRndInZone(zone)

            local t, p = attack_mission.helpers.partnerCheck(typ, {x = x, y = y}, D_TABLE.DEFINITION.MAIN[typ].att)
            util.misc.append(typs, t)
            util.misc.append(poss, p)
        end
    until #typs >= amount

    return typs, poss
end