#include <fonts/ttf.h>
#include "ttf_internal.h"
#include <graphics/draw.h>
#include <memory/heap.h>
#include <serial.h>

// 逐字形临时缓冲区 — 静态分配以避免大中文字形的栈压力
static ttf_outline_t  s_outline;
static ttf_seg_t      s_segs[4096];
static SUINT8         s_coverage[256 * 256];

// 在屏幕 (px, py) 处渲染单个字形位图，py 为字形顶部（已从基线转换）
static void blit_glyph(SSINT32 px, SSINT32 py, SUINT32 w, SUINT32 h,
    const SUINT8* coverage, SUINT32 N,
    EFI_GRAPHICS_OUTPUT_BLT_PIXEL color)
{
    SUINT32 scale = 255 / N;
    for (SUINT32 y = 0; y < h; y++) {
        SSINT32 sy = py + (SSINT32)y;
        if (sy < 0) continue;
        for (SUINT32 x = 0; x < w; x++) {
            SSINT32 sx = px + (SSINT32)x;
            if (sx < 0) continue;
            SUINT8 c = coverage[y * w + x];
            if (c == 0) continue;
            SUINT8 a = (SUINT8)(c * scale);
            draw_pixel_alpha(sx, sy, color, a);
        }
    }
}

// 在基线 (x, y) 处渲染单个码点，返回进宽（26.6 定点数）
static f26_6 render_codepoint(ttf_face_t* face, SSINT32 cp,
    SSINT32 x, SSINT32 y, SUINT32 pixel_size,
    EFI_GRAPHICS_OUTPUT_BLT_PIXEL color)
{
    SUINT16 gid = ttf_cmap_lookup(face, cp);

    if (!ttf_load_glyph(face, gid, pixel_size, &s_outline)) {
        return 0;  // composite / parse error
    }

    // Bitmap dims in pixels
    SSINT32 bbox_w = s_outline.xmax - s_outline.xmin;
    SSINT32 bbox_h = s_outline.ymax - s_outline.ymin;
    if (bbox_w <= 0 || bbox_h <= 0) {
        return s_outline.advance;  // whitespace or zero-size
    }
    SUINT32 pw = (SUINT32)((bbox_w + 63) >> 6);
    SUINT32 ph = (SUINT32)((bbox_h + 63) >> 6);
    if (pw > 256 || ph > 256) {
        return s_outline.advance;  // too big for scratch
    }

    // Translate outline to bitmap-local: bx = fx - xmin, by = ymax - fy
    ttf_outline_t local;
    local.num_points   = s_outline.num_points;
    local.num_contours = s_outline.num_contours;
    for (SUINT16 i = 0; i < s_outline.num_contours; i++) {
        local.first[i] = s_outline.first[i];
        local.last[i]  = s_outline.last[i];
    }
    for (SUINT16 i = 0; i < s_outline.num_points; i++) {
        local.x[i] = s_outline.x[i] - s_outline.xmin;
        local.y[i] = s_outline.ymax - s_outline.y[i];
        local.on_curve[i] = s_outline.on_curve[i];
    }
    local.xmin = 0;
    local.ymin = 0;
    local.xmax = bbox_w;
    local.ymax = bbox_h;

    SUINT32 n_segs = 0;
    ttf_outline_to_segments(&local, s_segs, &n_segs);

    // Clear coverage
    for (SUINT32 i = 0; i < pw * ph; i++) s_coverage[i] = 0;

    const SUINT32 N = 5;  // subsamples per pixel row
    ttf_rasterize(s_segs, n_segs, 0, 0, pw, ph, s_coverage, N);

    // Screen origin of bitmap
    SSINT32 px_screen = x + (s_outline.xmin >> 6);
    SSINT32 py_screen = y - (s_outline.ymax  >> 6);

    blit_glyph(px_screen, py_screen, pw, ph, s_coverage, N, color);

    return s_outline.advance;
}

SSINT32 ttf_draw_text(ttf_face_t* face, const char* utf8,
    SSINT32 x, SSINT32 y, SUINT32 pixel_size,
    EFI_GRAPHICS_OUTPUT_BLT_PIXEL color)
{
    if (!face || !utf8) return 0;
    const char* p = utf8;
    f26_6 pen = 0;
    while (*p) {
        SSINT32 cp = ttf_utf8_decode(&p);
        if (cp < 0) continue;
        f26_6 adv = render_codepoint(face, cp,
            x + (pen >> 6), y, pixel_size, color);
        pen += adv;
    }
    return pen;
}

SSINT32 ttf_text_width(ttf_face_t* face, const char* utf8, SUINT32 pixel_size) {
    if (!face || !utf8) return 0;
    const char* p = utf8;
    f26_6 pen = 0;
    while (*p) {
        SSINT32 cp = ttf_utf8_decode(&p);
        if (cp < 0) continue;
        SUINT16 gid = ttf_cmap_lookup(face, cp);
        if (!ttf_load_glyph(face, gid, pixel_size, &s_outline)) continue;
        pen += s_outline.advance;
    }
    return pen;
}
