#pragma once
#include "Type/types.hpp"
#include <stdarg.hpp>

namespace JabyEngine {
    class FontWriter {
    private:
        #define __write_impl(start, color, wiggle) \
            va_list list; \
            va_start(list, start); \
            FontWriter::write(cursor, str, color, wiggle, list); \
            va_end(list)

        GPU::TexPage::Linked tex_page[2];
        FontInfo::RenderInfo render_info;
        GPU::PageClut        clut;
        GPU::Link*           last_primitive;

    public:
        static constexpr FontWriter empty() {
            FontWriter instance;

            instance.tex_page[0]    = {0};
            instance.tex_page[1]    = {0};
            instance.render_info    = FontInfo::RenderInfo::empty();
            instance.clut           = Make::PageClut();
            instance.last_primitive = nullptr;
            return instance;
        }

        void setup(const SimpleTIM& vram_dst, const FontInfo::RenderInfo& font_render_info);

        void setup(const SimpleTIM& vram_dst, const FontInfo& font_info) {
            FontWriter::setup(vram_dst, font_info.render_info);
        }

        void clear();

        void write(Cursor& cursor, const char* str, ...) {
            __write_impl(str, GPU::Color24::Grey(), nullptr);
        }
        void write(Cursor& cursor, const char* str, GPU::Color24 color, ...) {
            __write_impl(color, color, nullptr);
        }
        void write(Cursor& cursor, const char* str, GPU::Color24 color, const Wiggle* wiggle, ...) {
            __write_impl(wiggle, color, wiggle);
        }
        void write(Cursor& cursor, const char* str, GPU::Color24 color, const Wiggle* wiggle, va_list list);
        void render();

        #undef __write_impl
    };

    struct GlobalFontPrimitivePool {
        static void setup(FontPrimitive* start, size_t length);
        
        template<size_t Size>
        static void setup(FontPrimitive (&buffer)[Size]) {
            GlobalFontPrimitivePool::setup(buffer, Size);
        }
    };
}