from __future__ import annotations

from PySide6.QtCore import Qt
from PySide6.QtGui import QFont, QPainter, QPalette
from PySide6.QtWidgets import QWidget

from ._elide import ElideOptions, ElidingLabel, draw_elided_text, elide_text

_MODE_ALIASES = {
    "left": Qt.TextElideMode.ElideLeft,
    "right": Qt.TextElideMode.ElideRight,
    "middle": Qt.TextElideMode.ElideMiddle,
}

_ALIGN_ALIASES = {
    "left": Qt.AlignmentFlag.AlignLeft,
    "right": Qt.AlignmentFlag.AlignRight,
    "center": Qt.AlignmentFlag.AlignHCenter,
}


def _parse_mode(mode: Qt.TextElideMode | str | None) -> Qt.TextElideMode:
    if mode is None:
        return Qt.TextElideMode.ElideRight
    if isinstance(mode, Qt.TextElideMode):
        return mode
    key = str(mode).strip().lower()
    return _MODE_ALIASES.get(key, Qt.TextElideMode.ElideRight)


def _parse_alignment(
    alignment: Qt.AlignmentFlag | str | None,
) -> Qt.AlignmentFlag:
    if alignment is None:
        return Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter
    if isinstance(alignment, Qt.AlignmentFlag):
        return alignment
    if isinstance(alignment, Qt.Alignment):
        return alignment
    if isinstance(alignment, int):
        return Qt.AlignmentFlag(alignment)
    key = str(alignment).strip().lower()
    base = _ALIGN_ALIASES.get(key, Qt.AlignmentFlag.AlignLeft)
    return base | Qt.AlignmentFlag.AlignVCenter


def options(
    *,
    mode: Qt.TextElideMode | str | None = None,
    align: Qt.AlignmentFlag | str | None = None,
    padding: int = 0,
) -> ElideOptions:
    return ElideOptions(mode=_parse_mode(mode), alignment=_parse_alignment(align), padding=padding)


def text(
    value: str,
    *,
    font: QFont,
    width: int,
    mode: Qt.TextElideMode | str | None = None,
) -> str:
    return elide_text(value, font, width, _parse_mode(mode))


def paint(
    painter: QPainter,
    *,
    rect,
    text: str,
    font: QFont | None = None,
    palette: QPalette | None = None,
    enabled: bool = True,
    mode: Qt.TextElideMode | str | None = None,
    align: Qt.AlignmentFlag | str | None = None,
    padding: int = 0,
) -> str:
    return draw_elided_text(
        painter,
        rect,
        text,
        font=font,
        palette=palette,
        enabled=enabled,
        options=options(mode=mode, align=align, padding=padding),
    )


def label(
    *,
    text: str = "",
    mode: Qt.TextElideMode | str | None = None,
    align: Qt.AlignmentFlag | str | None = None,
    padding: int = 0,
    tooltip: bool = True,
    parent: QWidget | None = None,
) -> ElidingLabel:
    widget = ElidingLabel(parent)
    widget.setFullText(text)
    widget.setElideMode(_parse_mode(mode))
    widget.setElideAlignment(_parse_alignment(align))
    widget.setElidePadding(padding)
    if tooltip:
        widget.setToolTip(text)
    return widget
