# SPDX-License-Identifier: Apache-2.0
"""Deterministically render eight original A4 Visual Arts W13-14 aids."""

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 = "#22344c"
BLUE = "#eaf2fa"
GREEN = "#eaf5ea"
SAND = "#fff1df"
LILAC = "#f1ecf9"
GREY = "#f3f5f7"


def word(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 = 8) -> 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 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'{word(42, 64, title, 27, bold=True)}'
        f'{word(42, 101, description, 13)}'
        f'{body}{line(42, 1043, 752, 1043)}'
        f'{word(42, 1076, "SubjectNest original Foundation Visual Arts W13-14 · CC BY 4.0", 10)}'
        '</svg>\n'
    )


def source_and_choice() -> str:
    body = word(42, 147, "INTERNAL FICTION · NOT A REAL FAMILY ALBUM", 17, bold=True)
    body += box(42, 187, 710, 333, BLUE, name="story facts")
    body += word(60, 235, "STORY SAYS", 20, bold=True)
    body += word(60, 283, "Mika and Sol make cardboard boats.", 18)
    body += word(60, 329, "Ren showed how to fold the front.", 18)
    body += word(60, 375, "Sol made a paper flag.", 18)
    body += word(60, 453, "Colour and surface marks are NOT stated.", 17, bold=True)
    body += box(42, 559, 710, 434, SAND, name="artist choice")
    body += word(60, 606, "ILLUSTRATOR CHOOSES (ADULT EXAMPLE)", 18, bold=True)
    body += f'<path d="M221 736 L574 736 L523 841 L276 841 Z" fill="white" stroke="{INK}" stroke-width="5"/>'
    for x in (312, 351, 390, 429, 468):
        body += line(x, 772, x, 799, 5)
    body += word(60, 918, "A plain boat outline with short upright side marks.", 16)
    body += word(60, 967, "Those marks are invented for this picture.", 15)
    return page("Story fact or art choice?", "Fictional boat facts and an adult-invented mark treatment.", body)


def short_long_marks() -> str:
    body = word(42, 146, "SAME FICTIONAL CARD SIDE · TWO LINE LENGTHS", 17, bold=True)
    for x, title, fill in ((42, "SHORT MARKS", BLUE), (404, "LONG MARKS", GREEN)):
        body += box(x, 185, 348, 594, fill, name=title)
        body += word(x + 18, 232, title, 19, bold=True)
        body += box(x + 26, 294, 295, 356, "white", name="imaginary card side")
    for x in (111, 153, 195, 237, 279):
        body += line(x, 394, x, 437, 6)
    for x in (483, 565, 647):
        body += line(x, 349, x, 542, 7)
    body += box(42, 815, 710, 178, GREY)
    body += word(60, 864, "The picture lines differ in length.", 18, bold=True)
    body += word(60, 918, "They do not prove how a real surface feels.", 16)
    return page("Short marks, long marks", "Five short versus three long upright lines on imaginary cards.", body)


def close_spaced_marks() -> str:
    body = word(42, 146, "SAME FOUR BROAD DASHES · DIFFERENT GAPS", 18, bold=True)
    for x, title, fill in ((42, "CLOSE TOGETHER", SAND), (404, "SPACED APART", BLUE)):
        body += box(x, 185, 348, 590, fill, name=title)
        body += word(x + 18, 233, title, 18, bold=True)
        body += box(x + 25, 303, 298, 343, "white", name="fictional paper kite side")
    for x in (154, 186, 218, 250):
        body += line(x, 415, x, 511, 9)
    for x in (454, 529, 604, 679):
        body += line(x, 415, x, 511, 9)
    body += box(42, 812, 710, 183, GREY)
    body += word(60, 864, "What do the different gaps do in YOUR picture?", 17, bold=True)
    body += word(60, 922, "No repeating-unit or material-feel claim is supplied.", 15)
    return page("Close or spaced?", "Four upright dashes close on one card and spread on another.", body)


def illustration_canvas() -> str:
    body = box(42, 155, 710, 695, "white", name="blank original illustration")
    body += word(60, 202, "MY ORIGINAL ILLUSTRATION", 20, bold=True)
    body += word(60, 252, "The source says:", 16)
    body += line(205, 258, 729, 258)
    body += word(60, 321, "My chosen line length / direction / spacing:", 15)
    body += line(60, 360, 729, 360)
    body += word(60, 806, "Make, direct or describe the picture here.", 15)
    body += box(42, 884, 710, 110, GREEN)
    body += word(60, 927, "My invented part and why:", 17, bold=True)
    body += line(320, 934, 730, 934)
    body += word(60, 975, "Actual marker/placer: _________ or PLAN ONLY", 14)
    return page("Illustration canvas", "Blank source-stated and artist-invented fields around an art area.", body)


def paper_leaf(x: int, y: int, *, small: bool = False) -> str:
    scale = 0.7 if small else 1.0
    w = int(220 * scale)
    h = int(170 * scale)
    return f'<path d="M{x} {y+h//2} Q{x+w//4} {y-22} {x+w//2} {y+15} Q{x+3*w//4} {y-22} {x+w} {y+h//2} Q{x+3*w//4} {y+h+12} {x+w//2} {y+h-5} Q{x+w//4} {y+h+12} {x} {y+h//2} Z" fill="white" stroke="{INK}" stroke-width="5"/>'


