# -*- coding: utf-8 -*-
"""
book.h 生成器：把 inkboat/*.txt 变成固件用的 C 数组（多书架构）
================================================================
txt 格式（与模拟器共享同一份源文件，2026-08-29 升级）：
  '# ' 开头 = 章节标题行（目录项 / 页眉）
  '@ ' 开头 = 章内小节行（mark：居中渲染；如飞鸟集首编号、道德经卷内章名）
  其余非空行 = 正文段；首字符 <0x80 = 英文段（整词折行），否则中文段
  ※ 段首缩进不再写进文本（旧版加 \\u3000\\u3000），由固件 wrap_refs 渲染层处理：
    中文段首行缩进 2 格、英文段首行缩进 16px、续行均顶格——与模拟器同规则。
输出：firmware/inkboat/book.h
  BOOKS 数量 / BOOK_NAMES[] / 每书章数组 / 二级指针索引
正文 UTF-8 字符串直接 const char* 存 flash。

用法：.venv/Scripts/python.exe inkboat/make_book.py
"""

from pathlib import Path

SRC_DIR = Path(__file__).parent
DEST = SRC_DIR.parent / "firmware" / "inkboat" / "book.h"
BOOK_FILES = [("daodejing_grouped.txt", "道德经"), ("xinjing.txt", "心经"),
              ("lunyu.txt", "论语"), ("zhuangzi.txt", "庄子"),
              ("feiniao.txt", "飞鸟集")]                    # 2026-08-29：卷版+第5本


def c_str(s: str) -> str:
    # '\n' 是段落分隔符（固件 wrap_refs 遇它断段），C 串里要转义
    return '"' + s.replace("\\", "\\\\").replace('"', '\\"').replace("\n", "\\n") + '"'


def parse_book(path):
    chapters, title, body = [], None, []
    for line in path.read_text(encoding="utf-8").splitlines():
        if line.startswith("# "):
            if title is not None:
                chapters.append((title, "\n".join(body)))
            title, body = line[2:].strip(), []
        elif line.strip() and title is not None:
            body.append(line.strip())      # '@ ' 小节行原样保留（固件靠段首 '@' 识别）
    if title is not None:
        chapters.append((title, "\n".join(body)))
    return chapters


def main():
    out = ["// 本文件由 inkboat/make_book.py 自动生成，手改无效",
           "// 正文 UTF-8（汉字 3 字节），直接存 flash",
           "// 段格式：'\\n' 分段；段首 '@'=居中mark行；ASCII 起始=英文段（整词折行）",
           "#pragma once", "",
           f"#define BOOKS {len(BOOK_FILES)}", ""]
    names, total_all = [], 0
    for bi, (fname, disp) in enumerate(BOOK_FILES):
        chapters = parse_book(SRC_DIR / fname)
        assert chapters, f"{fname} 里没解析到章节"
        sym = fname.split(".")[0].upper()
        out.append(f"// —— 《{disp}》 {len(chapters)} 章 ——")
        out.append(f"const char *const {sym}_TITLES[{len(chapters)}] = {{")
        out += [f"  {c_str(t)}," for t, _ in chapters]
        out.append("};")
        out.append(f"const char *const {sym}_TEXTS[{len(chapters)}] = {{")
        out += [f"  {c_str(t)}," for _, t in chapters]
        out.append("};")
        out.append(f"const uint8_t {sym}_CHS = {len(chapters)};")
        out.append("")
        names.append((disp, sym))
        total_all += sum(len(t) for _, t in chapters)

    out.append("const char *const BOOK_NAMES[BOOKS] = {")
    out += [f"  {c_str(n)}," for n, _ in names]
    out.append("};")
    out.append("const uint8_t BOOK_CHS[BOOKS] = {")
    out += [f"  {s}_CHS," for _, s in names]
    out.append("};")
    out.append("const char *const *BOOK_TITLES[BOOKS] = {")
    out += [f"  {s}_TITLES," for _, s in names]
    out.append("};")
    out.append("const char *const *BOOK_TEXTS[BOOKS] = {")
    out += [f"  {s}_TEXTS," for _, s in names]
    out.append("};")

    DEST.parent.mkdir(parents=True, exist_ok=True)
    DEST.write_text("\n".join(out), encoding="utf-8")
    print(f"[OK] {DEST}  {len(BOOK_FILES)} 本书，正文共 {total_all} 字（含标点）")


if __name__ == "__main__":
    main()
