"""Writes a document with a small form: labelled boxes a reader fills in, a
check box a reader ticks, a drop-down a reader picks from, a set of radio
buttons a reader chooses one of, and a field a reader signs.

The Python twin of the `write_form` example in Rust: the same document, through
the binding rather than through the library directly.

Each text field is a labelled rectangle the reader types into. The label is
drawn on the page, as any other text; the box beside it is the field, empty but
for any value it starts with. The check box under them is ticked on or off and
shows a star when it is, the drop-down under that offers a set of options, the
radio buttons under that let one of several be chosen, and the signature field
under those is a place the reader signs. Reading software draws what is typed, the star, the chosen
option, and the dot itself. The notes box at the foot of the page is shown on the
screen and left off the paper. The box along the right edge of the page is filled in
sideways, its text reading from the bottom up.

The email field reports its answer under `customer_email` rather than under its
own name, which is the name the program receiving the form reads.

Every field carries a border, so the boxes a reader clicks are plain to see. The
standard draws none by default. The country the form starts with is drawn in
hollow blue letters, filled in white and outlined in blue, as a suggestion the
reader may keep or type over.

The second page is a grid of buttons, each doing one thing when pressed: turning the
page, going back to the form or to its signature line, sending the form four ways,
clearing it, filling it from a file, showing and hiding the notes, opening another
document or a file, printing. Under them, seven buttons show an icon, one per layout of
icon and caption, each fitting the icon its own way and showing another while pointed
at and pressed; the last button answers every event a widget reports.

The third page sets every setting a field takes: a comb of six boxes, a password, a
read-only reference, a required field with its help, a note never sent, the five
symbols a tick can take, a sorted list sending values of its own, a drop-down the reader
may type into, radio buttons that cannot all be cleared and two of which stand for the
same choice, and three signature fields each freezing part of the form. The foot of the
page reads back the borders drawn above it, then holds two boxes that state nothing of
their own: the group of fields they sit in states their font, their size, their
centring, that they are read-only, and the order number they both show, once for the
two. The buttons and the settings sit on a layer of their own.

The labels, the options and the document's title are held in `Words`, once per
language, and `HQF_PDF_LANG` picks which set is drawn. A field's name is not among
them: it is what a filled form's data comes back under, so it stays the same
whichever language the page is drawn in.

A structure tree names each of the two payment buttons as an element of its own,
carrying the label drawn beside it.

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

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

import _language
import _licence
import _out

import hqf_pdf

# The text fields the form asks for: the name a filled form's data comes back under, and
# the value the field starts with.
FIELDS = [("Name", ""), ("Email", ""), ("Country", "France")]

# The names the two radio buttons send back, in the order they are drawn.
PAYMENT_VALUES = ("card", "transfer")

# The payment group's place among the first page's fields: after the text fields, the
# check box and the drop-down.
PAYMENT_FIELD = len(FIELDS) + 2

# The text field whose answer a submitted form reports under another name, and that
# name.
SENT_AS = ("Email", "customer_email")


@dataclass(frozen=True)
class Words:
    """Every word the form draws, in one language.

    A field's name is not here: it is the name a filled form's data comes back under,
    and reading software that changed language would send back something else.
    """

    # The line at the head of the page.
    title: str
    # The label drawn beside each text field, in the order `FIELDS` names them.
    labels: tuple[str, str, str]
    # The line beside the check box.
    subscribe: str
    # The label beside the drop-down.
    plan: str
    # The options the drop-down offers; the second is the one it starts on.
    plans: tuple[str, str]
    # The label beside the radio buttons.
    payment: str
    # The line beside each radio button, in the order they are drawn.
    payments: tuple[str, str]
    # The label beside the signature field.
    signature: str
    # The label above the notes box, which is shown on the screen and left off the
    # paper.
    notes: str
    # What the box along the right edge starts holding, read sideways.
    office: str
    # The title the document carries in its information dictionary.
    document_title: str
    # The second page's title.
    buttons_title: str
    # The caption of each button of the second page, in the order `button_actions` gives
    # what each does.
    button_captions: tuple[str, ...]
    # The heading over the buttons that show an icon.
    icons_heading: str
    # The caption of a button that shows an icon, and the one it shows while the pointer
    # is over it and while it is pressed.
    icon_caption: str
    # See `icon_caption`.
    rollover: str
    # See `icon_caption`.
    pressed: str
    # What a button that shows an icon does, told to the reader.
    icon_tip: str
    # The caption of the button that answers every event.
    watched: str
    # What the field that event shows says.
    hint: str
    # The third page's title.
    settings_title: str
    # The label beside each text field of the third page.
    text_labels: tuple[str, str, str, str, str]
    # What the code field tells the reader it wants.
    code_tip: str
    # What the surname field tells the reader it wants.
    surname_tip: str
    # The label beside the five ticks.
    symbols: str
    # The label beside the list.
    list: str
    # The values the list offers.
    colours: tuple[str, str, str]
    # The label beside the drop-down the reader may type into.
    combo: str
    # The values that drop-down offers.
    speeds: tuple[str, str]
    # The label beside the radio buttons of the third page.
    delivery: str
    # What each of those radio buttons means.
    deliveries: tuple[str, str]
    # The label beside each of the three signature fields.
    signatures: tuple[str, str, str]
    # What each style of border is called: solid, dashed, bevelled, inset, underlined.
    styles: tuple[str, str, str, str, str]
    # The label beside each of the two boxes of the group of fields.
    group_labels: tuple[str, str]
    # The line saying what the two boxes take from their group.
    group_note: str


# The page in English.
ENGLISH = Words(
    title="Please fill in",
    labels=(
        "Name",
        "Email",
        "Country",
    ),
    subscribe="Subscribe to the newsletter",
    plan="Plan",
    plans=(
        "Monthly",
        "Yearly",
    ),
    payment="Payment",
    payments=(
        "Card",
        "Transfer",
    ),
    signature="Signature",
    notes="Notes, shown on the screen and left off the paper",
    office="For office use: file 2026-0917",
    document_title="A document with a form",
    buttons_title="Buttons, and what pressing one does",
    button_captions=(
        "First page",
        "Previous page",
        "Next page",
        "Last page",
        "Back to the form",
        "To the signature",
        "Send as FDF",
        "Send as HTML",
        "Send as XFDF",
        "Send the whole file",
        "Clear the form",
        "Fill from a file",
        "Show the notes",
        "Hide the notes",
        "Open the terms",
        "Open the read-me",
        "Print",
    ),
    icons_heading=(
        "Buttons with an icon: seven layouts, each fitting the icon its own way"
    ),
    icon_caption="Stamp",
    rollover="Over",
    pressed="Down",
    icon_tip="Stamps the form",
    watched="A button that answers every event",
    hint="The pointer is on the button",
    settings_title="Every setting a field takes",
    text_labels=(
        "Code, six boxes",
        "PIN, hidden as typed",
        "Reference, read only",
        "Surname, required",
        "Internal note, never sent",
    ),
    code_tip="Six letters or figures, one to a box",
    surname_tip="As on your identity card",
    symbols="Five ticks, each its own symbol",
    list="Several choices, sorted",
    colours=(
        "Blue",
        "Green",
        "Red",
    ),
    combo="One choice, or your own",
    speeds=(
        "Normal",
        "Urgent",
    ),
    delivery="Delivery",
    deliveries=(
        "By post, in three days",
        "By courier, the next day",
    ),
    signatures=(
        "Signing freezes the code",
        "Signing freezes all but the note",
        "Signing freezes everything",
    ),
    styles=(
        "solid",
        "dashed",
        "bevelled",
        "inset",
        "underlined",
    ),
    group_labels=("Order number", "Order number, copy"),
    group_note=(
        "Both boxes take their font, size, centring and value from the group they sit in."
    ),
)

# The page in French.
FRENCH = Words(
    title="Merci de remplir ce formulaire",
    labels=(
        "Nom",
        "Courriel",
        "Pays",
    ),
    subscribe="S’abonner à la lettre d’information",
    plan="Formule",
    plans=(
        "Mensuelle",
        "Annuelle",
    ),
    payment="Paiement",
    payments=(
        "Carte",
        "Virement",
    ),
    signature="Signature",
    notes="Notes, visibles à l’écran, non imprimées",
    office="Réservé à l’administration : dossier 2026-0917",
    document_title="Un document avec un formulaire",
    buttons_title="Des boutons, et ce que fait chacun",
    button_captions=(
        "Première page",
        "Page précédente",
        "Page suivante",
        "Dernière page",
        "Retour au formulaire",
        "Aller à la signature",
        "Envoyer en FDF",
        "Envoyer en HTML",
        "Envoyer en XFDF",
        "Envoyer tout le fichier",
        "Effacer le formulaire",
        "Remplir depuis un fichier",
        "Afficher les notes",
        "Masquer les notes",
        "Ouvrir les conditions",
        "Ouvrir le mode d’emploi",
        "Imprimer",
    ),
    icons_heading=(
        "Des boutons à icône : sept dispositions, chacune ajustant l’icône à sa façon"
    ),
    icon_caption="Tampon",
    rollover="Survol",
    pressed="Appui",
    icon_tip="Tamponne le formulaire",
    watched="Un bouton qui répond à chaque évènement",
    hint="Le pointeur est sur le bouton",
    settings_title="Tous les réglages d’un champ",
    text_labels=(
        "Code, six cases",
        "Code secret, masqué à la saisie",
        "Référence, en lecture seule",
        "Nom, obligatoire",
        "Note interne, jamais envoyée",
    ),
    code_tip="Six lettres ou chiffres, un par case",
    surname_tip="Comme sur votre pièce d’identité",
    symbols="Cinq coches, cinq symboles",
    list="Plusieurs choix, triés",
    colours=(
        "Bleu",
        "Vert",
        "Rouge",
    ),
    combo="Un choix, ou le vôtre",
    speeds=(
        "Normale",
        "Urgente",
    ),
    delivery="Livraison",
    deliveries=(
        "Par la poste, en trois jours",
        "Par coursier, le lendemain",
    ),
    signatures=(
        "La signature fige le code",
        "La signature fige tout sauf la note",
        "La signature fige tout",
    ),
    styles=(
        "plein",
        "tireté",
        "biseauté",
        "en creux",
        "souligné",
    ),
    group_labels=("Numéro de commande", "Numéro de commande, copie"),
    group_note=(
        "Les deux cases prennent police, taille, centrage et valeur du groupe qui les contient."
    ),
)

# The page in Dutch.
DUTCH = Words(
    title="Graag invullen",
    labels=(
        "Naam",
        "E-mail",
        "Land",
    ),
    subscribe="Abonneren op de nieuwsbrief",
    plan="Abonnement",
    plans=(
        "Maandelijks",
        "Jaarlijks",
    ),
    payment="Betaling",
    payments=(
        "Kaart",
        "Overschrijving",
    ),
    signature="Handtekening",
    notes="Notities, op het scherm getoond en niet afgedrukt",
    office="Intern gebruik: dossier 2026-0917",
    document_title="Een document met een formulier",
    buttons_title="Knoppen, en wat een klik erop doet",
    button_captions=(
        "Eerste pagina",
        "Vorige pagina",
        "Volgende pagina",
        "Laatste pagina",
        "Terug naar het formulier",
        "Naar de handtekening",
        "Verzenden als FDF",
        "Verzenden als HTML",
        "Verzenden als XFDF",
        "Het hele bestand verzenden",
        "Formulier wissen",
        "Invullen uit een bestand",
        "Notities tonen",
        "Notities verbergen",
        "Voorwaarden openen",
        "Leesmij openen",
        "Afdrukken",
    ),
    icons_heading=(
        "Knoppen met pictogram: zeven indelingen, elk plaatst het pictogram anders"
    ),
    icon_caption="Stempel",
    rollover="Erboven",
    pressed="Ingedrukt",
    icon_tip="Stempelt het formulier",
    watched="Een knop die op elke gebeurtenis reageert",
    hint="De aanwijzer staat op de knop",
    settings_title="Elke instelling die een veld aanneemt",
    text_labels=(
        "Code, zes vakjes",
        "Pincode, verborgen bij het typen",
        "Referentie, alleen-lezen",
        "Achternaam, verplicht",
        "Interne notitie, nooit verzonden",
    ),
    code_tip="Zes letters of cijfers, één per vakje",
    surname_tip="Zoals op uw identiteitskaart",
    symbols="Vijf vinkjes, elk met eigen symbool",
    list="Meerdere keuzes, gesorteerd",
    colours=(
        "Blauw",
        "Groen",
        "Rood",
    ),
    combo="Eén keuze, of uw eigen",
    speeds=(
        "Normaal",
        "Spoed",
    ),
    delivery="Levering",
    deliveries=(
        "Per post, in drie dagen",
        "Per koerier, de volgende dag",
    ),
    signatures=(
        "Ondertekenen vergrendelt de code",
        "Tekenen vergrendelt bijna alles",
        "Ondertekenen vergrendelt alles",
    ),
    styles=(
        "doorgetrokken",
        "gestreept",
        "afgeschuind",
        "verzonken",
        "onderstreept",
    ),
    group_labels=("Bestelnummer", "Bestelnummer, kopie"),
    group_note=(
        "Beide vakken nemen lettertype, grootte, centrering en waarde over van hun groep."
    ),
)

# The page in Portuguese.
PORTUGUESE = Words(
    title="Preencha, por favor",
    labels=(
        "Nome",
        "E-mail",
        "País",
    ),
    subscribe="Subscrever a newsletter",
    plan="Plano",
    plans=(
        "Mensal",
        "Anual",
    ),
    payment="Pagamento",
    payments=(
        "Cartão",
        "Transferência",
    ),
    signature="Assinatura",
    notes="Notas, visíveis no ecrã e omitidas no papel",
    office="Uso interno: processo 2026-0917",
    document_title="Um documento com um formulário",
    buttons_title="Botões, e o que faz premir cada um",
    button_captions=(
        "Primeira página",
        "Página anterior",
        "Página seguinte",
        "Última página",
        "Voltar ao formulário",
        "Ir para a assinatura",
        "Enviar como FDF",
        "Enviar como HTML",
        "Enviar como XFDF",
        "Enviar o ficheiro inteiro",
        "Limpar o formulário",
        "Importar do ficheiro",
        "Mostrar as notas",
        "Ocultar as notas",
        "Abrir as condições",
        "Abrir o leia-me",
        "Imprimir",
    ),
    icons_heading=(
        "Botões com ícone: sete disposições, cada uma encaixa o ícone a seu modo"
    ),
    icon_caption="Carimbo",
    rollover="Por cima",
    pressed="Premido",
    icon_tip="Carimba o formulário",
    watched="Um botão que responde a cada evento",
    hint="O ponteiro está sobre o botão",
    settings_title="Cada definição que um campo aceita",
    text_labels=(
        "Código, seis caixas",
        "PIN, oculto ao escrever",
        "Referência, só de leitura",
        "Apelido, obrigatório",
        "Nota interna, nunca enviada",
    ),
    code_tip="Seis letras ou algarismos, um por caixa",
    surname_tip="Como no seu cartão de cidadão",
    symbols="Cinco vistos com o seu símbolo",
    list="Várias escolhas, ordenadas",
    colours=(
        "Azul",
        "Verde",
        "Vermelho",
    ),
    combo="Uma escolha, ou a sua",
    speeds=(
        "Normal",
        "Urgente",
    ),
    delivery="Entrega",
    deliveries=(
        "Por correio, em três dias",
        "Por estafeta, no dia seguinte",
    ),
    signatures=(
        "Assinar congela o código",
        "Assinar congela tudo menos a nota",
        "Assinar congela tudo",
    ),
    styles=(
        "contínuo",
        "tracejado",
        "biselado",
        "embutido",
        "sublinhado",
    ),
    group_labels=("Número da encomenda", "Número da encomenda, cópia"),
    group_note=(
        "As duas caixas recebem tipo de letra, tamanho, centragem e valor do seu grupo."
    ),
)

# The page in Italian.
ITALIAN = Words(
    title="Compilare, per favore",
    labels=(
        "Nome",
        "E-mail",
        "Paese",
    ),
    subscribe="Iscriversi alla newsletter",
    plan="Piano",
    plans=(
        "Mensile",
        "Annuale",
    ),
    payment="Pagamento",
    payments=(
        "Carta",
        "Bonifico",
    ),
    signature="Firma",
    notes="Note, visibili a schermo e omesse sulla carta",
    office="Uso interno: pratica 2026-0917",
    document_title="Un documento con un modulo",
    buttons_title="Pulsanti, e cosa fa premerne uno",
    button_captions=(
        "Prima pagina",
        "Pagina precedente",
        "Pagina successiva",
        "Ultima pagina",
        "Torna al modulo",
        "Alla firma",
        "Invia come FDF",
        "Invia come HTML",
        "Invia come XFDF",
        "Invia l’intero file",
        "Svuota il modulo",
        "Compila da un file",
        "Mostra le note",
        "Nascondi le note",
        "Apri le condizioni",
        "Apri il leggimi",
        "Stampa",
    ),
    icons_heading=(
        "Pulsanti con icona: sette disposizioni, ognuna adatta l’icona a modo suo"
    ),
    icon_caption="Timbro",
    rollover="Sopra",
    pressed="Premuto",
    icon_tip="Timbra il modulo",
    watched="Un pulsante che risponde a ogni evento",
    hint="Il puntatore è sul pulsante",
    settings_title="Ogni impostazione che accetta un campo",
    text_labels=(
        "Codice, sei caselle",
        "PIN, nascosto mentre si digita",
        "Riferimento, sola lettura",
        "Cognome, obbligatorio",
        "Nota interna, mai inviata",
    ),
    code_tip="Sei lettere o cifre, una per casella",
    surname_tip="Come sulla carta d’identità",
    symbols="Cinque spunte con il loro simbolo",
    list="Più scelte, ordinate",
    colours=(
        "Blu",
        "Verde",
        "Rosso",
    ),
    combo="Una scelta, o la vostra",
    speeds=(
        "Normale",
        "Urgente",
    ),
    delivery="Consegna",
    deliveries=(
        "Per posta, in tre giorni",
        "Per corriere, il giorno dopo",
    ),
    signatures=(
        "La firma blocca il codice",
        "La firma blocca tutto tranne la nota",
        "La firma blocca tutto",
    ),
    styles=(
        "continuo",
        "tratteggiato",
        "smussato",
        "incassato",
        "sottolineato",
    ),
    group_labels=("Numero d’ordine", "Numero d’ordine, copia"),
    group_note=(
        "Entrambe le caselle prendono carattere, corpo, centratura e valore dal loro gruppo."
    ),
)

# The page in Spanish.
SPANISH = Words(
    title="Rellene, por favor",
    labels=(
        "Nombre",
        "Correo electrónico",
        "País",
    ),
    subscribe="Suscribirse al boletín",
    plan="Plan",
    plans=(
        "Mensual",
        "Anual",
    ),
    payment="Pago",
    payments=(
        "Tarjeta",
        "Transferencia",
    ),
    signature="Firma",
    notes="Notas, visibles en pantalla y omitidas en papel",
    office="Uso interno: expediente 2026-0917",
    document_title="Un documento con un formulario",
    buttons_title="Botones, y lo que hace pulsar cada uno",
    button_captions=(
        "Primera página",
        "Página anterior",
        "Página siguiente",
        "Última página",
        "Volver al formulario",
        "Ir a la firma",
        "Enviar como FDF",
        "Enviar como HTML",
        "Enviar como XFDF",
        "Enviar el archivo entero",
        "Vaciar el formulario",
        "Rellenar desde un archivo",
        "Mostrar las notas",
        "Ocultar las notas",
        "Abrir las condiciones",
        "Abrir el léame",
        "Imprimir",
    ),
    icons_heading=(
        "Botones con icono: siete disposiciones, cada una coloca el icono a su modo"
    ),
    icon_caption="Sello",
    rollover="Encima",
    pressed="Pulsado",
    icon_tip="Sella el formulario",
    watched="Un botón que responde a cada evento",
    hint="El puntero está sobre el botón",
    settings_title="Cada ajuste que admite un campo",
    text_labels=(
        "Código, seis casillas",
        "PIN, oculto al teclear",
        "Referencia, solo lectura",
        "Apellido, obligatorio",
        "Nota interna, nunca enviada",
    ),
    code_tip="Seis letras o cifras, una por casilla",
    surname_tip="Como en su documento de identidad",
    symbols="Cinco marcas con su símbolo",
    list="Varias opciones, ordenadas",
    colours=(
        "Azul",
        "Verde",
        "Rojo",
    ),
    combo="Una opción, o la suya",
    speeds=(
        "Normal",
        "Urgente",
    ),
    delivery="Entrega",
    deliveries=(
        "Por correo, en tres días",
        "Por mensajero, al día siguiente",
    ),
    signatures=(
        "Firmar congela el código",
        "Firmar congela todo menos la nota",
        "Firmar congela todo",
    ),
    styles=(
        "continuo",
        "discontinuo",
        "biselado",
        "hundido",
        "subrayado",
    ),
    group_labels=("Número de pedido", "Número de pedido, copia"),
    group_note=(
        "Ambas casillas toman fuente, tamaño, centrado y valor del grupo que las contiene."
    ),
)

# The page in German.
GERMAN = Words(
    title="Bitte ausfüllen",
    labels=(
        "Name",
        "E-Mail",
        "Land",
    ),
    subscribe="Newsletter abonnieren",
    plan="Tarif",
    plans=(
        "Monatlich",
        "Jährlich",
    ),
    payment="Zahlung",
    payments=(
        "Karte",
        "Überweisung",
    ),
    signature="Unterschrift",
    notes="Notizen, auf dem Bildschirm gezeigt und auf dem Papier weggelassen",
    office="Für den Bürogebrauch: Akte 2026-0917",
    document_title="Ein Dokument mit einem Formular",
    buttons_title="Schaltflächen und was ein Klick darauf bewirkt",
    button_captions=(
        "Erste Seite",
        "Vorherige Seite",
        "Nächste Seite",
        "Letzte Seite",
        "Zurück zum Formular",
        "Zur Unterschrift",
        "Als FDF senden",
        "Als HTML senden",
        "Als XFDF senden",
        "Ganze Datei senden",
        "Formular leeren",
        "Aus einer Datei füllen",
        "Notizen zeigen",
        "Notizen verbergen",
        "Bedingungen öffnen",
        "Liesmich-Datei öffnen",
        "Drucken",
    ),
    icons_heading=(
        "Schaltflächen mit Symbol: sieben Anordnungen, jede auf ihre Art"
    ),
    icon_caption="Stempel",
    rollover="Zeiger darüber",
    pressed="Gedrückt",
    icon_tip="Stempelt das Formular",
    watched="Eine Schaltfläche, die auf jedes Ereignis antwortet",
    hint="Der Zeiger ist auf der Schaltfläche",
    settings_title="Jede Einstellung, die ein Feld annimmt",
    text_labels=(
        "Code, sechs Kästchen",
        "PIN, beim Tippen verborgen",
        "Referenz, schreibgeschützt",
        "Nachname, Pflichtfeld",
        "Interne Notiz, wird nie gesendet",
    ),
    code_tip="Sechs Buchstaben oder Ziffern, eine pro Kästchen",
    surname_tip="Wie auf Ihrem Personalausweis",
    symbols="Fünf Häkchen, fünf Symbole",
    list="Mehrfachauswahl, sortiert",
    colours=(
        "Blau",
        "Grün",
        "Rot",
    ),
    combo="Auswahl oder eigene Eingabe",
    speeds=(
        "Normal",
        "Dringend",
    ),
    delivery="Lieferung",
    deliveries=(
        "Per Post, in drei Tagen",
        "Per Kurier, am nächsten Tag",
    ),
    signatures=(
        "Signieren sperrt den Code",
        "Signieren sperrt fast alles",
        "Signieren sperrt alles",
    ),
    styles=(
        "durchgezogen",
        "gestrichelt",
        "abgeschrägt",
        "vertieft",
        "unterstrichen",
    ),
    group_labels=("Bestellnummer", "Bestellnummer, Kopie"),
    group_note=(
        "Beide Felder übernehmen Schrift, Größe, Zentrierung und Wert von ihrer Gruppe."
    ),
)

# 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 size the labels and the field text are set at.
SIZE = 12.0

# The colour every field's border is stroked in.
BORDER = hqf_pdf.Rgb.gray(0.6)
# The width every field's border is stroked at, in points.
BORDER_WIDTH = 0.75
# The colour a value the form starts with is outlined in, so it reads as a suggestion
# rather than as something the reader typed.
SUGGESTED = hqf_pdf.Rgb(0.1, 0.3, 0.7)
# The colour the letters of a suggested value are filled in, inside their outline.
SUGGESTED_FILL = hqf_pdf.Rgb(1.0, 1.0, 1.0)
# The width a suggested value's letters are outlined at, in points.
SUGGESTED_OUTLINE = 0.5


def form_page(handle: hqf_pdf.FontHandle, words: Words) -> hqf_pdf.Page:
    """The form page: a title, then a label and a fillable box for each field."""
    content = hqf_pdf.Content()
    page = hqf_pdf.Page.a4()

    content.draw_text(handle, 20.0, 72.0, 760.0, words.title)

    top = 700.0
    for (name, value), label in zip(FIELDS, words.labels):
        content.draw_text(handle, SIZE, 72.0, top, label)
        page.add_field(
            hqf_pdf.TextField(
                name,
                180.0,
                top - 3.0,
                240.0,
                SIZE + 4.0,
                handle,
                SIZE,
                value=value or None,
                text_color=SUGGESTED_FILL if value else None,
                text_stroke_color=SUGGESTED if value else None,
                text_stroke_width=SUGGESTED_OUTLINE,
                border_color=BORDER,
                border_width=BORDER_WIDTH,
                mapping_name=SENT_AS[1] if name == SENT_AS[0] else None,
            )
        )
        top -= SIZE * 3.0

    content.draw_text(handle, SIZE, 90.0, top, words.subscribe)
    page.add_checkbox(hqf_pdf.CheckBox(
            "Subscribe",
            72.0,
            top - 2.0,
            SIZE,
            SIZE,
            checked=True,
            symbol=hqf_pdf.CheckSymbol.Star,
            border_color=BORDER,
            border_width=BORDER_WIDTH,
        ))
    top -= SIZE * 3.0

    content.draw_text(handle, SIZE, 72.0, top, words.plan)
    page.add_choice(
        hqf_pdf.ChoiceField(
            "Plan",
            180.0,
            top - 3.0,
            240.0,
            SIZE + 4.0,
            handle,
            SIZE,
            options=list(words.plans),
            selected=words.plans[1],
            combo=True,
            border_color=BORDER,
            border_width=BORDER_WIDTH,
        )
    )
    top -= SIZE * 3.0

    content.draw_text(handle, SIZE, 72.0, top, words.payment)
    page.add_radio(
        hqf_pdf.RadioGroup(
            "Payment",
            [
                (PAYMENT_VALUES[0], 180.0, top - 3.0, SIZE, SIZE),
                (PAYMENT_VALUES[1], 320.0, top - 3.0, SIZE, SIZE),
            ],
            selected=PAYMENT_VALUES[0],
            border_color=BORDER,
            border_width=BORDER_WIDTH,
        )
    )
    content.draw_text(handle, SIZE, 198.0, top, words.payments[0])
    content.draw_text(handle, SIZE, 338.0, top, words.payments[1])
    top -= SIZE * 4.0

    content.draw_text(handle, SIZE, 72.0, top, words.signature)
    page.add_signature(
        hqf_pdf.SignatureField(
            "Signature",
            180.0,
            top - 12.0,
            240.0,
            40.0,
            border_color=BORDER,
            border_width=BORDER_WIDTH,
        )
    )
    top -= SIZE * 5.0

    # Neither printed nor hidden: on the screen, and off the paper.
    content.draw_text(handle, SIZE, 72.0, top, words.notes)
    page.add_field(
        hqf_pdf.TextField(
            "Notes",
            72.0,
            top - 42.0,
            348.0,
            SIZE + 20.0,
            handle,
            SIZE,
            multiline=True,
            border_color=BORDER,
            border_width=BORDER_WIDTH,
            flags=hqf_pdf.AnnotationFlags.none(),
        )
    )

    # The box along the right edge, turned a quarter so its text runs up the edge.
    page.add_field(
        hqf_pdf.TextField(
            "Office",
            500.0,
            440.0,
            SIZE + 4.0,
            280.0,
            handle,
            SIZE,
            value=words.office,
            rotation=hqf_pdf.FieldRotation.Quarter,
            border_color=BORDER,
            border_width=BORDER_WIDTH,
        )
    )

    page.set_content(content)
    return page


# The left edge of the fields of the third page.
FIELD_X = 300.0

# Where a submitted form is sent.
SUBMIT_TO = "https://hqf-pdf.com/forms/submit"

# The group of fields at the foot of the third page.
ORDER_GROUP = "Order"

# The partial names of the two fields of that group.
ORDER_FIELDS = ("Number", "Copy")

# The value the group hands down to both its fields.
ORDER_NUMBER = "2026-0917"


def order_group(handle: hqf_pdf.FontHandle) -> hqf_pdf.FieldGroup:
    """The group the two fields at the foot of the third page sit in: it states, once,
    the kind, the font and size, the centring, the read-only flag and the value both
    take."""
    return hqf_pdf.FieldGroup(
        [ORDER_GROUP],
        kind=hqf_pdf.FieldKind.Text,
        read_only=True,
        font=handle,
        size=SIZE,
        align=hqf_pdf.FieldAlign.Center,
        value=ORDER_NUMBER,
    )

# The width and height of a button of the second page.
BUTTON = (150.0, 22.0)

# The left edge of each of the three columns of buttons.
BUTTON_COLUMNS = (72.0, 232.0, 392.0)

# The values the list offers, each sent back under a name of its own.
LIST_EXPORTS = ("blue", "green", "red")


def button_actions() -> list[hqf_pdf.Action]:
    """What each of the buttons of the second page does, in the order their captions
    are drawn."""
    Action = hqf_pdf.Action
    return [
        Action.menu_item(hqf_pdf.MenuItem.FirstPage),
        Action.menu_item(hqf_pdf.MenuItem.PreviousPage),
        Action.menu_item(hqf_pdf.MenuItem.NextPage),
        Action.menu_item(hqf_pdf.MenuItem.LastPage),
        Action.to_page(0, hqf_pdf.PageFit.full_width(780.0)),
        Action.to_destination("signature"),
        Action.submit_fields(
            SUBMIT_TO,
            fields=hqf_pdf.FieldSet.all(),
            format=hqf_pdf.SubmitFormat.fdf(with_no_value=True),
        ),
        Action.submit_fields(
            SUBMIT_TO,
            fields=hqf_pdf.FieldSet.only(["Name", "Email"]),
            format=hqf_pdf.SubmitFormat.html(get=False, with_click=True),
        ),
        Action.submit_fields(
            SUBMIT_TO,
            fields=hqf_pdf.FieldSet.all_but(["Notes"]),
            format=hqf_pdf.SubmitFormat.xfdf(),
        ),
        Action.submit_fields(
            SUBMIT_TO,
            fields=hqf_pdf.FieldSet.all(),
            format=hqf_pdf.SubmitFormat.whole_document(get=False),
        ),
        Action.reset_fields(hqf_pdf.FieldSet.all()),
        Action.import_fields("answers.fdf"),
        Action.show(["Notes"]),
        Action.hide(["Notes"]),
        Action.to_other_document(
            "terms.pdf",
            0,
            view=hqf_pdf.PageFit.whole_page(),
            element=None,
            new_window=True,
        ),
        Action.launch("readme.txt", new_window=False),
        Action.viewer_command("Print"),
    ]


def stamp() -> hqf_pdf.Drawing:
    """A small stamp drawn once, the icon the buttons of the second page show."""
    icon = hqf_pdf.Content()
    icon.set_fill(hqf_pdf.Rgb(0.75, 0.15, 0.15))
    icon.circle(10.0, 10.0, 9.0)
    icon.fill()
    icon.set_fill(hqf_pdf.Rgb.gray(1.0))
    icon.rect(6.0, 6.0, 8.0, 8.0)
    icon.fill()
    return hqf_pdf.Drawing(icon, hqf_pdf.Rect(0.0, 0.0, 20.0, 20.0))


def stamp_pressed() -> hqf_pdf.Drawing:
    """The same stamp in blue, shown while the pointer is over a button or the button
    is pressed."""
    icon = hqf_pdf.Content()
    icon.set_fill(hqf_pdf.Rgb(0.15, 0.3, 0.75))
    icon.circle(10.0, 10.0, 9.0)
    icon.fill()
    return hqf_pdf.Drawing(icon, hqf_pdf.Rect(0.0, 0.0, 20.0, 20.0))


def buttons_page(document, handle, words, layer) -> hqf_pdf.Page:
    """The second page: a grid of buttons, each doing one thing when pressed, and a
    row of buttons that show an icon, laid out and fitted each its own way."""
    content = hqf_pdf.Content()
    page = hqf_pdf.Page.a4()
    page.set_tab_order(hqf_pdf.TabOrder.Row)
    content.draw_text(handle, 20.0, 72.0, 760.0, words.buttons_title)

    top = 710.0
    rank = 0
    for place, (caption, action) in enumerate(
        zip(words.button_captions, button_actions())
    ):
        column = BUTTON_COLUMNS[place % len(BUTTON_COLUMNS)]
        if place > 0 and place % len(BUTTON_COLUMNS) == 0:
            top -= 34.0
        page.add_push_button(
            hqf_pdf.PushButton(
                f"Button{place}",
                column,
                top,
                BUTTON[0],
                BUTTON[1],
                handle,
                10.0,
                caption=caption,
                action=action,
                background=hqf_pdf.Rgb.gray(0.93),
                frame=hqf_pdf.FieldBorder.beveled(BORDER, BORDER_WIDTH),
                tab_rank=rank,
            )
        )
        rank += 1

    # The buttons that show an icon: one per layout, each fitting the icon its own way.
    top -= 60.0
    content.draw_text(handle, SIZE, 72.0, top, words.icons_heading)
    icon = document.add_drawing(stamp())
    pressed = document.add_drawing(stamp_pressed())
    layouts = (
        (
            hqf_pdf.ButtonLayout.CaptionOnly,
            hqf_pdf.IconFit(scale=hqf_pdf.IconScale.Always),
        ),
        (
            hqf_pdf.ButtonLayout.IconOnly,
            hqf_pdf.IconFit(scale=hqf_pdf.IconScale.WhenBigger),
        ),
        (
            hqf_pdf.ButtonLayout.CaptionBelowIcon,
            hqf_pdf.IconFit(scale=hqf_pdf.IconScale.WhenSmaller),
        ),
        (
            hqf_pdf.ButtonLayout.CaptionAboveIcon,
            hqf_pdf.IconFit(scale=hqf_pdf.IconScale.Never),
        ),
        (
            hqf_pdf.ButtonLayout.CaptionRightOfIcon,
            hqf_pdf.IconFit(stretch=hqf_pdf.IconStretch.Proportional),
        ),
        (
            hqf_pdf.ButtonLayout.CaptionLeftOfIcon,
            hqf_pdf.IconFit(stretch=hqf_pdf.IconStretch.Anamorphic),
        ),
        (
            hqf_pdf.ButtonLayout.CaptionOverIcon,
            hqf_pdf.IconFit(leftover=(0.0, 1.0), ignore_border=True),
        ),
    )
    highlights = (
        hqf_pdf.PressHighlight.None_,
        hqf_pdf.PressHighlight.Invert,
        hqf_pdf.PressHighlight.Outline,
        hqf_pdf.PressHighlight.Push,
    )
    rotations = (
        hqf_pdf.FieldRotation.Upright,
        hqf_pdf.FieldRotation.Half,
        hqf_pdf.FieldRotation.ThreeQuarters,
    )
    top -= 70.0
    x = 72.0
    for place, (layout, fit) in enumerate(layouts):
        page.add_push_button(
            hqf_pdf.PushButton(
                f"Stamp{place}",
                x,
                top,
                60.0,
                50.0,
                handle,
                8.0,
                caption=words.icon_caption,
                rollover_caption=words.rollover,
                down_caption=words.pressed,
                icon=icon,
                rollover_icon=pressed,
                down_icon=pressed,
                layout=layout,
                icon_fit=fit,
                text_color=hqf_pdf.Rgb(0.1, 0.1, 0.4),
                frame=hqf_pdf.FieldBorder.inset(BORDER, BORDER_WIDTH),
                highlight=highlights[place % len(highlights)],
                rotation=rotations[place % len(rotations)],
                tooltip=words.icon_tip,
                description=words.icon_tip,
                mapping_name=f"stamp_{place}",
                flags=hqf_pdf.AnnotationFlags.none().printed().no_zoom(),
                layer=layer,
                read_only=place == 0,
                required=place == 1,
                no_export=place == 2,
            )
        )
        x += 68.0

    # One more button, which answers to every event a widget reports.
    top -= 50.0
    show = hqf_pdf.Action.show(["Hint"])
    hide = hqf_pdf.Action.hide(["Hint"])
    page.add_push_button(
        hqf_pdf.PushButton(
            "Watched",
            72.0,
            top,
            230.0,
            BUTTON[1],
            handle,
            10.0,
            caption=words.watched,
            border_color=BORDER,
            border_width=BORDER_WIDTH,
            triggers=hqf_pdf.WidgetTriggers()
            .enter(show)
            .exit(hide)
            .up(hqf_pdf.Action.menu_item(hqf_pdf.MenuItem.NextPage))
            .focused(show)
            .blurred(hide)
            .page_opened(hide)
            .page_closed(hide)
            .page_shown(hide)
            .page_hidden(hide),
        )
    )
    page.add_field(
        hqf_pdf.TextField(
            "Hint",
            320.0,
            top,
            200.0,
            BUTTON[1],
            handle,
            9.0,
            value=words.hint,
            read_only=True,
            flags=hqf_pdf.AnnotationFlags.none().hidden(),
        )
    )

    page.set_content(content)
    return page


def style_name(words, style) -> str:
    """The words a field's border is described by, from the style it reads back."""
    styles = (
        hqf_pdf.BorderStyle.Solid,
        hqf_pdf.BorderStyle.Dashed,
        hqf_pdf.BorderStyle.Beveled,
        hqf_pdf.BorderStyle.Inset,
        hqf_pdf.BorderStyle.Underline,
    )
    for known, name in zip(styles, words.styles):
        if style == known:
            return name
    return words.styles[0]


