"""Pours one long passage into three columns, flowing from the foot of each to
the head of the next.

The Python twin of the `write_columns` example in Rust. The passage is broken
once to the column width, then set column by column: each column fits as many of
the lines as its height allows, draws that slice with `Lines.sub`, and the next
column takes up where it stopped. A thin rule outlines each column so the text
can be seen reaching its foot and carrying on.

The passage is held in `Words`, once per language, and `HQF_PDF_LANG` picks which one
is poured. The measure, the gap and the height are not language: they are the same
three columns whoever reads the page.

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

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

import _language
import _licence
import _out

import hqf_pdf


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

    # The passage poured through the columns, long enough to reach the third.
    passage: str


# The page in English.
ENGLISH = Words(
    passage=(
        "A flow too long for one column is set column by column. Each column takes "
        "as many of the broken lines as its height allows, draws them, and hands the "
        "rest to the column beside it, which takes up exactly where the last one "
        "stopped. The words are broken once, to the width one column has, so every "
        "column is set to the same measure. A line that would fall below a column's "
        "foot opens the next column instead, and the reading runs down one column "
        "and on into the top of the next with no line lost and none set twice. This "
        "is what sets a newspaper's text, a report's two columns, or the narrow "
        "measure a wide page reads best in."
    ),
)

# The page in French.
FRENCH = Words(
    passage=(
        "Un texte trop long pour une seule colonne se compose colonne par colonne. "
        "Chaque colonne prend autant de lignes coupées que sa hauteur le permet, les "
        "dessine, et passe le reste à sa voisine, qui reprend là où la "
        "précédente s'est arrêtée. Les mots ne sont coupés qu'une fois, à la largeur "
        "d'une colonne, et toutes sont composées à la même mesure. Une ligne qui "
        "tomberait sous le pied d'une colonne ouvre la suivante, et la lecture descend "
        "une colonne puis remonte en haut de la prochaine sans qu'aucune ligne soit "
        "perdue ni composée deux fois. C'est ainsi que se composent le "
        "texte d'un journal, les deux colonnes d'un rapport, ou la colonne étroite "
        "qui rend une page large lisible."
    ),
)

# 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 left edge of the first column.
LEFT = 70.0
# The top edge every column shares.
TOP = 720.0
# The width of one column.
COLUMN = 145.0
# The gap between one column and the next.
GAP = 25.0
# How far down from TOP a column reaches.
HEIGHT = 130.0
# How many columns the passage is poured through.
COLUMNS = 3


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

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

    flow = hqf_pdf.TextFlow(handle, 10.0, leading=14.0, align=hqf_pdf.Align.Justify)
    lines = flow.break_lines(words.passage, COLUMN)

    content = hqf_pdf.Content()
    start = 0
    x = LEFT
    for _ in range(COLUMNS):
        taken = flow.fit(lines, HEIGHT, start)
        flow.draw(content, lines.sub(start, start + taken), x, TOP, COLUMN)

        content.save_state()
        content.set_stroke(hqf_pdf.Rgb.gray(0.8))
        content.set_line_width(0.5)
        content.rect(x, TOP - HEIGHT, COLUMN, HEIGHT)
        content.stroke()
        content.restore_state()

        start += taken
        x += COLUMN + GAP

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