from typing import TYPE_CHECKING

from .common import (
    COLOUR_BLACK,
    TEXT_ELLIPSIS,
    FontType,
    fit_text_to_width,
    measure_text,
    wrap_text_to_width,
)

if TYPE_CHECKING:
    from PIL import ImageDraw

TEXT_LINE_HEIGHT_SAMPLE = "Ag"
FORECAST_UNAVAILABLE = "Weather unavailable"
WEATHER_LOADING = "Weather loading..."
UNKNOWN_WEATHER_ERROR = "Unknown weather error"


def draw_forecast_feedback(
    draw: ImageDraw.ImageDraw,
    font: FontType,
    left: int,
    top: int,
    right: int,
    bottom: int,
    message: str,
    error_text_line_spacing: int,
) -> None:
    feedback_message = message.strip() or UNKNOWN_WEATHER_ERROR
    lines = [
        *wrap_text_to_width(
            draw,
            font,
            FORECAST_UNAVAILABLE,
            right - left + 1,
        ),
        "",
        *wrap_text_to_width(draw, font, feedback_message, right - left + 1),
    ]
    draw_wrapped_text_block(
        draw=draw,
        font=font,
        left=left,
        top=top,
        right=right,
        bottom=bottom,
        lines=lines,
        line_spacing=error_text_line_spacing,
    )


def draw_wrapped_text_block(
    draw: ImageDraw.ImageDraw,
    font: FontType,
    left: int,
    top: int,
    right: int,
    bottom: int,
    lines: list[str],
    line_spacing: int,
) -> None:
    available_width = right - left + 1
    available_height = bottom - top + 1
    if available_width <= 0 or available_height <= 0:
        return

    _, line_height, _ = measure_text(draw, font, TEXT_LINE_HEIGHT_SAMPLE)
    if line_height <= 0:
        return

    max_lines = max(1, available_height // (line_height + line_spacing))
    if len(lines) > max_lines:
        lines = lines[:max_lines]
        trimmed = lines[-1].rstrip()
        fitted = fit_text_to_width(
            draw,
            font,
            trimmed,
            available_width,
            suffix=TEXT_ELLIPSIS,
        )
        lines[-1] = f"{fitted}{TEXT_ELLIPSIS}" if fitted else TEXT_ELLIPSIS

    y_position = top
    for line in lines:
        draw.text((left, y_position), line, fill=COLOUR_BLACK, font=font)
        y_position += line_height + line_spacing


def draw_forecast_loading(
    draw: ImageDraw.ImageDraw,
    font: FontType,
    left: int,
    top: int,
    right: int,
    bottom: int,
    error_text_line_spacing: int,
) -> None:
    lines = wrap_text_to_width(draw, font, WEATHER_LOADING, right - left + 1)
    draw_wrapped_text_block(
        draw=draw,
        font=font,
        left=left,
        top=top,
        right=right,
        bottom=bottom,
        lines=lines,
        line_spacing=error_text_line_spacing,
    )
