/*
 * mdview2_table.c — выровненная отрисовка markdown-таблиц.
 *
 * Разбор |-разделённых ячеек и эмиссия рамок/строк в общий буфер ячеек
 * рендера (gc_put/gc_fill, см. mdview2.h). Вызывается из index_lines()
 * ядра при обнаружении таблицы. Геометрия рамок (TBL_n), словарь стилей
 * (CK_n, INIT_STYLE_n) и cell-buffer API объявлены в mdview2.h.
 */

#include <stdint.h>
#include <conio.h>      /* COLOR() / COLOR_* для атрибутов TBL_ATTR/ATTR_TEXT */
#include "mdview2.h"

uint32_t row_end(uint32_t p)
{
    while (p < file_size && fb(p) != '\n') p++;
    return p;
}

/* Начало контента первой ячейки строки (после ведущих пробелов и '|'). */
uint32_t table_first_cell(uint32_t row_start)
{
    uint32_t p = row_start;
    while (p < file_size && fb(p) == ' ') p++;
    if (p < file_size && fb(p) == '|') p++;
    return p;
}

/* Следующая ячейка: [*cs,*ce) — обрезанный диапазон; *pp продвигается за '|'.
 * 0 — ячеек больше нет (включая хвостовую пустоту после последнего '|'). */
uint8_t table_next_cell(uint32_t *pp, uint32_t lineend, uint32_t *cs, uint32_t *ce)
{
    uint32_t p = *pp;
    if (p >= lineend) return 0;
    uint32_t a = p;
    while (p < lineend && fb(p) != '|') p++;
    uint32_t b = p;
    uint8_t had_pipe = (uint8_t)(p < lineend && fb(p) == '|');
    if (had_pipe) p++;
    *pp = p;
    while (a < b && fb(a) == ' ') a++;
    while (b > a && fb(b - 1) == ' ') b--;
    if (!had_pipe && a == b) return 0;
    *cs = a; *ce = b;
    return 1;
}

/* Строка-разделитель (|---|:-:|): каждая ячейка непустая и только '-'/':'. */
uint8_t table_is_sep_row(uint32_t row_start, uint32_t lineend)
{
    uint32_t p = table_first_cell(row_start);
    uint32_t cs, ce;
    uint8_t n = 0;
    while (table_next_cell(&p, lineend, &cs, &ce)) {
        if (cs >= ce) return 0;
        for (uint32_t q = cs; q < ce; q++) { char c = fb(q); if (c != '-' && c != ':') return 0; }
        n++;
    }
    return (uint8_t)(n > 0);
}

/* Горизонтальная рамка в g_cells: left + (H×(w+2) + mid|right) по колонкам. */
void table_border(const uint8_t *widths, uint8_t ncols, char left, char mid, char right)
{
    gc_put(left, TBL_ATTR);
    for (uint8_t c = 0; c < ncols; c++) {
        gc_fill(TBL_H, TBL_ATTR, (uint8_t)(widths[c] + 2));
        gc_put((c == (uint8_t)(ncols - 1)) ? right : mid, TBL_ATTR);
    }
}

/* Строка данных в g_cells: │ <ячейка, добитая до widths[c]> │ … */
void table_data_row(uint32_t row_start, uint32_t lineend, const uint8_t *widths, uint8_t ncols)
{
    uint32_t p = table_first_cell(row_start);
    uint32_t cs, ce;
    gc_put(TBL_V, TBL_ATTR);
    for (uint8_t c = 0; c < ncols; c++) {
        uint8_t got = table_next_cell(&p, lineend, &cs, &ce);
        gc_put(' ', TBL_ATTR);
        uint8_t rendered = 0;
        if (got && ce > cs) {
            uint8_t before = g_ncells;
            (void)inline_scan(cs, ce, 0, CK_OTHER, INIT_STYLE_PLAIN, ATTR_TEXT, 1);
            rendered = (uint8_t)(g_ncells - before);
        }
        if (rendered < widths[c]) gc_fill(' ', ATTR_TEXT, (uint8_t)(widths[c] - rendered));
        gc_put(' ', TBL_ATTR);
        gc_put(TBL_V, TBL_ATTR);
    }
}
