"""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, 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. A reader's software draws what is typed, the tick, the chosen
option, and the dot itself.

Every field carries a border, so the boxes a reader clicks are plain to see. The
standard draws none by default.

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.

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")


@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 a reader 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 title the document carries in its information dictionary.
    document_title: 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",
    document_title="A document with a form",
)

# 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",
    document_title="Un document avec un formulaire",
)


# 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}

# 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


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.FormField(
                name,
                180.0,
                top - 3.0,
                240.0,
                SIZE + 4.0,
                handle,
                SIZE,
                value=value or None,
                border_color=BORDER,
                border_width=BORDER_WIDTH,
            )
        )
        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,
            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,
        )
    )

    page.set_content(content)
    return page


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))

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


if __name__ == "__main__":
    main()
