--- @alias FontVariant "smallest" | "small" | "medium" | "large" | "headline"

--- @class TextTheme
--- @field private _sizes {[FontVariant]: integer}
local theme = {
    _sizes = {
        smallest = 12,
        small = 14,
        medium = 16,
        large = 22,
        headline = 32,
    }
}
theme.__index = theme

--- @param loader fun(size: integer): love.Font?
function theme.new(loader)
    local t = {}
    for tag, size in pairs(theme._sizes) do
        local f = loader(size)
        if not f then return nil end
        t[tag] = f
    end

    return setmetatable(t, theme)
end

--- @param variant FontVariant
--- @return love.Font
function theme:getVariant(variant)
    return self[variant]
end

----------------------------------------------------------

--- A singleton to handle fonts
--- @class FontManager
--- @field private _themes table
--- @field defaultTheme string?
local FontManager = {
    _themes = {}
}

--- @param name string
--- @param size integer
function FontManager.newFont(name, size)
    local err = function()
        print("[FontManager]: font " .. name .. " not found!")
    end
    local fontDir = Tree.assets.files.fonts[name]
    if not fontDir then return err() end
    local font = fontDir.font
    if not font then return err() end
    return love.graphics.newFont(font, size)
end

--- @param name string
--- @return FontManager
function FontManager:loadTheme(name)
    self._themes[name] = theme.new(
        function(size)
            return self.newFont(name, size)
        end
    )
    return self
end

--- @param name string
--- @return TextTheme?
function FontManager:getTheme(name)
    return self._themes[name]
end

--- @return TextTheme
function FontManager:getDefaultTheme()
    return self._themes[self.defaultTheme]
end

--- initial setup
--- @param defaultFontName string
function FontManager:load(defaultFontName)
    local t = self:loadTheme(defaultFontName):getTheme(defaultFontName)
    if not t then
        print("[FontManager]: default font " .. defaultFontName .. " is missing")
        return self
    end
    self.defaultTheme = defaultFontName

    local f = t:getVariant("medium")
    love.graphics.setFont(f)
    return self
end

return FontManager
