"""A contents page: every entry led to its page number by a row of dots.

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

The dots are not written into the text. Each entry is a cell that asks for a leader,
and the layout fills whatever room the entry leaves — which is why the dots still meet
the numbers when an entry is edited, translated or set in another font.

Usage: python examples/write_contents.py [out.pdf] [font.ttf]
"""

from __future__ import annotations

from dataclasses import dataclass

import _licence
import _out

import hqf_pdf

# A4's width, and the margins the contents are laid out between.
PAGE_WIDTH = 595.276
MARGIN = 64.0
TABLE_WIDTH = PAGE_WIDTH - 2.0 * MARGIN


@dataclass(frozen=True)
class Entry:
    """One line of the contents: how deep it sits, what it says, and the page it
    sends the reader to."""

    depth: int
    label: str
    page: str


# The contents of the report this page opens.
ENTRIES = (
    Entry(0, "1  Scope of the audit", "3"),
    Entry(1, "1.1  What was examined", "3"),
    Entry(1, "1.2  What was left out, and why", "5"),
    Entry(0, "2  How the documents are produced today", "8"),
    Entry(1, "2.1  The invoicing run", "8"),
    Entry(1, "2.2  The nightly statement of accounts", "11"),
    Entry(1, "2.3  Documents produced on demand from the counter", "14"),
    Entry(0, "3  What the archival standard asks for", "17"),
    Entry(1, "3.1  Fonts that travel with the file", "17"),
    Entry(1, "3.2  Colour that means the same on every screen", "20"),
    Entry(1, "3.3  Text a reading machine can follow", "23"),
    Entry(0, "4  What it would cost to change", "27"),
    Entry(1, "4.1  The work, month by month", "27"),
    Entry(1, "4.2  What is saved once it is done", "31"),
    Entry(0, "Appendix  Files read for this report", "34"),
)

# How far a sub-entry is set in from the margin, in points.
INDENT = 18.0


def contents(font: hqf_pdf.FontHandle) -> hqf_pdf.Table:
    """The contents, as one table: the entry, led by dots to its page number."""
    columns = hqf_pdf.Columns(
        [hqf_pdf.ColumnWidth.fraction(1.0), hqf_pdf.ColumnWidth.points(28.0)],
        TABLE_WIDTH,
    )

    table = hqf_pdf.Table(columns)
    table.rule(hqf_pdf.Rule.horizontal(0), hqf_pdf.Stroke(0.5, hqf_pdf.Rgb.gray(0.7)))

    for entry in ENTRIES:
        top = entry.depth == 0
        size = 10.5 if top else 9.5
        color = hqf_pdf.Rgb(0.0, 0.0, 0.0) if top else hqf_pdf.Rgb.gray(0.25)
        padding = hqf_pdf.Padding(
            left=INDENT * entry.depth,
            right=4.0,
            top=7.0 if top else 2.0,
            bottom=2.0,
        )

        table.push(
            hqf_pdf.Row(
                [
                    # The dots are drawn by the layout, in the room the entry leaves.
                    hqf_pdf.Cell(
                        font,
                        size,
                        entry.label,
                        color=color,
                        padding=padding,
                        leader=".",
                    ),
                    hqf_pdf.Cell(
                        font,
                        size,
                        entry.page,
                        color=color,
                        align=hqf_pdf.Align.Right,
                        padding=padding,
                    ),
                ]
            )
        )

    return table


def main() -> None:
    out = _out.output_path("contents")

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

    content = hqf_pdf.Content()

    title = hqf_pdf.TextFlow(font, 20.0)
    title.draw(
        content, title.break_lines("Contents", TABLE_WIDTH), MARGIN, 790.0, TABLE_WIDTH
    )

    subtitle = hqf_pdf.TextFlow(font, 8.5, color=hqf_pdf.Rgb.gray(0.4))
    subtitle.draw(
        content,
        subtitle.break_lines(
            "Audit of document production — ACME Ltd, second quarter", TABLE_WIDTH
        ),
        MARGIN,
        762.0,
        TABLE_WIDTH,
    )

    contents(font).fit(MARGIN, 730.0, 660.0).draw(content)

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