#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
"""Create five original A4 vector aids; PDFs are exported from these SVGs."""
from __future__ import annotations

import html
import textwrap
from pathlib import Path

ROOT = Path(__file__).resolve().parent
INK = "#15384b"
TEAL = "#006878"
PALE = "#e8f4f2"
LINE = "#536d76"
FONT = "DejaVu Sans, sans-serif"


def esc(value: str) -> str:
    return html.escape(value, quote=True)


def text(x: float, y: float, value: str, size: float = 4, bold: bool = False, colour: str = INK) -> str:
    weight = ' font-weight="700"' if bold else ""
    return f'<text x="{x}" y="{y}" font-family="{FONT}" font-size="{size}"{weight} fill="{colour}">{esc(value)}</text>'


def wrapped(x: float, y: float, value: str, width: int, size: float = 4, gap: float = 6.2) -> str:
    return "\n".join(text(x, y + i * gap, line, size) for i, line in enumerate(textwrap.wrap(value, width=width)))


def rect(x: float, y: float, width: float, height: float, fill: str = "#fff", stroke: str = LINE, radius: float = 2) -> str:
    return f'<rect x="{x}" y="{y}" width="{width}" height="{height}" rx="{radius}" fill="{fill}" stroke="{stroke}" stroke-width=".8"/>'


def panel(x: float, y: float, width: float, height: float, label: str) -> str:
    return "\n".join(
        [
            rect(x, y, width, height),
            f'<rect x="{x}" y="{y}" width="{width}" height="12" fill="{PALE}"/>',
            text(x + 5, y + 8.3, label, 4.8, True),
        ]
    )


def page(title: str, description: str, heading: str, subtitle: str, body: str) -> str:
    start = (
        f'<svg xmlns="http://www.w3.org/2000/svg" width="210mm" height="297mm" viewBox="0 0 210 297" '
        f'role="img" aria-labelledby="title desc"><title id="title">{esc(title)}</title>'
        f'<desc id="desc">{esc(description)}</desc><rect width="210" height="297" fill="#fff"/>'
    )
    header = "\n".join(
        [
            text(14, 17, "SubjectNest  /  Foundation English  /  Weeks 35–36", 4.2, True, TEAL),
            text(14, 30, heading, 7.6, True),
            f'<path d="M14 37 H196" stroke="{TEAL}" stroke-width="1.2"/>',
            text(14, 46, subtitle, 3.8),
        ]
    )
    footer = "\n".join(
        [
            f'<path d="M14 277 H196" stroke="{LINE}" stroke-width=".6"/>',
            text(14, 286, "Point · say · sign · use AAC · move broad cards · direct an adult.", 3.3),
            text(14, 293, "Original SubjectNest vector  •  © 2026 NeuroForgeIO Pty Ltd  •  CC BY 4.0", 2.9),
        ]
    )
    return f"{start}\n{header}\n{body}\n{footer}\n</svg>\n"


def write(name: str, content: str) -> None:
    (ROOT / f"{name}.svg").write_text(content, encoding="utf-8")


scenes = [
    "Luma spread one wide paper mat on a pretend play table. Luma wanted space for a toy road.",
    "Jay brought three large paper puppets and wanted the same mat for a show. Both wanted to use it now.",
    "Luma asked, “Could we each use one side?” Jay said, “I hear you. My puppets need more room. Could we try one short turn each instead?”",
    "Luma said, “Let's try turns and ask if both of us got a chance.” They agreed to try. The story ends before the turns happen; it does not say whether the plan worked.",
]
story_parts = []
for index, (y, scene) in enumerate(zip((55, 108, 161, 214), scenes, strict=True), start=1):
    story_parts.append(panel(14, y, 182, 48, f"SCENE {index}"))
    story_parts.append(wrapped(20, y + 22, scene, 72, 4.0, 6.5))
write(
    "shared-mat-story",
    page(
        "The wide paper mat, four-scene original story",
        "Four ordered story panels. Luma wants a wide paper mat for a toy road; Jay wants it for paper puppets. Luma asks whether they can use sides; Jay asks to try short turns. They agree to try but the story ends before any turn occurs. No outcome or emotion is shown.",
        "The wide paper mat",
        "A fictional shared-place story · read scenes in order · result not yet known",
        "\n".join(story_parts),
    ),
)

