local H = wesnoth.require "lua/helper.lua"
local AH = wesnoth.require "ai/lua/ai_helper.lua"

local function get_enemies(cfg)
    local scatter_distance = cfg.scatter_distance or 3
    local enemies = wesnoth.get_units {
        { "filter_side", { { "enemy_of", { side = wesnoth.current.side } } } },
        { "filter_location",
            { radius = scatter_distance, { "filter", { side = wesnoth.current.side } } }
        }
    }
    return enemies
end

local function get_swarm_units(cfg)
    return AH.get_units_with_moves { side = wesnoth.current.side }
end

local ca_swarm_scatter = {}

function ca_swarm_scatter:evaluation(ai, cfg)
    if (not get_enemies(cfg)[1]) then return 0 end
    if (not get_swarm_units(cfg)[1]) then return 0 end
    return cfg.ca_score
end

function ca_swarm_scatter:execution(ai, cfg)
    local enemies = get_enemies(cfg)
    local units = get_swarm_units(cfg)
    local vision_distance = cfg.vision_distance or 12

    -- In this case we simply maximize the distance from all these close enemies
    -- but only for units that are within 'vision_distance' of one of those enemies
    for _,unit in ipairs(units) do
        local unit_enemies = {}
        for _,enemy in ipairs(enemies) do
            if (H.distance_between(unit.x, unit.y, enemy.x, enemy.y) <= vision_distance) then
                table.insert(unit_enemies, enemy)
            end
        end

        if unit_enemies[1] then
            local best_hex = AH.find_best_move(unit, function(x, y)
                local rating = 0
                for _,enemy in ipairs(unit_enemies) do
                    rating = rating + H.distance_between(x, y, enemy.x, enemy.y)
                end
                return rating
            end)

            AH.movefull_stopunit(ai, unit, best_hex)
        end
    end
end

return ca_swarm_scatter
