#!/usr/bin/env python3
"""Generate three original A4 SVG/PDF textual analysis aids."""

from __future__ import annotations

import argparse
import os
import subprocess
from pathlib import Path
from xml.sax.saxutils import escape

HERE = Path(__file__).resolve().parent
INK, NAVY, GREY, TINT = "#1d2631", "#234d72", "#455461", "#eaf1f7"


def words(x: int, y: int, value: str, size: int = 18, bold: bool = False,
          colour: str = INK) -> str:
    return (f'<text x="{x}" y="{y}" fill="{colour}" font-family="DejaVu Sans, sans-serif" '
            f'font-size="{size}" font-weight="{700 if bold else 400}">{escape(value)}</text>')


def box(x: int, y: int, width: int, height: int, fill: str = "white") -> str:
    return (f'<rect x="{x}" y="{y}" width="{width}" height="{height}" rx="9" '
            f'fill="{fill}" stroke="{NAVY}" stroke-width="2"/>')


def rule(x1: int, y1: int, x2: int, y2: int) -> str:
    return (f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" '
            f'stroke="{GREY}" stroke-width="2"/>')


def page(title: str, desc: str, elements: list[str]) -> str:
    return "\n".join([
        ('<svg xmlns="http://www.w3.org/2000/svg" width="210mm" height="297mm" '
         'viewBox="0 0 794 1123" role="img">'),
        f'<title>{escape(title)}</title>', f'<desc>{escape(desc)}</desc>',
        '<rect width="794" height="1123" fill="white"/>',
        box(32, 25, 730, 107, TINT),
        words(52, 63, "SUBJECTNEST / YEAR 11 / ENGLISH", 16, True, NAVY),
        words(52, 107, title, 29, True),
        *elements,
        rule(34, 1073, 760, 1073),
        words(38, 1100, "Original A4 aid · full text and tactile route supplied", 13, colour=GREY),
        '</svg>', '',
    ])


def foreground() -> str:
    out = [words(40, 166, "A text can select a real-in-story fact and still narrow the story.", 18, True),
           words(40, 195, "Read in order. All information is in the words, not the shading.", 16)]
    cards = [
        ("1  FOREGROUND: what leads?", "P leads with Mina's final point."),
        ("2  RECORD: what is stated?", "The invented score is 4–3; Mina made the last point."),
        ("3  OUTSIDE: what is missing?", "There is no complete earlier play-by-play."),
        ("4  EFFECT: what might a reader infer?", "A reader may credit the final point with the whole win."),
        ("5  BOUNDARY: what can I say?", "Celebrate the moment without assigning all earlier points."),
    ]
    for index, (head, prompt) in enumerate(cards):
        y = 226 + index * 158
        out.extend([box(46, y, 703, 140), box(59, y + 10, 677, 43, TINT),
                    words(74, y + 40, head, 18, True, NAVY),
                    words(74, y + 84, prompt, 16), rule(74, y + 113, 720, y + 113)])
    out.append(words(40, 1049, "Try it on a new source; keep maker labels attached.", 17, True))
    return page("Foreground and record",
                "Five numbered cards in vertical order: foreground, recorded facts, missing evidence, possible reader effect, bounded claim. A fictional 4–3 result is the worked example; blank lines invite transfer.", out)


def sequence() -> str:
    out = [words(40, 165, "Sequence a scene, then keep interpretation separate.", 19, True)]
    for index, label in enumerate(("1  Before", "2  Turning point", "3  After", "4  What remains open")):
        y = 206 + index * 166
        out.extend([box(50, y, 694, 148), box(64, y + 10, 666, 44, TINT),
                    words(79, y + 41, label, 18, True, NAVY),
                    rule(78, y + 92, 718, y + 92), rule(78, y + 120, 718, y + 120)])
    out.extend([box(50, 884, 694, 166, "#f7fafc"),
                words(69, 924, "NAME THE DIFFERENCE", 18, True, NAVY),
                words(69, 970, "The text states ...", 17), rule(68, 989, 720, 989),
                words(69, 1022, "I infer ... because ...", 17), rule(68, 1041, 720, 1041)])
    return page("Four sequence windows",
                "Four large numbered writing windows labelled before, turning point, after, what remains open. Bottom pair separates the text states from I infer because. Full words make the order available without colour.", out)


def arc() -> str:
    out = [words(40, 166, "Keep an old line so the reason for change is visible.", 19, True)]
    stages = [
        ("1  AUDIENCE", "Who needs this public line?"),
        ("2  EVIDENCE", "Which exact source detail must stay?"),
        ("3  POSSIBLE EFFECT", "What may the current wording suggest?"),
        ("4  LIMIT", "Which result, frame or future fact is unknown?"),
        ("5  REVISION", "Write a more useful line; explain the change."),
    ]
    for index, (head, prompt) in enumerate(stages):
        y = 209 + index * 155
        x = 45 if index % 2 == 0 else 69
        out.extend([box(x, y, 680, 135), box(x + 10, y + 9, 660, 41, TINT),
                    words(x + 23, y + 39, head, 18, True, NAVY),
                    words(x + 23, y + 80, prompt, 17),
                    rule(x + 23, y + 111, x + 655, y + 111)])
    out.extend([words(40, 1010, "Before: _________________________________", 17),
                words(40, 1047, "After: __________________________________", 17)])
    return page("Evidence to edit arc",
                "Five alternating numbered cards: audience, evidence, possible effect, limit, revision. Each has a prompt and writing line. At bottom, before and after lines preserve the edit trail.", out)


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument("--write", action="store_true")
    args = parser.parse_args()
    if not args.write:
        parser.error("pass --write to regenerate the three A4 aid pairs")
    env = {**os.environ, "SOURCE_DATE_EPOCH": "1790640000"}
    for stem, make in (("foreground-strip", foreground),
                       ("sequence-windows", sequence), ("editor-arc", arc)):
        svg = HERE / f"{stem}.svg"
        pdf = HERE / f"{stem}.pdf"
        svg.write_text(make(), encoding="utf-8")
        subprocess.run(["rsvg-convert", "--format", "pdf", "--output", str(pdf), str(svg)],
                       check=True, env=env)
        print(f"generated {svg.name} + {pdf.name}")


if __name__ == "__main__":
    main()
