--- @class Selector
--- @field id Id | nil
--- @field lastId Id | nil
--- @field locked boolean
local selector = {}
selector.__index = selector

local function new()
    return setmetatable({}, selector)
end

--- @param characterId integer | nil
function selector:select(characterId)
    self.id = characterId
    print("[Selector]:", characterId and "selected " .. characterId or "deselected")
end

function selector:update(dt)
    self.lastId = self.id
    if self.locked or not Tree.controls:isJustPressed("select") then return end

    local mousePosition = Tree.level.camera:toWorldPosition(Vec3 { love.mouse.getX(), love.mouse.getY() }):floor()

    if mousePosition.x >= Tree.level.size.x or mousePosition.y >= Tree.level.size.y or mousePosition.y < 0 or mousePosition.x < 0 then
        return
    end
    local selectedId = Tree.level.characterGrid:get(Vec3 { mousePosition.x, mousePosition.y })

    if not self.id then
        if selectedId ~= Tree.level.turnOrder.current and Tree.level.turnOrder.isTurnsEnabled then return end
        return self:select(selectedId)
    else
        local char = Tree.level.characters[self.id]

        char:try(Tree.behaviors.spellcaster, function(b)
            if not b.cast then
                if not selectedId then self:select(nil) end
                return
            end
            local task = b.cast:cast(char, mousePosition) -- в task функция, которая запускает анимацию спелла
            if not task then return end                   -- не получилось скастовать

            self:lock()
            b.state = "running"

            task(
                function(_)                                                          -- это коллбэк, который сработает по окончании анимации спелла
                    b:endCast()
                    if not char:has(Tree.behaviors.ai) then self:select(char.id) end -- выделяем персонажа обратно после того, как посмотрели на каст
                end
            )
        end)
    end
end

--- Disables the selector until [unlock] is called
function selector:lock()
    self.id = nil
    self.locked = true
end

--- Cancels the effect of [lock]
function selector:unlock()
    self.locked = false
end

--- If a character was selected during this tick, returns its Id
function selector:selected()
    if self.id and self.id ~= self.lastId then return self.id end
end

--- If a character was **de**selected during this tick, returns its Id
function selector:deselected()
    if not self.id and self.lastId then return self.lastId end
end

return {
    new = new
}