def settings_page(handle, words, layer) -> hqf_pdf.Page:
    """The third page: every setting a field takes, one field after another."""
    content = hqf_pdf.Content()
    page = hqf_pdf.Page.a4()
    page.set_tab_order(hqf_pdf.TabOrder.Column)
    page.set_triggers(
        hqf_pdf.PageTriggers()
        .opened(hqf_pdf.Action.show(["Code"]))
        .closed(hqf_pdf.Action.reset_fields(hqf_pdf.FieldSet.only(["Pin"])))
    )
    content.draw_text(handle, 20.0, 72.0, 760.0, words.settings_title)

    dashed = hqf_pdf.FieldBorder.dashed(BORDER, 1.0, hqf_pdf.Dash.on_off(3.0, 2.0))
    beveled = hqf_pdf.FieldBorder.beveled(BORDER, BORDER_WIDTH)
    inset = hqf_pdf.FieldBorder.inset(BORDER, BORDER_WIDTH)

    top = 710.0
    field_height = SIZE + 6.0
    text_fields = (
        hqf_pdf.TextField(
            "Code",
            FIELD_X,
            top - 3.0,
            120.0,
            field_height,
            handle,
            SIZE,
            max_length=6,
            comb=True,
            tooltip=words.code_tip,
            align=hqf_pdf.FieldAlign.Center,
            frame=dashed,
        ),
        hqf_pdf.TextField(
            "Pin",
            FIELD_X,
            top - 33.0,
            120.0,
            field_height,
            handle,
            SIZE,
            password=True,
            required=True,
            frame=beveled,
        ),
        hqf_pdf.TextField(
            "Reference",
            FIELD_X,
            top - 63.0,
            200.0,
            field_height,
            handle,
            SIZE,
            value="HQF-2026-0917",
            default_value="HQF-2026-0917",
            read_only=True,
            align=hqf_pdf.FieldAlign.Right,
            frame=inset,
        ),
        hqf_pdf.TextField(
            "Surname",
            FIELD_X,
            top - 93.0,
            200.0,
            field_height,
            handle,
            SIZE,
            required=True,
            description=words.surname_tip,
            background=hqf_pdf.Rgb(1.0, 0.98, 0.85),
            highlight=hqf_pdf.PressHighlight.Outline,
            tab_rank=1,
            triggers=hqf_pdf.WidgetTriggers().blurred(hqf_pdf.Action.show(["Surname"])),
            border_color=BORDER,
            border_width=BORDER_WIDTH,
        ),
        hqf_pdf.TextField(
            "Internal",
            FIELD_X,
            top - 123.0,
            200.0,
            field_height,
            handle,
            SIZE,
            no_export=True,
            layer=layer,
            frame=hqf_pdf.FieldBorder.underline(BORDER, BORDER_WIDTH),
        ),
    )
    for field, label in zip(text_fields, words.text_labels):
        content.draw_text(handle, SIZE, 72.0, top, label)
        page.add_field(field)
        top -= 30.0

    # The five symbols a tick can take, each box sending back "yes".
    content.draw_text(handle, SIZE, 72.0, top, words.symbols)
    symbols = (
        hqf_pdf.CheckSymbol.Check,
        hqf_pdf.CheckSymbol.Cross,
        hqf_pdf.CheckSymbol.Circle,
        hqf_pdf.CheckSymbol.Diamond,
        hqf_pdf.CheckSymbol.Square,
    )
    settings = (
        {"checked": True, "checked_by_default": True},
        {"read_only": True},
        {"required": True, "description": words.symbols},
        {"no_export": True, "tab_rank": 2},
        {
            "layer": layer,
            "triggers": hqf_pdf.WidgetTriggers().up(hqf_pdf.Action.show(["Code"])),
        },
    )
    x = FIELD_X
    for place, (symbol, extra) in enumerate(zip(symbols, settings)):
        page.add_checkbox(
            hqf_pdf.CheckBox(
                f"Tick{place}",
                x,
                top - 2.0,
                SIZE,
                SIZE,
                symbol=symbol,
                export_value="yes",
                background=hqf_pdf.Rgb.gray(0.97),
                highlight=hqf_pdf.PressHighlight.Push,
                border_color=BORDER,
                border_width=BORDER_WIDTH,
                **extra,
            )
        )
        x += 30.0
    top -= 40.0

    # A list offering several values at once, sorted, each sent back under a name of its
    # own; then a drop-down the reader may also type into.
    content.draw_text(handle, SIZE, 72.0, top, words.list)
    page.add_choice(
        hqf_pdf.ChoiceField(
            "Colours",
            FIELD_X,
            top - 44.0,
            150.0,
            56.0,
            handle,
            SIZE,
            options=list(zip(LIST_EXPORTS, words.colours)),
            default_selected=LIST_EXPORTS[0],
            multi_select=True,
            sorted=True,
            required=True,
            background=hqf_pdf.Rgb.gray(0.97),
            highlight=hqf_pdf.PressHighlight.Invert,
            tab_rank=3,
            description=words.list,
            layer=layer,
            triggers=hqf_pdf.WidgetTriggers().blurred(hqf_pdf.Action.show(["Colours"])),
            frame=dashed,
        )
    )
    top -= 70.0

    content.draw_text(handle, SIZE, 72.0, top, words.combo)
    page.add_choice(
        hqf_pdf.ChoiceField(
            "Speed",
            FIELD_X,
            top - 3.0,
            150.0,
            field_height,
            handle,
            SIZE,
            options=list(words.speeds),
            combo=True,
            editable=True,
            default_selected=words.speeds[0],
            align=hqf_pdf.FieldAlign.Center,
            frame=beveled,
        )
    )
    page.add_choice(
        hqf_pdf.ChoiceField(
            "SpeedCopy",
            FIELD_X + 160.0,
            top - 3.0,
            110.0,
            field_height,
            handle,
            SIZE,
            options=[words.speeds[0]],
            combo=True,
            read_only=True,
            no_export=True,
            align=hqf_pdf.FieldAlign.Right,
            frame=inset,
        )
    )
    top -= 40.0

    # Two ways of delivery, each described; the group cannot be emptied again, and a
    # third button stands for the same choice as the first.
    content.draw_text(handle, SIZE, 72.0, top, words.delivery)
    page.add_radio(
        hqf_pdf.RadioGroup(
            "Delivery",
            [
                ("post", FIELD_X, top - 3.0, SIZE, SIZE),
                ("courier", FIELD_X + 80.0, top - 3.0, SIZE, SIZE),
                ("post", FIELD_X + 160.0, top - 3.0, SIZE, SIZE),
            ],
            default_selected="post",
            descriptions=[
                ("post", words.deliveries[0]),
                ("courier", words.deliveries[1]),
            ],
            no_toggle_to_off=True,
            in_unison=True,
            required=True,
            background=hqf_pdf.Rgb.gray(0.97),
            highlight=hqf_pdf.PressHighlight.Outline,
            tab_rank=4,
            layer=layer,
            triggers=hqf_pdf.WidgetTriggers().up(hqf_pdf.Action.show(["Delivery"])),
            border_color=BORDER,
            border_width=BORDER_WIDTH,
        )
    )
    page.add_radio(
        hqf_pdf.RadioGroup(
            "Wrapping",
            [("paper", FIELD_X, top - 23.0, SIZE, SIZE)],
            read_only=True,
            no_export=True,
            border_color=BORDER,
            border_width=BORDER_WIDTH,
        )
    )
    top -= 60.0

    # Three signature fields, each freezing part of the form once signed.
    locks = (
        hqf_pdf.SignatureLock.only(["Code"]),
        hqf_pdf.SignatureLock.all_but(["Internal"]),
        hqf_pdf.SignatureLock.all(),
    )
    for place, (label, lock) in enumerate(zip(words.signatures, locks)):
        content.draw_text(handle, SIZE, 72.0, top, label)
        page.add_signature(
            hqf_pdf.SignatureField(
                f"Sign{place}",
                FIELD_X,
                top - 20.0,
                200.0,
                34.0,
                lock=lock,
                tooltip=label,
                description=label,
                background=hqf_pdf.Rgb.gray(0.97),
                tab_rank=5,
                highlight=hqf_pdf.PressHighlight.Invert,
                layer=layer,
                triggers=hqf_pdf.WidgetTriggers().focused(
                    hqf_pdf.Action.show(["Code"])
                ),
                border_color=BORDER,
                border_width=BORDER_WIDTH,
                required=place == 0,
                read_only=place == 1,
                no_export=place == 2,
            )
        )
        top -= 44.0

    # What each of the borders above is, read back from the border itself.
    for border in (dashed, beveled, inset):
        values = " ".join(f"{value:.1f}" for value in border.color.to_components())
        line = f"{style_name(words, border.style)}, {border.width:g} pt, {values}"
        content.draw_text(handle, 9.0, 72.0, top, line)
        top -= 14.0

    # Two boxes stating nothing of their own: the group above them states it.
    top -= 10.0
    content.draw_text(handle, 9.0, 72.0, top, words.group_note)
    top -= 24.0
    for child, label in zip(ORDER_FIELDS, words.group_labels):
        content.draw_text(handle, SIZE, 72.0, top, label)
        page.add_field(
            hqf_pdf.TextField(
                f"{ORDER_GROUP}.{child}",
                FIELD_X,
                top - 3.0,
                200.0,
                SIZE + 6.0,
                None,
                None,
                border_color=BORDER,
                border_width=BORDER_WIDTH,
            )
        )
        top -= 30.0

    page.set_content(content)
    return page


