--- Тип, отвечающий за выбор и фильтрацию подходящих тайлов как цели спелла
--- теория множеств my beloved?
--- @class SpellTargetQuery
local query = {}
query.__index = query

--- Проверяет координаты на соответствие внутреннему условию
--- @param caster Character
--- @param position Vec3
--- @return boolean
function query.test(caster, position)
    return true
end

--- Объединение
--- @param q SpellTargetQuery
function query:join(q)
    return setmetatable({
        test = function(caster, pos)
            return self.test(caster, pos) or q.test(caster, pos)
        end
    }, query)
end

--- Пересечение
--- @param q SpellTargetQuery
function query:intersect(q)
    return setmetatable({
        test = function(caster, pos)
            return self.test(caster, pos) and q.test(caster, pos)
        end
    }, query)
end

--- Исключение (не коммутативное, "те, что есть в query, но нет в q")
--- @param q SpellTargetQuery
function query:exclude(q)
    return setmetatable({
        test = function(caster, pos)
            return self.test(caster, pos) and not q.test(caster, pos)
        end
    }, query)
end

--- Находит все соответствующие условиям координаты тайлов и возвращает их в виде списка
--- @param caster Character
--- @return Vec3[]
function query:asSet(caster)
    --- @TODO: оптимизировать и брать не всю карту для выборки
    local res = {}
    for _, tile in pairs(Tree.level.tileGrid.__grid) do
        if self.test(caster, tile.position) then
            table.insert(res, tile.position)
        end
    end

    return res
end

--- @param test SpellTargetTest
local function new(test)
    return setmetatable({
        test = test
    }, query)
end

return new
