# SPDX-License-Identifier: Apache-2.0
"""Build the eight original A4 Visual Arts W9-10 SVG/PDF aid pairs."""

from __future__ import annotations

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

from pypdf import PdfReader, PdfWriter

HERE = Path(__file__).resolve().parent
INK = "#21334b"
BLUE = "#4388d1"
ORANGE = "#e48c3e"
PALE_BLUE = "#e9f3fb"
PALE_ORANGE = "#fff0df"
PALE_GREEN = "#eaf5ea"
GREY = "#f3f5f7"


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


def box(x: int, y: int, w: int, h: int, fill: str = "white", *, name: str = "", radius: int = 9) -> str:
    data = f' data-part="{escape(name)}"' if name else ""
    return f'<rect x="{x}" y="{y}" width="{w}" height="{h}" rx="{radius}" fill="{fill}" stroke="{INK}" stroke-width="2"{data}/>'


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


def circle(cx: int, cy: int, r: int, fill: str = "white", width: int = 3) -> str:
    return f'<circle cx="{cx}" cy="{cy}" r="{r}" fill="{fill}" stroke="{INK}" stroke-width="{width}"/>'


def polygon(points: str, fill: str = "white", width: int = 3) -> str:
    return f'<polygon points="{points}" fill="{fill}" stroke="{INK}" stroke-width="{width}"/>'


def page(title: str, description: 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(description)}</desc>'
        '<rect width="794" height="1123" fill="white"/>'
        f'{words(42, 63, title, 27, bold=True)}'
        f'{words(42, 100, description, 13)}'
        f'{body}{line(42, 1042, 752, 1042)}'
        f'{words(42, 1075, "SubjectNest original Foundation Visual Arts W9-10 · CC BY 4.0", 10)}'
        '</svg>\n'
    )


def colour_and_cue() -> str:
    body = words(42, 148, "TWO CUES FOR EACH PART", 20, bold=True)
    for x, fill, label in ((42, PALE_BLUE, "BLUE CIRCLE + DOTS"), (404, PALE_ORANGE, "ORANGE TRIANGLE + LINES")):
        body += box(x, 185, 348, 514, fill, name=label)
        body += words(x + 17, 229, label, 18, bold=True)
    body += circle(216, 417, 113, BLUE, 5)
    for x, y in ((170, 388), (216, 388), (262, 388), (193, 442), (239, 442)):
        body += circle(x, y, 8, "white", 2)
    body += polygon("578,302 474,526 682,526", ORANGE, 5)
    for yy in (428, 458, 488):
        body += line(541, yy, 616, yy, 7)
    body += box(42, 744, 710, 246, GREY)
    body += words(60, 795, "If colour goes away, the shape and marks remain.", 18, bold=True)
    body += words(60, 846, "Name the colour. Then find a second clue.", 17)
    body += words(60, 915, "Choose your own combination for an imagined object.", 15)
    return page("Colour and another clue", "Circle with dots; triangle with lines; both also have colour names.", body)


def toolbox(x: int, y: int, *, handle_striped: bool) -> str:
    body = box(x + 15, y + 100, 280, 164, "white", name="box")
    body += box(x + 104, y + 35, 100, 68, "white", name="handle")
    if handle_striped:
        for xx in (x + 122, x + 146, x + 170, x + 194):
            body += line(xx, y + 48, xx, y + 90, 6)
    else:
        for xx in (x + 50, x + 105, x + 160, x + 215, x + 270):
            body += line(xx, y + 128, xx, y + 228, 6)
    return body


def two_attention_choices() -> str:
    body = words(42, 148, "SAME INVENTED TOOLBOX · TWO STRIPE LOCATIONS", 18, bold=True)
    for x, label, focus, is_handle in ((42, "OPTION A", "STRIPED HANDLE", True), (404, "OPTION B", "STRIPED BOX", False)):
        body += box(x, 188, 348, 542, PALE_BLUE if is_handle else PALE_ORANGE, name=label)
        body += words(x + 18, 233, label, 20, bold=True)
        body += toolbox(x + 20, 296, handle_striped=is_handle)
        body += words(x + 19, 664, focus, 17, bold=True)
    body += box(42, 771, 710, 220, GREY)
    body += words(60, 821, "What would YOU want a viewer to find first?", 18, bold=True)
    body += words(60, 874, "A choice is an intention; no viewer has been tested.", 16)
    body += words(60, 937, "Stripes can be found without any colour.", 16)
    return page("Two ways to draw attention", "One fictional toolbox, with stripes on the handle or on the box.", body)


