"""Sets the same two paragraphs six ways, one shape to a block: indents, the room
around a paragraph, the alignment of its last line, and where its first baseline
sits.

The Python twin of the `write_paragraphs` example in Rust.

The paragraphs and the heading over each block are written in the language
`HQF_PDF_LANG` names: what a shape does to a paragraph is only visible on a paragraph
somebody can read.

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

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

import _language
import _licence
import _out

import hqf_pdf

# The width of a block, and the gap between the two columns of them.
COLUMN = 225.0
# The left edge of the two columns.
LEFT = (60.0, 310.0)
# The top of the first block of each column.
TOP = 780.0
# How far apart the blocks of a column are stacked.
STEP = 190.0

# The body size every block is set at, and the leading it is set on.
SIZE = 10.0
LEADING = 13.0

# The size a block's heading is set at, and the leading it is set on.
HEADING = 7.5
HEADING_LEADING = 9.5

# How far under its heading the text of a block starts.
HEADING_GAP = 8.0


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

    # Two paragraphs, so that every block shows both what happens inside one and what
    # happens between two.
    text: str
    # What each block is headed by, in the order they are set.
    headings: tuple[str, str, str, str, str, str]


# The page in English.
ENGLISH = Words(
    text=(
        "The deposit is held on the account named overleaf and is returned within "
        "thirty days of the keys being handed back.\nDeductions are itemised in "
        "writing, and anything not itemised is not deducted."
    ),
    headings=(
        "Nothing set: the shape a flow has by default.",
        "First line indented; the paragraphs are told apart by that alone.",
        "First line hung out to the left of the block.",
        "Room left above and below each paragraph.",
        "Justified, with the last line of each paragraph centred.",
        "First baseline on the top of the capitals, last line clear of its "
        "descenders.",
    ),
)

# The page in French.
FRENCH = Words(
    text=(
        "Le dépôt de garantie est conservé sur le compte indiqué "
        "au verso et restitué dans les trente jours qui suivent la remise des "
        "clés.\nToute retenue est détaillée par écrit, et ce qui "
        "n'est pas détaillé n'est pas retenu."
    ),
    headings=(
        "Rien de réglé : la forme qu'un bloc prend par défaut.",
        "Première ligne en retrait ; c'est le seul signe qui sépare les "
        "paragraphes.",
        "Première ligne sortie à gauche du bloc.",
        "De l'air laissé au-dessus et au-dessous de chaque paragraphe.",
        "Justifié, la dernière ligne de chaque paragraphe centrée.",
        "Première ligne de base sur le haut des capitales, dernière ligne "
        "dégagée de ses jambages.",
    ),
)

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


def block(
    content: hqf_pdf.Content,
    handle: hqf_pdf.FontHandle,
    flow: hqf_pdf.TextFlow,
    x: float,
    top: float,
    label: str,
    text: str,
) -> None:
    """Sets one block: its heading, the text under it, and the box the flow fills."""
    heading = hqf_pdf.TextFlow(
        handle, HEADING, leading=HEADING_LEADING, color=hqf_pdf.Rgb.gray(0.35)
    )
    heading_lines = heading.break_lines(label, COLUMN)
    heading.draw(content, heading_lines, x, top, COLUMN)

    text_top = top - heading.height(heading_lines) - HEADING_GAP
    lines = flow.break_lines(text, COLUMN)
    flow.draw(content, lines, x, text_top, COLUMN)

    # The box the flow reports filling, so that the room it keeps around a paragraph is
    # visible and not merely stated.
    height = flow.height(lines)
    content.save_state()
    content.set_stroke(hqf_pdf.Rgb.gray(0.8))
    content.set_line_width(0.5)
    content.rect(x, text_top - height, COLUMN, height)
    content.stroke()
    content.restore_state()


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("paragraphs.pdf", language)).stem)

    document = hqf_pdf.Document()
    document.set_license(_licence.licensed())
    handle = document.add_font(hqf_pdf.Font.from_path(_out.font_path()))

    blocks = (
        (
            words.headings[0],
            hqf_pdf.TextFlow(handle, SIZE, leading=LEADING),
        ),
        (
            words.headings[1],
            hqf_pdf.TextFlow(handle, SIZE, leading=LEADING, first_line_indent=18.0),
        ),
        (
            words.headings[2],
            hqf_pdf.TextFlow(
                handle,
                SIZE,
                leading=LEADING,
                left_indent=24.0,
                first_line_indent=-24.0,
            ),
        ),
        (
            words.headings[3],
            hqf_pdf.TextFlow(
                handle, SIZE, leading=LEADING, space_before=4.0, space_after=8.0
            ),
        ),
        (
            words.headings[4],
            hqf_pdf.TextFlow(
                handle,
                SIZE,
                leading=LEADING,
                align=hqf_pdf.Align.Justify,
                last_align=hqf_pdf.Align.Center,
                right_indent=12.0,
            ),
        ),
        (
            words.headings[5],
            hqf_pdf.TextFlow(
                handle,
                SIZE,
                leading=LEADING,
                first_baseline=hqf_pdf.FirstBaseline.cap_height(),
                last_baseline=hqf_pdf.LastBaseline.descender(),
            ),
        ),
    )

    content = hqf_pdf.Content()
    for index, (label, flow) in enumerate(blocks):
        block(
            content,
            handle,
            flow,
            LEFT[index // 3],
            TOP - STEP * (index % 3),
            label,
            words.text,
        )

    page = hqf_pdf.Page.a4()
    page.set_content(content)
    document.add_page(page)

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


if __name__ == "__main__":
    main()
