#include "pch.h"

#include "TextRenderer.h"
#include <systems/sources/ShaderProgram.h>
#include "systems/RenderSystem.h"
#include <systems/sources/ShaderManagement.h>
#include <systems/buffer/Tesselator.h>
#include "AlignedMemoryStack.h"

typedef Vivid2D::Render::Buffer::Tesselator Tesselator;
typedef Vivid2D::Render::Buffer::BufferBuilder BufferBuilder;

Logger TextRenderer::logger{ "TextRenderer" };
int TextRenderer::CHINESE_FIRST_CHAR = 0x4E00; // CJK Unified Ideographs 常用汉字起始范围
int TextRenderer::CHINESE_CHAR_COUNT = 20000;

TextRenderer::TextRenderer(int bitmapWidth, int bitmapHeight, int firstChar, int charCount)
    : bitmapWidth(bitmapWidth),
      bitmapHeight(bitmapHeight),
      firstChar(firstChar),
      charCount(charCount)
{
}


/**
 * 初始化字体渲染器
 */
void TextRenderer::initialize(ByteBuffer fontData, float fontHeight)
{
    if (initialized) {
        logger.warning("TextRenderer already initialized");
        return;
    }
    if (fontData.empty() || fontHeight <= 0) {
        logger.error("Invalid font data or font height");
        return;
    }

    ShaderProgram* shader = ShaderManagement::getShaderProgram("TextShader");
    if (!shader) {
        logger.error("TextShader not found");
        return;
    }

    shader->use();

    try {
        asciiCharData.resize(charCount);
        ByteBuffer asciiBitmap(bitmapWidth * bitmapHeight);
        int asciiRes = stbtt_BakeFontBitmap(
            fontData.data(),
            0, fontHeight,
            asciiBitmap.data(),
            bitmapWidth, bitmapHeight, firstChar, charCount,
            asciiCharData.data());
        if (asciiRes <= 0) {
            logger.error("ASCII font bake failed, result: {}", asciiRes);
            cleanup();
            return;
        }
        asciiTextureId = createTextureFromBitmap(bitmapWidth, bitmapHeight, asciiBitmap);
        if (asciiTextureId == 0) {
            logger.error("Failed to create ASCII texture");
            cleanup();
            return;
        }

        // 烘焙中文 - 使用更大的纹理和正确的字符范围
        int chineseTexSize = 4096; // 中文字符需要更大的纹理
        // 分配足够的空间来存储 CHINESE_CHAR_COUNT 个字符的数据
        chineseCharData.resize(CHINESE_CHAR_COUNT);
        ByteBuffer chineseBitmap(chineseTexSize * chineseTexSize);
        // 关键：烘焙从 CHINESE_FIRST_CHAR 开始的 CHINESE_CHAR_COUNT 个连续字符
        int chineseRes = stbtt_BakeFontBitmap(fontData.data(),
            0, fontHeight,
            chineseBitmap.data(),
            chineseTexSize, chineseTexSize, CHINESE_FIRST_CHAR, CHINESE_CHAR_COUNT,
            chineseCharData.data());
        if (chineseRes <= 0) {
            logger.error("Chinese font bake failed, result: {}", chineseRes);
            cleanup();
            return;
        }
        chineseTextureId = createTextureFromBitmap(chineseTexSize, chineseTexSize, chineseBitmap);
        if (chineseTextureId == 0) {
            logger.error("Failed to create Chinese texture");
            cleanup();
            return;
        }

        initialized = true;
        logger.debug("TextRenderer initialized, ASCII tex={}, Chinese tex={}", asciiTextureId, chineseTextureId);

    }
    catch (std::exception e) {
        logger.error("Exception during TextRenderer init: {}", e.what(), e);
        cleanup();
    }
    catch (...) {
        logger.error("Unknown exception during TextRenderer init");
        cleanup();
    }
    shader->stop();
}



/**
 * 获取一行文字的宽度（带缩放）
 */
float TextRenderer::getTextWidth(std::string text, float scale) const
{
    if (!initialized || text.empty()) return 0.0f;

    float width = 0.0f;

    for (int i = 0; i < text.length(); i++) {
        char c = text[i];
        if (c >= firstChar && c < firstChar + charCount) {
            BakedChar bakedChar = asciiCharData[c - firstChar];
            width += bakedChar.xadvance * scale;
        }
        else {
            // 修复中文索引逻辑：检查字符是否在烘焙的连续范围内
            if (c >= CHINESE_FIRST_CHAR && c < CHINESE_FIRST_CHAR + CHINESE_CHAR_COUNT) {
                int idx = c - CHINESE_FIRST_CHAR; // 关键：使用 Unicode 差值作为索引
                BakedChar bakedChar = chineseCharData[idx];
                width += bakedChar.xadvance * scale;
            }
            else {
                // 对于未找到的字符，使用空格宽度
                width += 0.5f * scale; // 估计值
            }
        }
    }

    return width;
}