def plant_view_note() -> str:
    body = word(42, 145, "SOURCE STATUS BEFORE AN ART MARK", 18, bold=True)
    body += box(42, 182, 710, 384, GREEN, name="fictional paper plant")
    body += word(60, 226, "FICTIONAL PAPER PLANT PRACTICE", 18, bold=True)
    body += paper_leaf(288, 300)
    body += word(60, 528, "One oval paper leaf with a wavy edge.", 17)
    body += box(42, 606, 710, 386, "white", name="real view or fiction note")
    body += word(60, 649, "MY SOURCE: ACTUAL APPROVED VIEW / FICTION", 17, bold=True)
    body += word(60, 701, "If actual: date, plant/viewpoint, visible feature:", 15)
    body += line(60, 741, 731, 741)
    body += word(60, 805, "My art mark choice (not a plant-change claim):", 15)
    body += line(60, 844, 731, 844)
    body += word(60, 949, "No plant touch, species guess or invented growth.", 15)
    return page("Plant view or paper fiction?", "Labelled fictional paper leaf and blank actual-source/art fields.", body)


def art_source_record() -> str:
    fields = (
        ("SOURCE / DATE / VIEW", "REAL approved source or FICTION; exact seen/stated fact.", BLUE),
        ("MY ART MARK", "Line length, direction or spacing and child's reason.", SAND),
        ("ACTUAL MARKER / SUPPORT", "Who really marked? Or PLAN ONLY?", GREEN),
        ("ACTUAL WILLING VIEWER", "Who truly saw own work? Reply or NOT SHARED.", GREY),
    )
    body = word(42, 146, "Source fact, art choice, maker and audience stay separate.", 16, bold=True)
    for i, (title, prompt, fill) in enumerate(fields):
        y = 185 + i * 201
        body += box(42, y, 710, 174, fill, name=title)
        body += word(60, y + 42, title, 18, bold=True)
        body += word(60, y + 84, prompt, 15)
        body += line(60, y + 145, 733, y + 145)
    return page("Art and source record", "Four blank fields for source, visual mark, maker and viewer.", body)


def check_u() -> str:
    body = word(42, 145, "CHECK U · FICTIONAL CARD LANTERN", 18, bold=True)
    body += box(42, 181, 710, 319, SAND, name="plain fictional lantern source")
    body += box(249, 242, 297, 204, "white", name="plain outer card", radius=0)
    body += box(307, 298, 180, 91, SAND, name="wide rectangular opening", radius=0)
    body += word(68, 475, "PLAIN OUTER BAND · ONE WIDE RECTANGULAR OPENING", 15, bold=True)
    body += word(42, 541, "Show two different invented line textures on the band.", 16)
    for y, title in ((566, "IDEA 1"), (766, "IDEA 2")):
        body += box(42, y, 710, 176, "white", name=title)
        body += word(60, y + 42, title, 18, bold=True)
    body += word(42, 995, "Story fact? Your added marks? No real light or heat.", 14)
    return page("Check U: Card lantern", "Plain fictional card object, rectangular opening and two blank art spaces.", body)


def three_bump_edge(x: int, y: int) -> str:
    return f'<path d="M{x} {y+105} Q{x+20} {y-20} {x+100} {y+45} Q{x+150} {y-35} {x+200} {y+45} Q{x+280} {y-20} {x+300} {y+105} Q{x+150} {y+217} {x} {y+105} Z" fill="white" stroke="{INK}" stroke-width="5"/>'


def check_v() -> str:
    body = word(42, 145, "CHECK V · FICTIONAL PAPER GARDEN CARDS", 17, bold=True)
    for x, title, fill in ((42, "STORY MONDAY", BLUE), (404, "STORY THURSDAY", GREEN)):
        body += box(x, 183, 348, 343, fill, name=title)
        body += word(x + 18, 226, title, 17, bold=True)
        body += three_bump_edge(x + 25, 263)
    body += word(42, 559, "Both cards show the SAME three-bump paper edge.", 16, bold=True)
    for y, title in ((589, "ART IDEA 1"), (781, "ART IDEA 2")):
        body += box(42, y, 710, 170, "white", name=title)
        body += word(60, y + 42, title, 18, bold=True)
    body += word(42, 994, "Choose a line treatment. No living plant was observed.", 14)
    return page("Check V: Same paper edge", "Two identical three-bump fictional leaf cards and blank art choices.", body)


PAGES = {
    "source-and-choice": source_and_choice,
    "short-long-marks": short_long_marks,
    "close-spaced-marks": close_spaced_marks,
    "illustration-canvas": illustration_canvas,
    "plant-view-note": plant_view_note,
    "art-source-record": art_source_record,
    "check-u-lantern": check_u,
    "check-v-edge": check_v,
}


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")
        rendered = subprocess.run(["rsvg-convert", "-f", "pdf", str(svg)], check=True, capture_output=True)
        writer = PdfWriter()
        writer.append_pages_from_reader(PdfReader(BytesIO(rendered.stdout)))
        writer.add_metadata({
            "/Title": stem,
            "/Author": "SubjectNest by NeuroForgeIO Pty Ltd",
            "/CreationDate": "D:20260930000000+10'00'",
            "/ModDate": "D:20260930000000+10'00'",
        })
        writer.write(str(pdf))
        print(f"WROTE {stem}.svg + .pdf")


if __name__ == "__main__":
    main()
