"""Pure coordinate-mapping math shared by the QQuickPaintedItem chart items
(GraphQuickItem, TrendChartItem). No QPainter or Qt-widget dependency, so
it's testable without a GUI — unlike the paint() methods that call it.
"""
from __future__ import annotations


def value_to_pixel(
    value: float,
    value_min: float,
    value_max: float,
    pixel_start: float,
    pixel_span: float,
) -> float:
    """Map a value onto a pixel range, inverted so larger values sit at
    smaller pixel coordinates (screen y grows downward).

    Also used for evenly-spaced tick indices: pass the tick index as
    `value` and `(tick_count - 1)` as `value_max` with `value_min=0`.
    """
    value_range = value_max - value_min
    if value_range < 1e-9:
        return pixel_start + pixel_span / 2
    fraction = 1.0 - (value - value_min) / value_range
    return pixel_start + fraction * pixel_span


def index_to_pixel(index: float, count: int, pixel_start: float, pixel_span: float) -> float:
    """Map a 0-based sample index onto a pixel range, left to right."""
    if count <= 1:
        return pixel_start + pixel_span / 2
    fraction = index / (count - 1)
    return pixel_start + fraction * pixel_span


def elapsed_to_pixel(
    elapsed: float,
    window_start: float,
    window_end: float,
    pixel_start: float,
    pixel_span: float,
) -> float:
    """Map an elapsed-seconds value onto a pixel range, left to right.

    Unlike `value_to_pixel`, this is not inverted: larger elapsed values sit
    at larger pixel x-coordinates, matching how time flows left-to-right.
    """
    window_span = window_end - window_start
    if window_span < 1e-9:
        return pixel_start + pixel_span
    fraction = (elapsed - window_start) / window_span
    return pixel_start + fraction * pixel_span