void TextRenderer::renderText(std::string text, float x, float y, Vector4f color, float scale)
{
    if (!initialized || text.empty()) return;
    if (scale <= 0.0f) scale = 1.0f;

    RenderSystem::assertOnRenderThread();
    RenderSystem::pushState();
    try {
        ShaderProgram* shader = ShaderManagement::getShaderProgram("TextShader");
        if (!shader) {
            logger.error("TextShader not found");
            return;
        }
        shader->use();
        ShaderManagement::setUniformVec4(shader, "uColor", color);
        ShaderManagement::setUniformInt(shader, "uTexture", 0);

        RenderSystem::enableBlend();
        RenderSystem::blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        RenderSystem::disableDepthTest();

        thread_local AlignedMemoryStack stack;
        try {
            auto* q = stack.pushStackAllocate<AlignedQuad>(sizeof(AlignedQuad));
            float xpos = x;
            float ypos = y;

            Tesselator& t = Tesselator::getInstance();
            BufferBuilder& builder = t.getBuilder();

            // 按字符类型分组渲染以减少纹理切换
            int currentTexture = -1;
            bool batchStarted = false;

            for (int i = 0; i < text.length(); i++) {
                char c = text[i];
                int targetTexture;
                BakedCharBuffer charBuffer;
                int texWidth, texHeight;

                if (c >= firstChar && c < firstChar + charCount) {
                    targetTexture = asciiTextureId;
                    charBuffer = asciiCharData;
                    texWidth = bitmapWidth;
                    texHeight = bitmapHeight;
                    stbtt_GetBakedQuad(charBuffer.data(), texWidth, texHeight, c - firstChar, &xpos, &ypos, q, true);
                }
                else {
                    // 修复中文索引逻辑：检查字符是否在烘焙的连续范围内
                    if (c >= CHINESE_FIRST_CHAR && c < CHINESE_FIRST_CHAR + CHINESE_CHAR_COUNT) {
                        targetTexture = chineseTextureId;
                        charBuffer = chineseCharData;
                        texWidth = 4096;
                        texHeight = 4096;
                        // 关键修复：索引是字符的 Unicode 减去起始 Unicode
                        int idx = c - CHINESE_FIRST_CHAR;
                        stbtt_GetBakedQuad(charBuffer.data(), texWidth, texHeight, idx, &xpos, &ypos, q, true);
                    }
                    else {
                        continue; // 跳过不支持的字符
                    }
                }

                // 如果纹理改变，结束当前批次
                if (targetTexture != currentTexture) {
                    if (batchStarted) {
                        t.end();
                        batchStarted = false;
                    }
                    RenderSystem::bindTexture(targetTexture);
                    currentTexture = targetTexture;
                }

                // 开始新批次（如果需要）
                if (!batchStarted) {
                    builder.begin(GL_TRIANGLES, (text.length() - i) * 6);
                    batchStarted = true;
                }

                // 应用缩放并计算顶点
                float sx0 = x + (q->x0 - x) * scale;
                float sx1 = x + (q->x1 - x) * scale;
                float sy0 = y + (q->y0 - y) * scale;
                float sy1 = y + (q->y1 - y) * scale;

                builder.vertex(sx0, sy0, q->s0, q->t0);
                builder.vertex(sx1, sy0, q->s1, q->t0);
                builder.vertex(sx0, sy1, q->s0, q->t1);

                builder.vertex(sx1, sy0, q->s1, q->t0);
                builder.vertex(sx1, sy1, q->s1, q->t1);
                builder.vertex(sx0, sy1, q->s0, q->t1);
            }

            // 结束最后一个批次
            if (batchStarted) {
                t.end();
            }
            stack.popStack();
        }
        catch (...) {
            stack.popStack();
            throw;
        }
    }
    catch (std::exception e) {
        logger.error("Error rendering text: {}", e.what(), e);
    }
    catch (...) {
        logger.error("Unknown error rendering text");
    }
    RenderSystem::popState();
}

int TextRenderer::createTextureFromBitmap(int width, int height, ByteBuffer pixels)
{
    RenderSystem::assertOnRenderThread();
    try {
        int textureId = RenderSystem::genTextures();
        RenderSystem::bindTexture(textureId);

        RenderSystem::pixelStore(GL_UNPACK_ALIGNMENT, 1);
        RenderSystem::texImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0,
            GL_RED, GL_UNSIGNED_BYTE, pixels.data());

        RenderSystem::setTextureMinFilter(GL_LINEAR);
        RenderSystem::setTextureMagFilter(GL_LINEAR);
        RenderSystem::setTextureWrapS(GL_CLAMP_TO_EDGE);
        RenderSystem::setTextureWrapT(GL_CLAMP_TO_EDGE);

        // 设置纹理swizzle以便单通道纹理在着色器中显示为白色
        RenderSystem::texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
        RenderSystem::texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED);
        RenderSystem::texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
        RenderSystem::texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);

        RenderSystem::pixelStore(GL_UNPACK_ALIGNMENT, 4);
        RenderSystem::bindTexture(0);

        return textureId;
    }
    catch (std::exception e) {
        logger.error("Failed to create texture from bitmap: {}", e.what(), e);
        return 0;
    }
    catch (...) {
        logger.error("Unknown error creating texture from bitmap");
        return 0;
    }
}

void TextRenderer::cleanup()
{
    RenderSystem::assertOnRenderThread();
    if (asciiTextureId != 0)
    {
        RenderSystem::deleteTextures(asciiTextureId);
        asciiTextureId = 0;
    }
    if (chineseTextureId != 0)
    {
        RenderSystem::deleteTextures(chineseTextureId);
        chineseTextureId = 0;
    }
    if (!asciiCharData.empty())
    {
        asciiCharData.clear();
        asciiCharData.shrink_to_fit();
    }
    if (!chineseCharData.empty())
    {
        chineseCharData.clear();
        chineseCharData.shrink_to_fit();
    }
    initialized = false;
    logger.debug("TextRenderer cleaned up");
}

