#pragma once
#include "texture.h"
#include "util.h"
#include <stb/stb_truetype.h>

class Font
{
public:
    int w = 512;
    int h = 512;
    const int num_chars = 256-32;
    const int start_char = 32;
    // {mix, max}
    glm::vec4 bounds{ 0 };
    int size = 0;
    Texture2D font_tex;
    std::string path;
    std::string id;
    std::vector<stbtt_bakedchar> chars;
    float scale = 1.f;

    Font() = default;
    Font(const Font&) = delete;
    void operator=(const Font&) = delete;
    Font(Font&& other) noexcept;
    void operator=(Font&& other) noexcept;

    bool load(const std::string& ttf, int sz, float scale);
    void change_scale(float scale);
    void calc_bounds();
};

class FontManager
{
public:
    static std::map<std::string, Font> m_fonts;
    static Sampler m_sampler;
    static void init();
    static bool load(const std::string& id, const std::string& ttf, int sz, float scale);
    static const Font& get(const std::string& name, int size, const std::string& weight, bool italic);
    static void invalidate() { m_fonts.clear(); }
    static void change_scale(float scale);
};

class TextMesh
{
    struct Token
    {
        std::string s;
        float w;
        Token(const std::string& str, float width) : s(str), w(width) {}
    };
    std::vector<Token> tokenize(const std::string& s, const Font& f) const noexcept;
public:
    GLuint font_array = 0;
    int font_array_count = 0;
    int max_width = 0;
    GLuint font_buffers[2] = {0, 0};
    std::string font;
    std::string weight;
    int italic;
    int size;
    glm::vec2 bb = { 0, 0 };
    glm::vec4 cur_box;
    bool create();
    void update(const std::string& text, const std::string& font, int size, const std::string& weight, bool italic);
    void draw();
};
