#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
"""Generate five original, text-selectable A4 Foundation maths aids."""
from __future__ import annotations

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

HERE = Path(__file__).resolve().parent
INK = "#18364a"
BLUE = "#eaf4f8"
GREEN = "#eef7ec"
PEACH = "#fff0e4"


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


def word(x: int, y: int, value: str, size: int = 20, weight: int = 400) -> str:
    return (
        f'<text x="{x}" y="{y}" fill="{INK}" font-family="DejaVu Sans" '
        f'font-size="{size}" font-weight="{weight}">{escape(value)}</text>'
    )


def line(x1: int, y1: int, x2: int, y2: int) -> str:
    return (
        f'<path d="M{x1} {y1} L{x2} {y2}" fill="none" '
        f'stroke="{INK}" stroke-width="2"/>'
    )


def page(title: str, desc: str, body: str) -> str:
    return (
        '<svg xmlns="http://www.w3.org/2000/svg" width="210mm" height="297mm" '
        'viewBox="0 0 794 1123" role="img">'
        f'<title>{escape(title)}</title><desc>{escape(desc)}</desc>'
        '<rect width="794" height="1123" fill="#ffffff"/>'
        f'{word(45, 70, title, 28, 700)}'
        f'{word(45, 106, desc, 13)}'
        f'{body}'
        f'{line(45, 1052, 749, 1052)}'
        f'{word(45, 1080, "SubjectNest · original Foundation maths aid · CC BY 4.0", 11)}'
        '</svg>\n'
    )


def track() -> str:
    b = word(45, 158, "Reference: count each step from zero to twenty", 18, 700)
    for row, nums in enumerate((range(11), range(11, 21))):
        y = 190 + row * 116
        for i, n in enumerate(nums):
            x = 45 + i * 63
            b += box(x, y, 57, 76, BLUE if row == 0 else GREEN)
            b += word(x + (14 if n < 10 else 7), y + 49, str(n), 25, 700)
        if row == 0:
            b += word(45, y + 98, "Continue to the next strip below.", 13)
    b += word(45, 455, "Build: place loose numeral cards on the blank track", 18, 700)
    for row, n in enumerate((11, 10)):
        y = 485 + row * 118
        for i in range(n):
            x = 45 + i * 63
            b += box(x, y, 57, 76, "white")
            if row == 0 and i in (0, 10):
                b += word(x + (20 if i == 0 else 11), y + 47, str(i), 19, 700)
            if row == 1 and i == 9:
                b += word(x + 9, y + 47, "20", 19, 700)
        b += word(45, y + 100, "0 to 10" if row == 0 else "11 to 20; count on from the strip above", 13)
    b += box(45, 775, 704, 207, PEACH)
    b += word(65, 817, "Say how you know", 20, 700)
    b += word(65, 855, "Which number comes just before? Just after? Between?", 16)
    b += word(65, 889, "Point, speak, sign, use AAC, or direct a helper.", 15)
    b += line(65, 925, 725, 925)
    return page("Zero to twenty: reference and build", "Numeral order is position, not the length of a card.", b)


def count_mat() -> str:
    b = word(45, 158, "Move each large piece exactly once", 18, 700)
    b += box(45, 190, 333, 620, BLUE) + box(416, 190, 333, 620, GREEN)
    b += word(68, 230, "TO COUNT", 23, 700) + word(439, 230, "COUNTED", 23, 700)
    for col in (45, 416):
        for row in range(4):
            b += line(col + 24, 336 + row * 105, col + 309, 336 + row * 105)
    b += box(45, 840, 704, 155, PEACH)
    b += word(68, 880, "Last count word = how many in this set", 18, 700)
    b += word(68, 918, "A total: ________      B total: ________", 17)
    b += word(68, 952, "Compare like pieces by count or one-to-one pairs.", 14)
    return page("Count once, then compare", "Track each piece; do not decide by row length alone.", b)


def part_whole() -> str:
    b = word(45, 158, "Keep the two parts visible before combining", 18, 700)
    b += box(45, 195, 320, 290, BLUE) + box(429, 195, 320, 290, GREEN)
    b += word(70, 238, "PART 1", 24, 700) + word(454, 238, "PART 2", 24, 700)
    b += word(45, 550, "Move both parts down; every piece still counts once.", 17)
    b += box(45, 580, 704, 260, PEACH) + word(70, 625, "WHOLE", 24, 700)
    b += box(45, 865, 704, 126, "white")
    b += word(70, 907, "Part 1: ____    Part 2: ____    Whole: ____", 18)
    b += word(70, 944, "Count, subitise a small part, or direct a helper.", 14)
    return page("Two parts make a whole", "Use broad pieces for collections no greater than ten.", b)


def change_story() -> str:
    b = word(45, 158, "Read the action before choosing a movement", 18, 700)
    ys = (190, 420, 650)
    for y, label, fill in zip(ys, ("START", "CHANGE: ADD IN or TAKE AWAY", "END: HOW MANY NOW?"), (BLUE, PEACH, GREEN)):
        b += box(45, y, 704, 190, fill)
        b += word(68, y + 45, label, 23, 700)
        b += line(68, y + 150, 720, y + 150)
    b += box(45, 880, 704, 112, "white")
    b += word(68, 923, "What moved? Which pieces does the question ask about?", 16)
    b += word(68, 959, "Keep TAKEN AWAY pieces in a separate used pocket.", 14)
    return page("A story changes a collection", "Act out start, change and end with large paper cards.", b)


def checks() -> str:
    b = box(45, 150, 704, 370, BLUE)
    b += word(68, 193, "TEACHER HELD · Check A · Day 155", 20, 700)
    b += word(68, 237, "A: 12 identical broad star cards, spread out", 17)
    b += word(68, 270, "B: 19 identical broad star cards, close together", 17)
    b += word(68, 303, "Empty pocket: no hidden card", 17)
    b += word(68, 347, "Loose numerals: 0, 11, 12, 13, 18, 19, 20", 17)
    b += word(68, 393, "Ask: zero, both counts, more, order 11 / 12 / 13.", 14)
    b += word(68, 430, "Precount privately; do not say the totals to the child.", 14)
    b += box(45, 560, 704, 360, GREEN)
    b += word(68, 603, "TEACHER HELD · Check B · Day 160", 20, 700)
    b += word(68, 647, "Story 1: 6 badge cards; add 3; ask END.", 17)
    b += word(68, 681, "Story 2: reset; 8 flag cards; take away 5; ask LEFT.", 17)
    b += word(68, 727, "Use separate large sets and a USED pocket.", 15)
    b += word(68, 766, "Record first child-controlled model before feedback.", 15)
    b += word(68, 806, "Key is public by URL; these are not secure exams.", 14)
    b += word(68, 845, "Full clean prompts and key are in separate files.", 14)
    b += word(45, 980, "Do not display with routine practice before the named day.", 14, 700)
    return page("Fresh checks: teacher preparation", "Two new fictional cases. Keep away from practice tables.", b)


PAGES = {
    "zero-to-twenty-track": track,
    "count-once-mat": count_mat,
    "part-whole-tray": part_whole,
    "change-story-mat": change_story,
    "teacher-held-checks": checks,
}


def main() -> None:
    for stem, make in PAGES.items():
        svg = HERE / f"{stem}.svg"
        pdf = HERE / f"{stem}.pdf"
        svg.write_text(make(), encoding="utf-8")
        subprocess.run(
            ["rsvg-convert", "-f", "pdf", "-o", str(pdf), str(svg)],
            check=True,
        )
        print(stem)


if __name__ == "__main__":
    main()