def what_i_found_card() -> str:
    body = words(42, 147, "ADULT MODEL: A MADE-UP STORY FINDING", 18, bold=True)
    body += box(42, 183, 710, 344, PALE_GREEN, name="fictional model")
    body += words(60, 229, "FICTIONAL: square handle on a round box", 19, bold=True)
    body += circle(283, 366, 81, "white", 5)
    body += box(487, 318, 86, 86, "#8ebc87", name="green square handle", radius=0)
    for xx in (500, 519, 538, 557):
        body += line(xx, 327, xx + 19, 392, 3)
    body += words(60, 486, "Chosen detail: GREEN + CROSSHATCH square handle", 16)
    body += box(42, 566, 710, 428, "white", name="child art space")
    body += words(60, 609, "MY SOURCE:  REAL + DATE  /  MADE UP", 18, bold=True)
    body += line(60, 647, 733, 647)
    body += words(60, 705, "My chosen detail and two cues:", 17)
    body += line(60, 742, 733, 742)
    body += words(60, 974, "Blank work area or describe the exact card aloud.", 14)
    return page("Show one thing I found", "Fictional square-handle model and a blank source-labelled art card.", body)


def display_card() -> str:
    body = box(42, 155, 710, 707, "white", name="blank display art area")
    body += words(62, 203, "MY ORIGINAL ART CARD", 20, bold=True)
    body += words(62, 251, "The part I want found:", 17)
    body += line(275, 257, 720, 257)
    body += words(62, 339, "Make, direct or describe the picture here.", 17)
    body += line(62, 729, 731, 729)
    body += words(62, 797, "Two cues (one works without colour):", 16)
    body += box(42, 882, 710, 113, PALE_ORANGE, name="revision note")
    body += words(60, 924, "I kept/changed:", 17, bold=True)
    body += line(225, 929, 730, 929)
    body += words(60, 973, "Source REAL + DATE / MADE UP · actual maker / PLAN ONLY", 14)
    return page("My small display card", "Large blank art area, two-cue prompt, source and revision note.", body)


def first_now_view() -> str:
    body = words(42, 145, "TEACHER-MADE FICTIONAL BASKET DRAFTS", 18, bold=True)
    for x, title, now in ((42, "FIRST", False), (404, "NOW", True)):
        body += box(x, 185, 348, 472, PALE_BLUE if not now else PALE_GREEN, name=title)
        body += words(x + 19, 230, title, 21, bold=True)
        body += box(x + 59, 393, 231, 174, "white", name="basket")
        body += box(x + 136, 302, 75, 75, BLUE, name="blue square", radius=0)
        if now:
            body += box(x + 124, 290, 99, 99, "none", name="wide outline", radius=0)
            body += box(x + 115, 281, 117, 117, "none", name="wide outer outline", radius=0)
        body += words(x + 19, 616, "BLUE SQUARE + OUTLINE" if now else "BLUE SQUARE ONLY", 16, bold=True)
    body += box(42, 707, 710, 284, GREY, name="reflection prompts")
    body += words(60, 755, "What stayed? The square and its named colour.", 17)
    body += words(60, 807, "What changed? A wide outline was added.", 17)
    body += words(60, 859, "These are today's adult drafts, not a child's progress.", 15)
    body += words(60, 927, "Your art choice: keep ___; try ___; because ___.", 17, bold=True)
    return page("First and now: a choice", "Fictional blue square on basket; now draft adds a wide outline.", body)


