local anim8 = require "lib.utils.anim8"

--- @class SpriteBehavior : Behavior
--- @field animationTable table<string, table>
--- @field animationGrid table
--- @field state "idle"|"run"|"hurt"|"attack"
--- @field side 1|-1
local sprite = {}
sprite.__index = sprite
sprite.id = "sprite"
sprite.LEFT = -1
sprite.RIGHT = 1
--- Скорость между кадрами в анимации
sprite.ANIMATION_SPEED = 0.1

function sprite.new(spriteDir)
    local anim = setmetatable({}, sprite)
    anim.animationTable = {}
    anim.animationGrid = {}

    -- n: name; i: image
    for n, i in pairs(spriteDir) do
        local aGrid = anim8.newGrid(96, 64, i:getWidth(), i:getHeight())
        local tiles = '1-' .. math.ceil(i:getWidth() / 96)
        anim.animationGrid[n] = aGrid(tiles, 1)
    end

    anim.state = "idle"
    anim.side = sprite.RIGHT
    anim:loop("idle")
    return anim
end

function sprite:update(dt)
    local anim = self.animationTable[self.state] or self.animationTable["idle"] or nil

    if not anim then return end
    anim:update(dt)
end

function sprite:draw()
    if not self.animationTable[self.state] or not Tree.assets.files.sprites.character[self.state] then return end

    self.owner:try(Tree.behaviors.map,
        function(map)
            local ppm = Tree.level.camera.pixelsPerMeter
            local position = map.displayedPosition
            if Tree.level.selector.id == self.owner.id then
                local texW, texH = Tree.assets.files.sprites.character[self.state]:getWidth(),
                    Tree.assets.files.sprites.character[self.state]:getHeight()
                local shader = Tree.assets.files.shaders.outline
                shader:send("texSize", { texW, texH })
                shader:send("time", love.timer:getTime())
                love.graphics.setShader(shader)
            end

            self.animationTable[self.state]:draw(Tree.assets.files.sprites.character[self.state],
                position.x + 0.5,
                position.y + 0.5, nil, 1 / ppm * self.side, 1 / ppm, 38, 47)
            love.graphics.setColor(1, 1, 1)
            love.graphics.setShader()
        end
    )
end

--- @param node AnimationNode
function sprite:animate(state, node)
    if not self.animationGrid[state] then
        return print("[SpriteBehavior]: no animation for '" .. state .. "'")
    end
    self.animationTable[state] = anim8.newAnimation(self.animationGrid[state], self.ANIMATION_SPEED,
        function()
            self:loop("idle")
            node:finish()
        end)
    self.state = state
end

function sprite:loop(state)
    if not self.animationGrid[state] then
        return print("[SpriteBehavior]: no animation for '" .. state .. "'")
    end
    self.animationTable[state] = anim8.newAnimation(self.animationGrid[state], self.ANIMATION_SPEED)
    self.state = state
end

return sprite
