#!/usr/bin/env python3
"""Regenerate the four original Geography A4 SVG/PDF aids."""
from __future__ import annotations

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

HERE = Path(__file__).resolve().parent
INK, BLUE, MUTED, PALE, LIGHT = '#172d39', '#245875', '#425966', '#eaf3f7', '#f6fafc'


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


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="8" '
            f'fill="{fill}" stroke="{BLUE}" stroke-width="2"/>')


def line(x1: int, y1: int, x2: int, y2: int) -> str:
    return f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" stroke="{BLUE}" stroke-width="2"/>'


def page(title: str, description: str, content: list[str]) -> str:
    return '\n'.join([
        '<svg xmlns="http://www.w3.org/2000/svg" width="210mm" height="297mm" viewBox="0 0 794 1123" role="img">',
        f'<title>{escape(title)}</title>', f'<desc>{escape(description)}</desc>',
        '<rect width="794" height="1123" fill="white"/>',
        box(32, 23, 730, 108, PALE),
        txt(49, 60, 'SUBJECTNEST / YEAR 11 / GEOGRAPHY', 16, True, BLUE),
        txt(49, 106, title, 28, True),
        *content,
        line(33, 1068, 761, 1068),
        txt(36, 1098, 'Original teaching model · full text and tactile route supplied', 13, colour=MUTED),
        '</svg>', '',
    ])


def hazard() -> str:
    rows = [
        ('1  PROCESS', 'Card B1: heavy rain and runoff raise the creek.',
         'The process may produce a hazard; no event is observed.'),
        ('2  MODEL ZONE', 'Card A: A = H; B = M; C and D = L.',
         'These are relative labels for one invented scenario.'),
        ('3  COUNTED EXPOSURE', 'B2 contains 15 model dwellings in M.',
         'Counted dwellings are not a count of people.'),
        ('4  CONDITIONS', 'Warning reach, roads and buildings are unknown.',
         'Vulnerability and capacity need separate evidence.'),
        ('5  IMPACT', 'No actual inundation or loss is recorded.',
         'A hazard-zone label is not a disaster report.'),
    ]
    content = [txt(43, 170, 'Follow the evidence; stop at the missing step.', 18, True)]
    for i, (head, a, b) in enumerate(rows):
        y = 197 + i * 166
        content += [box(42, y, 710, 145, PALE if i % 2 == 0 else 'white'),
                    txt(58, y + 37, head, 17, True, BLUE),
                    txt(58, y + 81, a, 15), txt(58, y + 120, b, 15)]
    return page('Hazard to impact',
                'Five numbered full-word steps distinguish physical process, model hazard zone, counted exposure, unknown vulnerability and capacity conditions, and unknown impact. No real hazard claim is made.', content)


def grid() -> str:
    content = [txt(43, 167, 'North is up; A to D runs west to east.', 18, True),
               txt(43, 202, 'One invented cell = 100 m × 100 m = 0.01 km².', 16),
               txt(43, 242, 'CATEGORY / DWELLINGS IN CELL', 15, True, BLUE)]
    heads = ['A · H', 'B · M', 'C · L', 'D · L']
    for j, head in enumerate(heads):
        x = 72 + j * 174
        content += [box(x, 260, 164, 62, PALE), txt(x + 13, 299, head, 16, True)]
    values = [[0, 8, 12, 4], [0, 15, 18, 5], [0, 6, 10, 3]]
    for i, row in enumerate(values):
        y = 330 + i * 128
        content += [txt(43, y + 50, str(i + 1), 19, True, BLUE)]
        for j, n in enumerate(row):
            x = 72 + j * 174
            content += [box(x, y, 164, 113, LIGHT if j % 2 == 0 else 'white'),
                        txt(x + 19, y + 49, f'{heads[j][-1]} / {n}', 20, True),
                        txt(x + 19, y + 82, 'dwellings', 15)]
    content += [box(43, 753, 708, 158, PALE),
                txt(58, 796, 'READ A RELATIONSHIP', 17, True, BLUE),
                txt(58, 835, 'B2 (M / 15) is west of C2 (L / 18).', 16),
                txt(58, 874, 'M does not mean one metre of flood depth.', 16),
                txt(43, 972, '12 model cells = 0.12 km². Not a real map.', 16, True)]
    return page('Grid reader',
                'North-up original Creekbend 3-row, 4-column model grid. A column is H with zero dwellings in each cell; B is M with 8, 15, 6; C is L with 12, 18, 10; D is L with 4, 5, 3. Each invented square is 100 metres on a side. B2 lies west of C2.', content)


