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

local herding_area = wesnoth.require "ai/micro_ais/cas/ca_herding_f_herding_area.lua"

local function get_next_sheep(cfg)
    local sheep = AH.get_units_with_moves {
        side = wesnoth.current.side,
        { "and", cfg.filter_second }
    }
    return sheep[1]
end

local ca_herding_sheep_move = {}

function ca_herding_sheep_move:evaluation(ai, cfg)
   -- If nothing else is to be done, the sheep do a random move
    if get_next_sheep(cfg) then return cfg.ca_score end
    return 0
end

function ca_herding_sheep_move:execution(ai, cfg)
    -- We simply move the first sheep first, the order does not matter
    local sheep = get_next_sheep(cfg)

    local reach_map = AH.get_reachable_unocc(sheep)
    -- Exclude those that are next to a dog
    reach_map:iter( function(x, y, v)
        for xa, ya in H.adjacent_tiles(x, y) do
            local dog = wesnoth.get_unit(xa, ya)
            if dog and (wesnoth.match_unit(dog, cfg.filter)) then
                reach_map:remove(x, y)
            end
        end
    end)

    -- Choose one of the possible locations  at random (or the current location, if no move possible)
    local x, y = sheep.x, sheep.y
    if (reach_map:size() > 0) then
        x, y = AH.LS_random_hex(reach_map)
    end

    -- If this move remains within herding area or dogs have no moves left, or sheep doesn't move
    -- make it a full move, otherwise partial move
    local herding_area = herding_area(cfg)
    local dogs = AH.get_units_with_moves {
        side = wesnoth.current.side,
        { "and", cfg.filter }
    }
    if herding_area:get(x, y) or (not dogs[1]) or ((x == sheep.x) and (y == sheep.y)) then
        AH.movefull_stopunit(ai, sheep, x, y)
    else
        AH.checked_move(ai, sheep, x, y)
    end
end

return ca_herding_sheep_move
