/*
 * mdview2_status.c — статус-бар (строка 0), нижнее меню (строка 31) и спиннер.
 *
 * Хром бара АТОМИЗИРОВАН — обновляется по частям, без перерисовки всего бара:
 *   prerender_status()         — фон + разделители │ + "MDVIEW" + имя файла (1 раз);
 *   status_encoding()          — только поле кодировки (col 37), по F8;
 *   render_md_status_numbers() — числа MD: диапазон строк + % (при скролле);
 *   render_raw_status_numbers()— числа RAW: метка режима + % по байтам;
 *   render_full_status()       — encoding + numbers (MD), при смене набора/режима;
 *   render_menu()              — строка меню, по смене режима/готовности;
 *   spinner_tick/show          — индикатор занятости во время загрузки.
 * Оба *_status_numbers() самоочищаются по геометрии разделителей (DIV1_X/DIV2_X
 * в mdview2.h) — фикс. хром не перерисовывается. RAW-позицию даёт raw_pct()
 * из mdview2_raw.c (raw_top там приватен).
 *
 * Раскладка строки 0:
 *   0       1..6     8      10..      37..43   45 46..70        71 72..79
 *   .      MDVIEW  spinner  filename   encod.   │  L a-b / total │  pct%
 */

#include <stdint.h>
#include <stdio.h>          /* dec8/dec16, cputs */
#include <conio.h>          /* textattr/gotoxy/wrchar/COLOR */
#include <limits.h>         
#include <bios/text.h>      /* bios_fillcharattr/bios_write_until */
#include "mdview2.h"

/* ---- Спиннер (слот SPINNER_COL в баре) --------------------------- */
static const char spinner_chars[4] = { '|', '/', '-', '\\' };
static uint8_t    spinner_phase    = 0;
static uint8_t    spinner_active   = 0;

/* Продвигает спиннер на один кадр (если включён). */
void spinner_tick(void)
{
    if (!spinner_active) 
        return;
    wrchar(SPINNER_COL, 0, spinner_chars[spinner_phase & 3], ATTR_BAR_SPINNER);
    spinner_phase++;
}

/* Вкл/выкл спиннер; при выключении гасит его позицию. */
void spinner_show(uint8_t on)
{
    spinner_active = on;
    if (!on) wrchar(SPINNER_COL, 0, ' ', ATTR_BAR);
}

/* ---- Вычисления для чисел статус-бара ----------------------------- */

/* Число строк, готовых к показу. Во время загрузки последняя эмитированная
 * строка ещё в g_cells (не зафлашена), поэтому доступны [0..n_lines-2]. */
uint16_t drawable_lines(void)
{
    if (g_loading)
        return (n_lines >= 1) ? (uint16_t)(n_lines - 1) : 0;
    return n_lines;
}


/* ---- Атомарные части статус-бара ---------------------------------- */

/* Фиксированный хром бара — рисуется ОДИН раз при старте: фон, два
 * разделителя │, метка "MDVIEW" и имя файла (они не меняются за сессию). */
void prerender_status(void)
{
    fill_row(0, ATTR_BAR);
    wrchar(DIV1_X, 0, 0xB3, ATTR_BAR);     /* │ */
    wrchar(DIV2_X, 0, 0xB3, ATTR_BAR);     /* │ */
    put_str_attr(1, 0, "MDVIEW", ATTR_BAR);
    put_str_attr(10, 0, filename, ATTR_BAR);
}

/* Поле текущей кодировки (col 37, 7 ячеек). Меняется только по F8. */
void status_encoding(void)
{
    textattr(ATTR_BAR);
    gotoxy(DIV1_X - 10, 0);
    bios_write_until(enc_name(g_encoding), 8, 0);
}

static uint16_t local_total = UINT_MAX;
static uint16_t local_last = UINT_MAX;
static uint8_t local_loading = UCHAR_MAX;
static uint8_t local_pct = UCHAR_MAX;

/* Числовая часть (MD): "L a-b / total" между разделителями + "pct%" справа.
 * Перезаписывает ТОЛЬКО области между/после разделителей, сами │ и фикс.
 * хром не трогает. */
