"""Writes a deed of assignment claiming the second part of the archival
standard, at level U.

Level U adds one promise to level B: every mark of ink drawn on the page
says which letter it stands for, so a registry searching thirty thousand
deeds finds this one, and a clerk copying a clause out of it gets the
clause. Nothing about the layout changes for it.

Whether the result really is PDF/A-2U is not for us to say. `veraPDF` says,
and `scripts/check_archival.sh` asks it.

The words of the page and of its metadata are held in `Words`, once per language,
and `HQF_PDF_LANG` picks which set the record is written in.

Usage: `python examples/write_pdfa2u.py [out.pdf] [font.ttf]`
       `HQF_PDF_LANG=fr python examples/write_pdfa2u.py`
"""

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

import _language
import _licence
import _out

import hqf_pdf

# When the record was drawn up. The library never reads the clock — a document that
# stamped itself with the time would be a different file on every build — so the caller
# says when.
ISSUED = "2026-04-17T10:15:00+02:00"

# Who the file says wrote it, and what produced it, in every language alike.
AUTHOR = "HQF Development"
PRODUCER = "hqf-pdf-server"

@dataclass(frozen=True)
class Words:
    """Every word the deed is written in, in one language."""

    # What the file says it is, in its metadata.
    title: str
    # What the file says it is about, in its metadata.
    subject: str
    # The heading at the top of the page.
    heading: str
    # The line under the heading saying what the record is filed under.
    reference: str
    # What the page says of the part it claims.
    body: str
    # What each line of the record asks, one a line.
    labels: str
    # What each line of the record answers, beside its label.
    answers: str


# The deed in English.
ENGLISH = Words(
    title="Deed of assignment, ACME/2026/0417",
    subject="A record whose every word can be searched for and copied out",
    heading="Deed of assignment",
    reference="Reference ACME/2026/0417, filed 17 April 2026",
    body=(
        "This deed claims the second part of the archival standard at the level above "
        "the plain one: on top of the promise that the page keeps its looks, every "
        "mark of ink drawn on it says which letter it stands for. A registry searching "
        "thirty thousand deeds for a reference finds this one; a clerk copying a "
        "clause out of it gets the clause, not a row of question marks. That is the "
        "whole of the difference between the two levels. Nothing about the layout "
        "changes, and nothing is added to the page."
    ),
    labels="Assignor\nAssignee\nEffective",
    answers="Ateliers du Nord, Lille\nACME Industries, Rouen\n1 May 2026",
)


# The deed in French.
FRENCH = Words(
    title="Acte de cession, ACME/2026/0417",
    subject="Un document dont chaque mot peut être recherché et recopié",
    heading="Acte de cession",
    reference="Référence ACME/2026/0417, enregistrée le 17 avril 2026",
    body=(
        ("Cet acte déclare suivre la deuxième partie de la norme d’archivage, au "
         "niveau situé juste au-dessus du plus simple : en plus de la promesse que la "
         "page garde son apparence, chaque trace d’encre dit quelle lettre elle "
         "représente. Un greffe qui cherche une référence parmi trente mille actes "
         "trouve celui-ci ; un clerc qui en recopie une clause obtient la clause, et "
         "non une rangée de points d’interrogation. C’est toute la différence entre "
         "les deux niveaux : la mise en page ne change en rien, et rien n’est ajouté à"
         " la page.")
    ),
    labels="Cédant\nCessionnaire\nPrise d’effet",
    answers="Ateliers du Nord, Lille\nACME Industries, Rouen\n1er mai 2026",
)


