--- @class Render
--- @field textures table<string, love.Canvas>
local render = {
    textures = {}
}

function render:clear()
    local weather = Tree.level.weather
    local txs = self.textures
    love.graphics.setCanvas(txs.shadowLayer)
    love.graphics.clear()
    love.graphics.setCanvas(txs.spriteLayer)
    love.graphics.clear()
    love.graphics.setCanvas(txs.spriteLightLayer)
    love.graphics.clear(weather.skyLight.x, weather.skyLight.y, weather.skyLight.z)
    love.graphics.setCanvas(txs.floorLayer)
    love.graphics.clear()
    love.graphics.setCanvas(txs.lightLayer)
    love.graphics.clear(weather.skyLight.x, weather.skyLight.y, weather.skyLight.z)
    love.graphics.setCanvas(txs.overlayLayer)
    love.graphics.clear()
end

function render:free()
    for _, tx in pairs(self.textures) do
        tx:release()
    end
    self.textures = nil
end

--- TODO: это используется для блюра, должно кэшироваться и поддерживать ресайз

function render:applyBlur(input, radius)
    local blurShader = Tree.assets.files.shaders.blur

    -- Горизонтальный проход
    blurShader:send("direction", { 1.0, 0.0 })
    blurShader:send("radius", radius)

    self.textures.tmp1:renderTo(function()
        love.graphics.clear()
        love.graphics.setShader(blurShader)
        love.graphics.draw(input)
        love.graphics.setShader()
    end)

    -- Вертикальный проход
    self.textures.tmp2:renderTo(
        function()
            love.graphics.clear()
            love.graphics.setShader(blurShader)
            blurShader:send("direction", { 0.0, 1.0 })
            love.graphics.draw(self.textures.tmp1)
            love.graphics.setShader()
        end
    )
    return self.textures.tmp2
end

function render:draw()
    -- пол -> тени -> спрайты -> свет -> оверлей
    local weather = Tree.level.weather
    local txs = self.textures
    love.graphics.setCanvas(txs.lightLayer)
    love.graphics.draw(self:applyBlur(txs.shadowLayer, 4 * Tree.level.camera.scale))
    love.graphics.setCanvas()

    -- self.lightLayer:newImageData():encode("png", "lightLayer.png")
    -- os.exit(0)

    local lightShader = Tree.assets.files.shaders.light_postprocess
    lightShader:send("scene", txs.floorLayer)
    lightShader:send("light", self:applyBlur(txs.lightLayer, 2))
    lightShader:send("ambient", { weather.ambientLight.x, weather.ambientLight.y, weather.ambientLight.z })
    love.graphics.setShader(lightShader)
    love.graphics.draw(txs.floorLayer)


    lightShader:send("scene", txs.spriteLayer)
    lightShader:send("light", txs.spriteLightLayer)
    love.graphics.draw(txs.spriteLayer)
    love.graphics.setShader()

    love.graphics.draw(txs.overlayLayer)
end

---@param params {w: number?, h: number?}
---@return table|Render
local function new(params)
    local w = params.w or love.graphics.getWidth()
    local h = params.h or love.graphics.getHeight()
    return setmetatable({
        textures = {
            shadowLayer = love.graphics.newCanvas(w, h),
            spriteLayer = love.graphics.newCanvas(w, h),
            spriteLightLayer = love.graphics.newCanvas(w, h),
            floorLayer = love.graphics.newCanvas(w, h),
            overlayLayer = love.graphics.newCanvas(w, h),
            lightLayer = love.graphics.newCanvas(w, h),
            tmp1 = love.graphics.newCanvas(w, h),
            tmp2 = love.graphics.newCanvas(w, h),
        }
    }, { __index = render })
end

return { new = new }
