/**
 * @file Font.h
 * @author apio (cloudapio.eu)
 * @brief PSF font loading and rendering.
 *
 * @copyright Copyright (c) 2023, the Luna authors.
 *
 */

#pragma once
#include <luna/Buffer.h>
#include <luna/SharedPtr.h>
#include <os/Path.h>
#include <ui/Canvas.h>

#define PSF_FONT_MAGIC 0x864ab572

namespace ui
{
    /**
     * @brief A class holding PSF font data, used for low-level direct rendering of glyphs into a canvas.
     *
     * This class does not handle special characters such as tabs or newlines. For those, you should be using a more
     * high-level component such as ui::Label instead.
     */
    class Font : public Shareable
    {
      public:
        /**
         * @brief An enum used to select a font weight when loading a font.
         */
        enum FontWeight
        {
            Regular,
            Bold,
        };

        /**
         * @brief Load a Font object from a font file.
         *
         * @param path The full path to the font file.
         * @return Result<SharedPtr<Font>> An error, or the loaded Font object.
         */
        static Result<SharedPtr<Font>> load(const os::Path& path);

        /**
         * @brief Load a system font by name.
         *
         * @param name The name of the font to load (the default system font is "Tamsyn").
         * @param weight The weight of the font (regular or bold).
         * @return Result<SharedPtr<Font>> An error, or the loaded Font object.
         */
        static Result<SharedPtr<Font>> load_builtin(StringView name, FontWeight weight);

        /**
         * @brief Return a pointer to the system's default font.
         *
         * @return SharedPtr<Font> The default font.
         */
        static SharedPtr<Font> default_font();

        /**
         * @brief Return a pointer to the system's default bold font.
         *
         * @return SharedPtr<Font> The default bold font.
         */
        static SharedPtr<Font> default_bold_font();

        /**
         * @brief Render a single Unicode code point onto a canvas, using this font's glyphs.
         *
         * @param codepoint The code point to render.
         * @param color The color to draw the code point in.
         * @param canvas The canvas to use.
         */
        void render(wchar_t codepoint, ui::Color color, ui::Canvas& canvas);

        /**
         * @brief Render a Unicode text string onto a canvas, using this font's glyphs.
         *
         * @param text The string to render (must be null-terminated).
         * @param color The color to draw the code point in.
         * @param canvas The canvas to use.
         */
        void render(const wchar_t* text, ui::Color color, ui::Canvas& canvas);

        /**
         * @brief Return the width of this font's glyphs.
         *
         * @return int The width.
         */
        int width() const
        {
            return m_psf_header.width;
        }

        /**
         * @brief Return the height of this font's glyphs.
         *
         * @return int The height.
         */
        int height() const
        {
            return m_psf_header.height;
        }

      private:
        struct PSFHeader
        {
            u32 magic;
            u32 version; // zero
            u32 headersize;
            u32 flags; // 0 if there's no unicode table
            u32 numglyph;
            u32 bytesperglyph;
            int height;
            int width;
        };

        PSFHeader m_psf_header;
        Buffer m_font_data;
    };
};