# The deed in German.
GERMAN = Words(
    title="Abtretungsurkunde, ACME/2026/0417",
    subject="Ein Dokument, in dem sich jedes Wort suchen und herauskopieren lässt",
    heading="Abtretungsurkunde",
    reference="Aktenzeichen ACME/2026/0417, eingereicht am 17. April 2026",
    body=(
        ("Diese Urkunde erklärt Konformität mit dem zweiten Teil der Archivnorm, auf "
         "der Stufe über der einfachen: Zusätzlich zur Zusage, dass die Seite ihr "
         "Aussehen behält, gibt jede darauf gesetzte Druckspur an, für welchen "
         "Buchstaben sie steht. Ein Register, das dreißigtausend Urkunden nach einem "
         "Aktenzeichen durchsucht, findet diese; wer eine Klausel daraus "
         "herauskopiert, erhält die Klausel und keine Reihe von Fragezeichen. Das ist "
         "der ganze Unterschied zwischen den beiden Stufen. Am Layout ändert sich "
         "nichts, und der Seite wird nichts hinzugefügt.")
    ),
    labels="Zedent\nZessionar\nWirksam ab",
    answers="Ateliers du Nord, Lille\nACME Industries, Rouen\n1. Mai 2026",
)


# The deed in Spanish.
SPANISH = Words(
    title="Escritura de cesión, ACME/2026/0417",
    subject="Un documento en el que cada palabra se puede buscar y copiar",
    heading="Escritura de cesión",
    reference="Referencia ACME/2026/0417, registrada el 17 de abril de 2026",
    body=(
        "Esta escritura declara cumplir la segunda parte de la norma de archivo, en el "
        "nivel por encima del básico: además de prometer que la página conserva su "
        "aspecto, cada trazo de tinta dice qué letra representa. Un registro que busca "
        "una referencia entre treinta mil escrituras encuentra esta; un oficial que "
        "copia una cláusula obtiene la cláusula, no una hilera de signos de "
        "interrogación. Esa es toda la diferencia entre los dos niveles. La "
        "maquetación no cambia en nada y no se añade nada a la página."
    ),
    labels="Cedente\nCesionario\nFecha de efecto",
    answers="Ateliers du Nord, Lille\nACME Industries, Rouen\n1 de mayo de 2026",
)


# The deed in Italian.
ITALIAN = Words(
    title="Atto di cessione, ACME/2026/0417",
    subject="Un documento di cui ogni parola si può cercare e copiare",
    heading="Atto di cessione",
    reference="Riferimento ACME/2026/0417, depositato il 17 aprile 2026",
    body=(
        ("Quest’atto dichiara di rispettare la seconda parte della norma di "
         "archiviazione, al livello sopra quello di base: oltre alla promessa che la "
         "pagina conservi il suo aspetto, ogni segno d’inchiostro dice quale lettera "
         "rappresenta. Un ufficio che cerca un riferimento fra trentamila atti trova "
         "quest’atto; un impiegato che ne copia una clausola ottiene la clausola, non "
         "una fila di punti interrogativi. Tutta la differenza fra i due livelli è "
         "qui. L’impaginazione non cambia in nulla e alla pagina non si aggiunge "
         "niente.")
    ),
    labels="Cedente\nCessionario\nDecorrenza",
    answers="Ateliers du Nord, Lille\nACME Industries, Rouen\n1° maggio 2026",
)


# The deed in Portuguese.
PORTUGUESE = Words(
    title="Escritura de cessão, ACME/2026/0417",
    subject="Um documento em que cada palavra pode ser pesquisada e copiada",
    heading="Escritura de cessão",
    reference="Referência ACME/2026/0417, registada a 17 de abril de 2026",
    body=(
        ("Esta escritura declara cumprir a segunda parte da norma de arquivo, no nível"
         " acima do básico: além da promessa de que a página mantém o seu aspeto, cada"
         " traço de tinta diz que letra representa. Uma conservatória que procure uma "
         "referência entre trinta mil escrituras encontra esta; um funcionário que "
         "copia uma cláusula obtém a cláusula, e não uma fila de pontos de "
         "interrogação. É essa toda a diferença entre os dois níveis. A paginação não "
         "muda em nada e nada é acrescentado à página.")
    ),
    labels="Cedente\nCessionário\nEm vigor a partir de",
    answers="Ateliers du Nord, Lille\nACME Industries, Rouen\n1 de maio de 2026",
)


