#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
"""Generate five original reproducible A4 SVG/PDF subject-menu aids."""
from __future__ import annotations

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

HERE = Path(__file__).resolve().parent


def text(x: float, y: float, value: str, size: float = 4.3, bold: bool = False) -> str:
    return f'<text x="{x}" y="{y}" font-size="{size}" font-weight="{700 if bold else 400}">{escape(value)}</text>'


def rect(x: float, y: float, width: float, height: float, fill: str = "#fffefa") -> str:
    return f'<rect x="{x}" y="{y}" width="{width}" height="{height}" rx="2.5" fill="{fill}" stroke="#31566a" stroke-width="0.55"/>'


def line(x: float, y: float, x2: float) -> str:
    return f'<path d="M{x} {y}H{x2}" stroke="#31566a" stroke-width="0.36"/>'


def page(title: str, desc: str, body: list[str]) -> str:
    return f'''<svg xmlns="http://www.w3.org/2000/svg" width="210mm" height="297mm" viewBox="0 0 210 297" role="img" aria-labelledby="title desc">
<title id="title">{escape(title)}</title><desc id="desc">{escape(desc)}</desc>
<rect width="210" height="297" fill="#fffefa"/>
<g font-family="DejaVu Sans, sans-serif" fill="#173b50">{''.join(body)}</g>
<text x="13" y="287" font-family="DejaVu Sans, sans-serif" font-size="3.3" fill="#173b50">SubjectNest · original menu aid · CC BY 4.0 · neuroforge.io</text>
</svg>
'''


def science() -> str:
    b = [text(13, 18, "Science: one fair question", 8, True), text(13, 28, "Label REAL, MODEL or PLAN before writing any result.", 4.1), line(13, 34, 197)]
    for i, (head, hint) in enumerate((
        ("QUESTION + PREDICTION", "What might change? Why?"),
        ("CHANGE ONE THING", "Surface, slope or material: name it."),
        ("KEEP THESE THE SAME", "Start, object, time or reading method."),
        ("TRIALS + SOURCE", "Record units and REAL/MODEL label."),
        ("PATTERN + NEXT QUESTION", "What does the evidence allow?"),
    )):
        y = 42 + i * 45
        b += [rect(13, y, 184, 39, ("#f0f6f8", "#f6f1fa", "#f1f7ef", "#fff6e7", "#f0f6f8")[i]),
              text(18, y+9, head, 5, True), text(18, y+17, hint, 3.8), line(18, y+29, 192), line(18, y+36, 192)]
    b += [text(13, 275, "A printed number is not a measurement you took.", 4.1)]
    return page("Year 4 science fair-question mat", "Five numbered fields for question/prediction, changed factor, controls, trials/source and cautious pattern/next question. Complete linear and tactile alternative in TEXT-ALTERNATIVES.md.", b)


def hass() -> str:
    b = [text(13, 18, "HASS: read a fictional source", 8, True), text(13, 27, "H1 Share Shelf paper plan · 2026 draft · NOT a real place", 4.1), line(13, 33, 197),
         rect(13, 40, 184, 184, "#f7fafb"),
         rect(76, 49, 57, 20, "#e7f1f6"), text(88, 62, "SHELF", 5, True),
         rect(139, 53, 46, 29, "#f5f1fb"), text(145, 70, "READING MAT", 3.8, True),
         rect(19, 101, 53, 30, "#eff7ef"), text(25, 119, "BORROW 1", 4.1, True),
         rect(19, 146, 53, 30, "#eff7ef"), text(25, 164, "BORROW 2", 4.1, True),
         rect(139, 123, 46, 31, "#fff5e8"), text(145, 141, "RETURN", 4.2, True),
         '<path d="M104 206V79" stroke="#31566a" stroke-width="4" stroke-dasharray="3 2"/>',
         text(81, 217, "ENTRANCE ↑", 4.7, True),
         text(13, 237, "Source/title/date:", 4.5, True), line(60, 238, 197),
         text(13, 250, "What the plan shows:", 4.5, True), line(66, 251, 197),
         text(13, 263, "What it cannot prove:", 4.5, True), line(72, 264, 197),
         text(13, 275, "No scale, route width or user record is supplied.", 4)]
    return page("Fictional Share Shelf source map", "Top-view invented paper plan: entrance at bottom, dotted path to one shelf at top; two BORROW baskets left of path, RETURN basket right, reading mat beside shelf. No scale. Full linear and tactile equivalent in TEXT-ALTERNATIVES.md.", b)


