"""Fills text and a shape with a gradient, through a shading pattern.

The Python twin of the `write_gradient_fill` example in Rust. Where
`write_gradient` paints a gradient into a clipped box, this makes a gradient the
colour something is filled with: a headline whose letters are windows onto a
three-stop blend, and a panel filled with a radial one. The gradient lives in
the page's own space, so the letters show the part of it behind them.

The two captions are held in `Words`, once per language, and `HQF_PDF_LANG` picks which
set is drawn. The headline is the library's own name and reads the same in every
language.

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

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

import _language
import _licence
import _out

import hqf_pdf

# The headline the gradient fills, which is the library's own name.
HEADLINE = "hqf-pdf"


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

    # The caption under the headline.
    letters: str
    # The caption under the panel.
    shape: str


# The page in English.
ENGLISH = Words(
    letters="Text filled with a gradient, through a shading pattern.",
    shape="A shape filled with a radial gradient.",
)

# The page in French.
FRENCH = Words(
    letters="Du texte rempli par un dégradé, au moyen d'un motif.",
    shape="Une forme remplie par un dégradé en cercle.",
)


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

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

    left = 70.0

    # A three-stop gradient spanning the width of the headline, set as a fill pattern so
    # the letters show it through their shapes.
    headline_size = 84.0
    headline_baseline = 660.0
    headline_width = handle.measure(HEADLINE, headline_size)
    ramp = hqf_pdf.Function.stitching(
        (0.0, 1.0),
        [
            hqf_pdf.Function.exponential(
                (0.0, 1.0), 1.0, ([0.85, 0.12, 0.12], [0.12, 0.55, 0.2])
            ),
            hqf_pdf.Function.exponential(
                (0.0, 1.0), 1.0, ([0.12, 0.55, 0.2], [0.12, 0.2, 0.8])
            ),
        ],
        [0.5],
        [(0.0, 1.0), (0.0, 1.0)],
    )
    letters = document.add_shading_pattern(
        hqf_pdf.Axial(
            (left, headline_baseline),
            (left + headline_width, headline_baseline),
            hqf_pdf.DeviceSpace.Rgb,
            ramp,
        )
    )

    # A radial gradient filling a panel below the headline.
    px, py, pw, ph = left, 350.0, 455.0, 190.0
    panel = document.add_shading_pattern(
        hqf_pdf.Radial.rgb(
            (px + pw / 2.0, py + ph / 2.0, 0.0),
            (px + pw / 2.0, py + ph / 2.0, pw / 2.0),
            hqf_pdf.Rgb(1.0, 1.0, 1.0),
            hqf_pdf.Rgb(0.1, 0.15, 0.45),
        ).extend(False, True)
    )

    content = hqf_pdf.Content()

    # The headline, its letters filled with the gradient.
    content.save_state()
    content.set_fill_pattern(letters)
    content.draw_text(handle, headline_size, left, headline_baseline, HEADLINE)
    content.restore_state()

    # A caption, in plain black.
    content.draw_text(handle, 13.0, left, headline_baseline - 26.0, words.letters)

    # The panel, filled with the radial gradient.
    content.save_state()
    content.set_fill_pattern(panel)
    content.rect(px, py, pw, ph)
    content.fill()
    content.restore_state()

    content.draw_text(handle, 12.0, px, py - 16.0, words.shape)

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