local utils = require "lib.utils.utils"
local pQueue = require "lib.utils.priority_queue"
--- @class CharacterGrid : Grid
--- @field __grid {string: Id|nil}
--- @field yOrderQueue PriorityQueue<Character> очередь отрисовки сверху вниз
local grid = setmetatable({}, require "lib.level.grid.base")
grid.__index = grid

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

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

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

    local centerX, centerY = math.floor(positioned.position.x + 0.5),
        math.floor(positioned.position.y + 0.5)
    local sizeX, sizeY     = tiled.size.x, tiled.size.y

    for y = centerY, centerY + sizeY - 1 do
        for x = centerX, centerX + sizeX - 1 do
            self.__grid[tostring(Vec3 { x, y })] = character.id
        end
    end
end

--- @param a Character
--- @param b Character
local function drawCmp(a, b)
    --- @TODO: это захардкожено, надо разделить поведения
    return a:has(Tree.behaviors.positioned).position.y < b:has(Tree.behaviors.positioned).position.y
end

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

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

return { new = new }
