#include "rendering/FontRenderer.h"

FontRenderer::FontRenderer() : buffer(8 * 1024 * 1024, 8 * sizeof (float)), tex1("resources/font8x8.png"),
tex2("resources/font16x16.png"), tex3("resources/font24x24.png"), activeTex(&tex1), scale(1) {
    vertexBuffer.bind();
    int step = 8 * sizeof (float);
    vertexBuffer.setFloatAttribute(0, 2, 0, step);
    vertexBuffer.setFloatAttribute(1, 2, 2 * sizeof (float), step);
    vertexBuffer.setFloatAttribute(2, 4, 4 * sizeof (float), step);
}

float FontRenderer::drawString(float x, float y, const char* text) {
    vertexBuffer.bind();

    const int maxIndex = 256;
    buffer.reset(maxIndex * 4 * sizeof (float) * 8);

    int index = 0;
    float r = 1.0f;
    float g = 1.0f;
    float b = 1.0f;
    
    float addX = 6.0f * scale;
    float addY = 8.0f * scale;

    while(text[index] != '\0' && index < maxIndex) {
        char32_t c = text[index];
        if(c > 128 && index + 1 < maxIndex && text[index + 1] != '\0') {
            index++;
            c = (text[index] & 0x3F) | ((c & 0x1F) << 6);
        }
        if(c == '&') {
            if(text[index + 1] == '\0' || text[index + 2] == '\0' || text[index + 3] == '\0') {
                break;
            }
            r = (text[index + 1] - '0') * (1.0f / 9.0f);
            g = (text[index + 2] - '0') * (1.0f / 9.0f);
            b = (text[index + 3] - '0') * (1.0f / 9.0f);
            index += 4;
            continue;
        }

        float minX = (c & 0xF) * (1.0f / 16.0f) + 1.0f / 128.0f;
        float minY = (c >> 4) * (1.0f / 16.0f);
        float maxX = minX + (1.0f / 16.0f) - 2.0f / 128.0f;
        float maxY = minY + (1.0f / 16.0f);

        buffer.add(x).add(y).add(minX).add(minY).add(r).add(g).add(b).add(1.0f);
        buffer.add(x).add(y + addY).add(minX).add(maxY).add(r).add(g).add(b).add(1.0f);
        buffer.add(x + addX).add(y).add(maxX).add(minY).add(r).add(g).add(b).add(1.0f);
        buffer.add(x + addX).add(y + addY).add(maxX).add(maxY).add(r).add(g).add(b).add(1.0f);

        x += addX;
        index++;
    }

    activeTex->bind();
    buffer.draw();
    return y + addY;
}

void FontRenderer::setSize(int size) {
    if(size == 1) {
        activeTex = &tex2;
        scale = 2;
    } else if(size == 2) {
        activeTex = &tex3;
        scale = 3;
    } else {
        activeTex = &tex1;
        scale = 1;
    }
}