def overlay() -> str:
    rows = [
        ('H  /  A1–A3', '0 + 0 + 0 = 0 dwellings', 'Do not conclude no people or road exposure.'),
        ('M  /  B1–B3', '8 + 15 + 6 = 29 dwellings', 'A middle category can contain many assets.'),
        ('L  /  C and D', '12+4+18+5+10+3 = 52 dwellings', 'Lower label does not mean zero impact.'),
    ]
    content = [txt(43, 166, 'Overlay a model category with a separate count layer.', 17, True)]
    for i, (head, count, note) in enumerate(rows):
        y = 207 + 216 * i
        content += [box(43, y, 708, 190, PALE if i % 2 == 0 else 'white'),
                    txt(60, y + 43, head, 19, True, BLUE),
                    txt(60, y + 94, count, 18, True),
                    txt(60, y + 145, note, 15)]
    content += [box(43, 888, 708, 105, LIGHT),
                txt(58, 930, 'NOT A RISK PROBABILITY OR DAMAGE FORECAST', 16, True, BLUE),
                txt(58, 965, 'People, depth, buildings and response are unmeasured.', 15)]
    return page('Overlay tally',
                'Three separate model inundation categories are overlaid with invented dwellings: H zero, M 29, L 52. Full written arithmetic and cautions show that a dwelling count does not measure people, losses or probability.', content)


def risk() -> str:
    rows = [
        ('SAME HAZARD + EXPOSURE', 'Eastbank and Westbank: 20 dwellings each in M.'),
        ('DIFFERENT CAPACITY EVIDENCE', 'East: rehearsed warning; two checked possible routes.'),
        ('SYSTEM GAP TO INVESTIGATE', 'West: warning reach untested; crossing unverified.'),
        ('CAUTIOUS INFERENCE', 'Consequences may differ; no losses are reported.'),
        ('ACTION + EVIDENCE', 'Test warning reach and ask authority to verify routes.'),
    ]
    content = [txt(43, 164, 'Compare systems, not stereotypes about residents.', 18, True)]
    for i, (head, value) in enumerate(rows):
        y = 198 + i * 162
        content += [box(43, y, 708, 143, PALE if i % 2 == 0 else 'white'),
                    txt(59, y + 46, f'{i + 1}  {head}', 16, True, BLUE),
                    txt(59, y + 96, value, 15)]
    content += [txt(43, 1030, 'Invented profiles ≠ required real two-place case study.', 15, True)]
    return page('Risk evidence board',
                'Five labelled steps compare equal invented M-zone exposure in Eastbank and Westbank, different warning and route capacity evidence, uncertainty about outcomes, and an authority-verified next action. No country development or resident trait is inferred.', content)


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument('--write', action='store_true')
    if not parser.parse_args().write:
        parser.error('pass --write to regenerate the four original A4 pairs')
    env = {**os.environ, 'SOURCE_DATE_EPOCH': '1790640000'}
    for stem, maker in (('hazard-to-impact', hazard), ('grid-reader', grid),
                        ('overlay-tally', overlay), ('risk-evidence', risk)):
        svg, pdf = HERE / f'{stem}.svg', HERE / f'{stem}.pdf'
        svg.write_text(maker(), encoding='utf-8')
        subprocess.run(['rsvg-convert', '--format', 'pdf', '--output', str(pdf), str(svg)],
                       env=env, check=True)
        print(f'{stem}: SVG + PDF')


if __name__ == '__main__':
    main()