def payment_tree(words: Words) -> hqf_pdf.StructureTree:
    """The structure tree: the payment group's two buttons, each a `Form` element
    named by its label, gathered in a `Div`."""
    group = hqf_pdf.StructElement(
        "Div",
        children=[
            hqf_pdf.StructElement(
                "Form",
                children=[hqf_pdf.TaggedField(0, PAYMENT_FIELD, button=button)],
                alt=label,
            )
            for button, label in enumerate(words.payments)
        ],
    )
    return hqf_pdf.StructureTree(
        children=[hqf_pdf.StructElement("Document", children=[group])]
    )


def main() -> None:
    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 two
    # languages do not overwrite each other in `tmp/`.
    out = _out.output_path(Path(_language.file_name("form.pdf", language)).stem)

    document = hqf_pdf.Document()
    document.set_license(_licence.licensed())
    document.set_info("Title", words.document_title)

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

    # The buttons and the settings sit on a layer of their own, which reading software
    # can hide; the signature line of the first page is a named place a button goes to.
    layer = document.add_layer(hqf_pdf.Layer("Controls"))
    document.add_destination(
        "signature", 0, hqf_pdf.PageFit.fixed(left=72.0, top=400.0, zoom=None)
    )
    document.add_page(buttons_page(document, handle, words, layer))
    document.add_page(settings_page(handle, words, layer))
    document.add_field_group(order_group(handle))
    document.set_structure(payment_tree(words))

    written = document.write(out)
    print(f"wrote {out} ({written} bytes)")


if __name__ == "__main__":
    main()