void render_md_status_numbers(void)
{
    uint16_t total = drawable_lines();
    uint16_t last  = top_line + VIEW_H;
    if (last > total) 
        last = total;

    if(local_total != total || local_last != last || local_loading != g_loading) {
        local_total = total; local_last = last; local_loading = g_loading;
        textattr(ATTR_BAR);
        gotoxy(DIV1_X + 2, 0);
        bios_fillcharattr(' ', ATTR_BAR, DIV2_X - DIV1_X - 2);   /* очистить [DIV1_X+1 .. DIV2_X-1] */
        gotoxy(DIV1_X + 2, 0);
        cputs("L ");
        dec16(top_line + 1);
        cputs("-");
        dec16(last);
        cputs(" / ");
        dec16(total);
        if (g_loading) cputs("...");        /* ещё грузится */
    }

}

/* Полное обновление переменной части (MD): кодировка + числа. */
void render_full_status(void)
{
    local_loading = UCHAR_MAX;
    status_encoding();
    render_md_status_numbers();
}

void render_percent_progress(uint8_t pct) {
    if (local_pct != pct) {
        local_pct = pct;
        gotoxy(DIV2_X + 2, 0);
        bios_fillcharattr(' ', ATTR_BAR, SCREEN_W - DIV2_X - 2);     /* очистить [DIV2_X+1 .. конец] */
        gotoxy(DIV2_X + 2, 0);
        dec8(pct);
        cputs("%");
    }
}

#if WITH_RAW
/* RAW-вариант числовой части бара (peer к render_md_status_numbers): метка
 * режима между разделителями + процент справа. Сам очищает свои области (та же
 * геометрия DIVn_X), атомарен — не требует общего fill всего бара. Позиция
 * берётся готовым числом из raw_pct() (raw_top приватен mdview2_raw.c). */
void render_raw_status(void)
{
    // uint8_t pct = raw_pct();
    textattr(ATTR_BAR);
    gotoxy(DIV1_X + 1, 0);
    bios_writeattr_until(g_view == VIEW_RAW_WRAP ? " RAW wrap" : " RAW pan",
                         DIV2_X - DIV1_X - 1, ATTR_BAR, 0);   /* метка + пад до DIV2_X-1 */
}
#endif /* WITH_RAW */

#if WITH_HEX
/* HEX-вариант числовой части бара (peer к render_raw_status). */
void render_hex_status(void)
{
    textattr(ATTR_BAR);
    gotoxy(DIV1_X + 1, 0);
    bios_writeattr_until(" HEX", DIV2_X - DIV1_X - 1, ATTR_BAR, 0);
}
#endif /* WITH_HEX */

/* ---- Нижнее меню (строка 31) -------------------------------------- */

void render_menu(void)
{
    /* Блок i = колонка i*8 (8 шириной): 2 поз. НОМЕР клавиши без 'F' (стиль
     * ATTR_MENU_K, ведущий «чёрный» пробел кроме F10) + 6 поз. ТЕКСТ-функция
     * (ATTR_MENU_T) сразу за номером. Номера рисуем для ВСЕХ 10 клавиш; текст —
     * только у задействованных и доступных сейчас. */
    char num[3];  

    fill_row(MENU_ROW, ATTR_MENU_T);

    num[2] = 0;
    for (uint8_t i = 0; i < 9; i++) {           /* F1..F9: ' 1'..' 9' */
        num[0] = ' '; num[1] = (char)('1' + i);
        put_str_attr((uint8_t)(i * 8), MENU_ROW, num, ATTR_MENU_K);
    }
    put_str_attr(9 * 8, MENU_ROW, "10", ATTR_MENU_K);   /* F10 */

    put_str_attr(0 * 8 + 2, MENU_ROW, "Help", ATTR_MENU_T);
#if WITH_RAW
    if (g_ready)                                /* RAW доступен после постройки документа */
        put_str_attr(1 * 8 + 2, MENU_ROW, (g_view == VIEW_MD) ? "RAW" : "MD", ATTR_MENU_T);
    if (VIEW_IS_RAW(g_view))                    /* Wrap/Unwrap — только в RAW */
        put_str_attr(2 * 8 + 2, MENU_ROW,
                     (g_view == VIEW_RAW_WRAP) ? "UnWrap" : "Wrap", ATTR_MENU_T);
#endif
#if WITH_HEX
    if (g_ready)                                /* HEX доступен после постройки документа */
        put_str_attr(3 * 8 + 2, MENU_ROW, (g_view == VIEW_HEX) ? "Back" : "Hex", ATTR_MENU_T);
#endif
    if (g_f8_enabled)                           /* смена кодировки сейчас возможна */
        put_str_attr(7 * 8 + 2, MENU_ROW, "CodePg", ATTR_MENU_T);
    put_str_attr(9 * 8 + 2, MENU_ROW, "Exit", ATTR_MENU_T);
}
