local utils = require "lib.utils.utils"
--- Пометровая сетка источников света, чтобы быстро искать ближайшие для некоторого объекта
--- @class LightGrid : Grid
--- @field __grid {string: [Id]}
local grid = setmetatable({}, require "lib.level.grid.base")
grid.__index = grid

--- Adds a character id to the grid
--- @private
--- @param id Id
function grid:add(id)
    local character = Tree.level.characters[id]
    if not character then return end

    local lightB = character:has(Tree.behaviors.light)
    if not lightB then return end

    local positioned = character:has(Tree.behaviors.positioned)
    if not positioned then return end

    local key = tostring(Vec3 { positioned.position.x, positioned.position.y }:floor())
    if not self.__grid[key] then self.__grid[key] = {} end
    table.insert(self.__grid[key], character.id)
end

--- fills the grid with the actual data
---
--- should be called as early as possible during every tick
function grid:reload()
    self:reset()
    utils.each(Tree.level.characters, function(c)
        self:add(c.id)
    end)
end

--- Возвращает все источники света, которые находятся в пределах круга с диаметром [distance] в [метрике Чебышёва](https://ru.wikipedia.org/wiki/Расстояние_Чебышёва)
--- @param position Vec3
--- @param distance integer
function grid:query(position, distance)
    --- @type Id[]
    local res = {}
    local topLeft = position:subtract(Vec3 { distance / 2, distance / 2 }):floor()
    for i = 0, distance, 1 do
        for j = 0, distance, 1 do
            --- @type Id[]?
            local lights = self:get(topLeft:add(Vec3 { i, j }))
            if lights then
                for _, lightChar in ipairs(lights) do
                    table.insert(res, lightChar)
                end
            end
        end
    end
    return res
end

--- Generates an empty grid
--- @return LightGrid
local function new()
    return setmetatable({
        __grid = {}
    }, grid)
end

return { new = new }
