#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Витяг шаблону верстки з англійського буклета — джерело правди для рендерера.

Дає два файли на урок:

* `template.json` — по блоках, рядках і спанах: `bbox`, `x`, `y` (базова
  лінія!), `w`, `gap` до попереднього спана, індекс стилю, `leading` блока;
* `worksheet.txt` — людиночитний дамп `p<сторінка>b<блок>` → стилі → рядки,
  саме за ним пишеться переклад.

    .venv/bin/python ua_build/extract.py Level0_A1 [Level1_A1 …]
    .venv/bin/python ua_build/extract.py --a1        # усі п'ять A1
"""
import argparse
import json
import os
import sys

import fitz

from lessons import Lesson, a1_set


def style_key(s):
    return (s["font"], round(s["size"], 2), s["color"])


def page_template(page):
    d = page.get_text("dict")
    blocks = []
    for bi, b in enumerate(d["blocks"]):
        if b["type"] != 0:
            continue
        styles, smap, lines = [], {}, []
        for l in b["lines"]:
            spans, prev_end = [], None
            for s in l["spans"]:
                if not s["text"].strip():
                    continue
                k = style_key(s)
                if k not in smap:
                    smap[k] = len(styles)
                    styles.append({"font": k[0], "size": k[1], "color": k[2]})
                spans.append({
                    "text": s["text"], "s": smap[k],
                    "x": round(s["bbox"][0], 1),
                    "y": round(s["origin"][1], 1),
                    "w": round(s["bbox"][2] - s["bbox"][0], 1),
                    "gap": None if prev_end is None else round(s["bbox"][0] - prev_end, 1),
                })
                prev_end = s["bbox"][2]
            if spans:
                lines.append({"bbox": [round(v, 1) for v in l["bbox"]], "spans": spans})
        if not lines:
            continue
        ys = [ln["spans"][0]["y"] for ln in lines]
        lead = (round(sum(ys[i + 1] - ys[i] for i in range(len(ys) - 1)) / (len(ys) - 1), 2)
                if len(ys) > 1 else 0)
        blocks.append({"i": bi, "bbox": [round(v, 1) for v in b["bbox"]],
                       "styles": styles, "leading": lead, "lines": lines})
    return blocks


def worksheet(pages, tt_by_page):
    """Дамп для перекладача. Контурні прогони позначені окремо: з них
    робиться інтерактивна розмальовка (§3.2), і перекладати їх треба як
    звичайний текст, але з `render: 1`."""
    out = []
    for p in pages:
        out.append(f"\n{'=' * 60}\nСТОРІНКА {p['page'] + 1}\n{'=' * 60}")
        for b in p["blocks"]:
            key = f"p{p['page']}b{b['i']}"
            out.append(f"\n--- {key}   bbox={b['bbox']}  leading={b['leading']}")
            for si, st in enumerate(b["styles"]):
                out.append(f"    s{si}: {st['font']} {st['size']} #{st['color']:06x}")
            for ln in b["lines"]:
                segs = "  |  ".join(
                    f"[s{s['s']} x={s['x']} y={s['y']}] {s['text']}" for s in ln["spans"])
                out.append(f"    {segs}")
        stroke = tt_by_page.get(p["page"], [])
        if stroke:
            out.append(f"\n    КОНТУРНИЙ ТЕКСТ (render_mode=stroke) — {len(stroke)} прогонів:")
            for s in stroke:
                out.append(f"      {s['font']} {s['size']:.0f}pt lw={s['lw']} "
                           f"bbox={s['bbox']} → {s['text']!r}")
    return "\n".join(out)


def run(lesson):
    doc = fitz.open(lesson.src)
    pages, tt = [], {}
    for pno, page in enumerate(doc):
        pages.append({"page": pno, "blocks": page_template(page)})
        runs = []
        for s in page.get_texttrace():
            if s["type"] != 1:                       # 1 = обведення без заливки
                continue
            txt = "".join(chr(c[0]) for c in s["chars"] if c[0])
            runs.append({"font": s["font"], "size": s["size"], "lw": s.get("linewidth"),
                         "bbox": [round(v) for v in s["bbox"]], "text": txt})
        if runs:
            tt[pno] = runs
    os.makedirs(lesson.work, exist_ok=True)
    with open(lesson.template, "w", encoding="utf-8") as f:
        json.dump(pages, f, ensure_ascii=False, indent=1)
    with open(lesson.worksheet, "w", encoding="utf-8") as f:
        f.write(worksheet(pages, tt))
    nb = sum(len(p["blocks"]) for p in pages)
    ns = sum(len(l["spans"]) for p in pages for b in p["blocks"] for l in b["lines"])
    print(f"{lesson.stem}: сторінок {len(pages)}  блоків {nb}  спанів {ns}  "
          f"контурних прогонів {sum(len(v) for v in tt.values())}")
    return {"stem": lesson.stem, "pages": len(pages), "blocks": nb, "spans": ns,
            "stroke": sum(len(v) for v in tt.values())}


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("stems", nargs="*")
    ap.add_argument("--a1", action="store_true", help="усі п'ять буклетів A1")
    args = ap.parse_args()

    lessons = a1_set() if args.a1 else [Lesson(s) for s in args.stems]
    if not lessons:
        sys.exit("вкажи буклети або --a1")
    for l in lessons:
        run(l)


if __name__ == "__main__":
    sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
    main()