def art_record() -> str:
    body = words(42, 146, "Keep intention, making and audience separate.", 17, bold=True)
    entries = (
        ("MY ART IDEA / FOCUS", "What should be found? Which two cues?", PALE_BLUE),
        ("FIRST / NOW / WHY", "Exact kept or changed feature and child reason.", PALE_ORANGE),
        ("SOURCE / ACTUAL MAKER", "REAL + DATE / FICTION · who marked or PLAN ONLY?", PALE_GREEN),
        ("ACTUAL WILLING VIEWER", "Who truly saw it? Exact response or NOT SHARED.", GREY),
    )
    for i, (title, prompt, fill) in enumerate(entries):
        y = 188 + i * 201
        body += box(42, y, 710, 174, fill, name=title)
        body += words(60, y + 42, title, 18, bold=True)
        body += words(60, y + 85, prompt, 15)
        body += line(60, y + 144, 734, y + 144)
    return page("My art decision record", "Four blank fields for focus, revision, source/maker and real audience.", body)


def check_q() -> str:
    body = words(42, 148, "CHECK Q · FICTIONAL SEED-POD CART", 18, bold=True)
    body += box(42, 180, 710, 326, PALE_GREEN, name="fictional cart source")
    body += box(150, 371, 473, 45, "white", name="long flat tray", radius=0)
    body += f'<ellipse cx="380" cy="319" rx="105" ry="62" fill="white" stroke="{INK}" stroke-width="4"/>'
    body += f'<path d="M623 372 H667 V302 H643" fill="none" stroke="{INK}" stroke-width="8"/>'
    body += circle(231, 445, 24, "white") + circle(561, 445, 24, "white")
    body += words(76, 479, "LONG TRAY", 14, bold=True)
    body += words(310, 250, "OVAL POD BOX", 15, bold=True)
    body += words(552, 269, "HOOK HANDLE", 14, bold=True)
    body += words(42, 541, "Choose ONE part. Show TWO different cue ideas.", 17)
    for y, title in ((564, "IDEA 1"), (768, "IDEA 2")):
        body += box(42, y, 710, 179, "white", name=title)
        body += words(60, y + 43, title, 18, bold=True)
    body += words(42, 996, "Choose one. What clue remains without colour?", 15)
    return page("Check Q: Imaginary cart", "Long tray, one oval pod box, hook handle and two blank art ideas.", body)


def check_r() -> str:
    body = words(42, 148, "CHECK R · ADULT'S FICTIONAL FIRST DRAFT", 18, bold=True)
    body += box(42, 181, 710, 373, PALE_BLUE, name="fictional first draft")
    body += circle(397, 365, 117, BLUE, 4)
    body += polygon("397,312 383,391 416,391", "white", 3)
    body += words(82, 530, "FIRST: ROUND BLUE FACE + SMALL TRIANGLE POINTER", 16, bold=True)
    body += box(42, 590, 710, 358, "white", name="blank now art space")
    body += words(60, 637, "MY NOW VERSION · choose a part to find", 18, bold=True)
    body += words(60, 899, "Keep/change/why? What clue works without colour?", 15)
    body += words(42, 996, "This is not a real station sign, timetable or past child work.", 14)
    return page("Check R: Imaginary clock", "Fictional first round blue face with small triangular pointer; now blank.", body)


PAGES = {
    "colour-and-cue": colour_and_cue,
    "two-attention-choices": two_attention_choices,
    "what-i-found-card": what_i_found_card,
    "display-card": display_card,
    "first-now-view": first_now_view,
    "art-record": art_record,
    "check-q-seed-cart": check_q,
    "check-r-clock": check_r,
}


def main() -> None:
    for stem, make in PAGES.items():
        svg = make()
        (HERE / f"{stem}.svg").write_text(svg, encoding="utf-8")
        raw_pdf = subprocess.run(
            ["rsvg-convert", "-f", "pdf", str(HERE / f"{stem}.svg")],
            check=True,
            capture_output=True,
        ).stdout
        reader = PdfReader(BytesIO(raw_pdf))
        writer = PdfWriter()
        writer.append_pages_from_reader(reader)
        writer.add_metadata({"/Title": stem, "/Author": "SubjectNest by NeuroForgeIO Pty Ltd", "/CreationDate": "D:20260930000000+10'00'", "/ModDate": "D:20260930000000+10'00'"})
        with (HERE / f"{stem}.pdf").open("wb") as file:
            writer.write(file)
        print(stem)


if __name__ == "__main__":
    main()