# The deed in Dutch.
DUTCH = Words(
    title="Akte van overdracht, ACME/2026/0417",
    subject="Een document waarvan elk woord doorzocht en overgenomen kan worden",
    heading="Akte van overdracht",
    reference="Kenmerk ACME/2026/0417, ingediend op 17 april 2026",
    body=(
        ("Deze akte verklaart te voldoen aan het tweede deel van de archiefnorm, op "
         "het niveau boven het eenvoudige: bovenop de belofte dat de pagina haar "
         "uiterlijk behoudt, zegt elk inktspoor voor welke letter het staat. Een "
         "register dat dertigduizend akten naar een kenmerk doorzoekt, vindt deze; een"
         " griffier die er een clausule uit overneemt, krijgt de clausule en geen rij "
         "vraagtekens. Dat is het hele verschil tussen de twee niveaus. Aan de opmaak "
         "verandert niets, en er komt niets bij op de pagina.")
    ),
    labels="Overdrager\nVerkrijger\nIngangsdatum",
    answers="Ateliers du Nord, Lille\nACME Industries, Rouen\n1 mei 2026",
)

# Every language the example is written in. A language is added by writing its own set
# of words and naming it here.
WORDS = {
    _language.ENGLISH: ENGLISH,
    _language.FRENCH: FRENCH,
    _language.GERMAN: GERMAN,
    _language.SPANISH: SPANISH,
    _language.ITALIAN: ITALIAN,
    _language.PORTUGUESE: PORTUGUESE,
    _language.DUTCH: DUTCH,
}


# The blocks of words the page carries, in the order it draws them: the box each goes
# in, the size it is set at, and the leading and alignment where it states them. A block
# the request states in several runs is one run of words here.
BLOCKS = (
    {
        "text": lambda words: words.heading,
        "size": 20.0,
        "left": 72.0,
        "top": 782.0,
        "width": 451.0,
        "set": None,
    },
    {
        "text": lambda words: words.reference,
        "size": 10.5,
        "left": 72.0,
        "top": 750.0,
        "width": 451.0,
        "set": None,
    },
    {
        "text": lambda words: words.body,
        "size": 11.0,
        "left": 72.0,
        "top": 716.0,
        "width": 451.0,
        "set": (16.0, hqf_pdf.Align.Justify),
    },
    {
        "text": lambda words: words.labels,
        "size": 11.0,
        "left": 72.0,
        "top": 576.0,
        "width": 451.0,
        "set": (17.0, hqf_pdf.Align.Left),
    },
    {
        "text": lambda words: words.answers,
        "size": 11.0,
        "left": 200.0,
        "top": 576.0,
        "width": 323.0,
        "set": (17.0, hqf_pdf.Align.Left),
    },
)


def sheet(handle: hqf_pdf.FontHandle, words: Words) -> hqf_pdf.Page:
    """The one page, block by block."""
    content = hqf_pdf.Content()
    for block in BLOCKS:
        settings = {}
        if block["set"] is not None:
            leading, align = block["set"]
            settings = {"leading": leading, "align": align}
        flow = hqf_pdf.TextFlow(handle, block["size"], **settings)
        lines = flow.break_lines(block["text"](words), block["width"])
        # The Python side opens and closes the text object itself, where the Rust side
        # leaves that to the caller.
        flow.draw(content, lines, block["left"], block["top"], block["width"])

    page = hqf_pdf.Page.a4()
    page.set_content(content)
    return page


def main() -> None:
    """Writes the file, and says where it went."""
    language = _language.from_environment()
    words = _language.words_of(WORDS, language)

    # A named file is written as named; the default one carries the language, so the
    # languages do not overwrite each other in `tmp/`.
    out = _out.output_path(Path(_language.file_name("pdfa2u.pdf", language)).stem)

    document = hqf_pdf.Document()
    document.set_license(_licence.licensed())
    document.set_conformance(hqf_pdf.PdfA.A2U)
    document.set_metadata(
        hqf_pdf.Metadata(
            title=words.title,
            author=AUTHOR,
            subject=words.subject,
            producer=PRODUCER,
            created=ISSUED,
        )
    )

    handle = document.add_font(hqf_pdf.Font.from_path(_out.font_path()))
    document.add_page(sheet(handle, words))

    data = document.to_bytes()
    out.parent.mkdir(parents=True, exist_ok=True)
    out.write_bytes(data)
    print(f"wrote {out}: {len(data)} bytes")


if __name__ == "__main__":
    main()