def hpe() -> str:
    b = [text(13, 18, "HPE: choose, ask, play, repair", 8, True), text(13, 27, "No touch or public performance is required.", 4.2), line(13, 33, 197)]
    for i, (head, prompt) in enumerate((
        ("1 · ASK", "May I move the token? Wait for an answer."),
        ("2 · CHOOSE", "Move, direct, observe or pass."),
        ("3 · TRY", "Use a safe clear space and an agreed rule."),
        ("4 · NOTICE + REPAIR", "What helped? What will change next time?"),
    )):
        y = 44 + i * 51
        b += [rect(13, y, 184, 44, ("#eef6f8", "#f4f0fa", "#fff6e9", "#f0f7f0")[i]), text(18, y+10, head, 5.2, True), text(18, y+20, prompt, 4.1), line(18, y+34, 192)]
    b += [text(13, 260, "Actual movement observed?   YES / NO / NOT YET", 4.6, True),
          text(13, 273, "A paper route shows a plan, not a movement performance.", 4.1)]
    return page("Year 4 cooperative HPE choice mat", "Four numbered stages: ask permission, choose a role, try an agreed safe game, notice and repair. Actual movement observed yes/no/not yet field. Full text/tactile alternative in TEXT-ALTERNATIVES.md.", b)


def technologies() -> str:
    b = [text(13, 18, "Technologies: make and trace", 8, True), text(13, 27, "Two subjects; keep physical testing and program runs distinct.", 4.1), line(13, 33, 197),
         rect(13, 42, 184, 101, "#f0f6f8"), text(18, 53, "DESIGN · PAPER LABEL HOLDER", 5.3, True),
         text(18, 64, "Need: stand 10 seconds; fold flat; one reusable scrap.", 4),
         text(18, 76, "Idea / material:", 4.2, True), line(57, 77, 192),
         text(18, 89, "Made and tested? REAL / MODEL / PLAN", 4.2, True),
         text(18, 102, "Test result:", 4.2, True), line(50, 103, 192),
         text(18, 115, "One revision:", 4.2, True), line(55, 116, 192),
         text(18, 131, "Keep a first version so change can be inspected.", 3.9),
         rect(13, 153, 184, 112, "#fff6e9"), text(18, 164, "DIGITAL · IF / ELSE / REPEAT", 5.3, True),
         text(18, 176, "INPUT: RETURN, BORROW or HOLD", 4.1),
         text(18, 188, "IF label = RETURN → LEFT", 4.2, True),
         text(18, 200, "ELSE → RIGHT", 4.2, True),
         text(18, 212, "REPEAT for each of 3 tokens; then STOP.", 4.1),
         text(18, 226, "Trace one input / output:", 4.2, True), line(87, 227, 192),
         text(18, 239, "Actual visual program run? YES / UNPLUGGED", 4.2, True),
         text(18, 252, "Change one block, predict, then test again.", 4)]
    return page("Year 4 design and digital technologies mat", "Top half: paper holder criteria, making/test/revision fields. Bottom half: fictional RETURN/BORROW/HOLD input with IF/ELSE/REPEAT branch, trace field and actual-program/unplugged status. Full text/tactile equivalent in TEXT-ALTERNATIVES.md.", b)


def arts() -> str:
    rows = [
        ("DANCE", "near · far · pause · return", "space / tempo"),
        ("DRAMA", "goal · obstacle · turning point", "character / action"),
        ("MEDIA ARTS", "wide · close · sequence", "frame / caption"),
        ("MUSIC", "tap · rest · answer", "beat / rest / tempo"),
        ("VISUAL ARTS", "line · texture · focal word", "mark / spacing"),
    ]
    b = [text(13, 18, "The Arts: five ways to shape an idea", 8, True),
         text(13, 27, "Each form has two optional Days 11–20 blocks.", 4.2), line(13, 33, 197)]
    for i, (form, prompt, elements) in enumerate(rows):
        y = 42 + i * 44
        b += [rect(13, y, 184, 38, ("#eef6f8", "#fff6e8", "#f3eff9", "#f0f7ee", "#eef6f8")[i]),
              text(18, y+9, form, 5.1, True), text(18, y+18, prompt, 4.2), text(18, y+28, f"Choose: {elements}", 3.9)]
    b += [text(13, 269, "Actually made / sounded / moved / shared? Record the route.", 4.2)]
    return page("Year 4 five-form Arts workbench", "Five labelled rows for Dance, Drama, Media Arts, Music and Visual Arts with original prompts and elements; note actual made, sounded, moved or shared route. Full text/tactile alternative in TEXT-ALTERNATIVES.md.", b)


def main() -> None:
    for stem, maker in (("science-aid", science), ("hass-aid", hass), ("hpe-aid", hpe), ("technologies-aid", technologies), ("arts-aid", arts)):
        path = HERE / f"{stem}.svg"
        path.write_text(maker(), encoding="utf-8")
        subprocess.run(["rsvg-convert", "-f", "pdf", "-o", str(path.with_suffix(".pdf")), str(path)], check=True)
        print(path.name, path.with_suffix(".pdf").name)


if __name__ == "__main__":
    main()