fair_labels = [
    "REQUEST · what is asked?",
    "REASON OR OTHER VIEW · what does someone else need?",
    "PROPOSED TRY · what might be tested?",
    "WHAT TO ASK · who will say if it worked?",
    "ACTUAL RESULT OR NOT TESTED",
]
fair_body = "\n".join(panel(14, y, 182, 37, label) for y, label in zip((55, 98, 141, 184, 227), fair_labels, strict=True))
write(
    "fair-plan",
    page(
        "Five-field request, other view, proposed try and result mat",
        "A4 blank five-area mat read top to bottom: request, reason or other view, proposed try, what to ask, actual result or not tested. Large fields allow pointing, broad tactile cards, drawing, dictated or written responses. A proposal is not marked as a successful result.",
        "Can we make a plan to try?",
        "Hear both views. Keep a proposed turn apart from what really happened.",
        fair_body,
    ),
)

pattern_parts = [
    text(14, 56, "SOURCE D · six broad tiles in order", 4.6, True),
]
xs = (14, 76, 138)
ys = (65, 129)
for row, y in enumerate(ys):
    for col, x in enumerate(xs):
        shape = ("CIRCLE", "CIRCLE", "SQUARE")[col]
        number = row * 3 + col + 1
        pattern_parts.append(rect(x, y, 58, 55))
        pattern_parts.append(text(x + 5, y + 9, f"{number}  {shape}", 3.8, True))
        if shape == "CIRCLE":
            pattern_parts.append(f'<circle cx="{x + 29}" cy="{y + 32}" r="15" fill="white" stroke="{TEAL}" stroke-width="1.5"/>')
        else:
            pattern_parts.append(rect(x + 15, y + 18, 28, 28, "#fff", TEAL, 0))
pattern_parts.append(panel(14, 193, 182, 72, "EXTRA SHAPE FOR SOURCE E · TRIANGLE"))
pattern_parts.append(f'<polygon points="105,210 81,249 129,249" fill="white" stroke="{TEAL}" stroke-width="1.5"/>')
pattern_parts.append(text(20, 258, "Source D order: circle · circle · square · circle · circle · square", 3.5))
write(
    "pattern-shape-cards",
    page(
        "Six labelled shape tiles and one extra triangle",
        "A4 tile sheet. Six large outlined tiles in reading order: circle, circle, square, circle, circle, square. All are labelled with shape words and positions one through six. A separate large triangle is supplied for shape-location Source E. Colour does not carry the pattern.",
        "Teach a pattern with shape names",
        "Look, listen or feel the order; tell someone what comes next.",
        "\n".join(pattern_parts),
    ),
)

instruction_labels = [
    "MATERIALS · which shapes are needed?",
    "STEP 1 · what goes first?",
    "STEP 2 · what happens next or repeats?",
    "HOW TO CHECK · what should the listener show?",
]
instruction_body = "\n".join(panel(14, y, 182, 45, label) for y, label in zip((55, 109, 163, 217), instruction_labels, strict=True))
write(
    "instruction-strip",
    page(
        "Four-area specific pattern or shape instruction strip",
        "A4 blank four-area mat read top to bottom: materials, step one, step two, how to check. Large areas allow broad tactile cards, point, drawing, dictated or written directions. No correct answer or colour code is prefilled.",
        "Can someone follow your directions?",
        "Name the shape, order and place. Ask what the listener understood.",
        instruction_body,
    ),
)

listener_labels = [
    "FIRST WORDS · exact first instruction",
    "WHAT LISTENER DID OR UNDERSTOOD",
    "DIFFERENCE · what did not match?",
    "REVISED WORDS · change one useful detail",
    "STILL TO CHECK · another listener or example",
]
listener_body = "\n".join(panel(14, y, 182, 37, label) for y, label in zip((55, 98, 141, 184, 227), listener_labels, strict=True))
write(
    "listener-repair",
    page(
        "Five-area listener and instruction repair record",
        "A4 blank five-area mat read top to bottom: exact first words, listener action or understanding, difference, revised words, still to check. A teacher marks modelled listener actions separately from actual peer use. Broad tactile and dictated responses fit every field.",
        "Try · listen · repair",
        "Keep the first instruction and the useful edit side by side.",
        listener_body,
    ),
)
print("Generated 5 original A4 SVGs")
