"""Helpers for Roku."""
from __future__ import annotations

from collections.abc import Awaitable, Callable, Coroutine
from functools import wraps
from typing import Any, TypeVar

from rokuecp import RokuConnectionError, RokuConnectionTimeoutError, RokuError
from typing_extensions import Concatenate, ParamSpec

from homeassistant.exceptions import HomeAssistantError

from .entity import RokuEntity

_RokuEntityT = TypeVar("_RokuEntityT", bound=RokuEntity)
_P = ParamSpec("_P")


def format_channel_name(channel_number: str, channel_name: str | None = None) -> str:
    """Format a Roku Channel name."""
    if channel_name is not None and channel_name != "":
        return f"{channel_name} ({channel_number})"

    return channel_number


def roku_exception_handler(
    ignore_timeout: bool = False,
) -> Callable[
    [Callable[Concatenate[_RokuEntityT, _P], Awaitable[Any]]],
    Callable[Concatenate[_RokuEntityT, _P], Coroutine[Any, Any, None]],
]:
    """Decorate Roku calls to handle Roku exceptions."""

    def decorator(
        func: Callable[Concatenate[_RokuEntityT, _P], Awaitable[Any]],
    ) -> Callable[Concatenate[_RokuEntityT, _P], Coroutine[Any, Any, None]]:
        @wraps(func)
        async def wrapper(
            self: _RokuEntityT, *args: _P.args, **kwargs: _P.kwargs
        ) -> None:
            try:
                await func(self, *args, **kwargs)
            except RokuConnectionTimeoutError as error:
                if not ignore_timeout:
                    raise HomeAssistantError(
                        "Timeout communicating with Roku API"
                    ) from error
            except RokuConnectionError as error:
                raise HomeAssistantError("Error communicating with Roku API") from error
            except RokuError as error:
                raise HomeAssistantError("Invalid response from Roku API") from error

        return wrapper

    return decorator
