from asyncio import Task
from collections.abc import Callable, Coroutine
from functools import wraps
from typing import Any, cast

from gi._gtktemplate import CallThing
from gi.repository import Gio, Gtk


def create(coro: Coroutine[Any, Any, Any]) -> Task[Any]:
    """Create a task with `Gio.Application`."""
    if not (app := Gio.Application.get_default()):
        raise ValueError(app)

    return cast(Task[Any], app.create_asyncio_task(coro))  # type: ignore[attr-defined]


def callback[**P](func: Callable[P, Coroutine[Any, Any, Any]]) -> CallThing:
    """Create an async `Gtk.Template.Callback`."""

    @Gtk.Template.Callback()
    @wraps(func)
    def wrapper(*args: P.args, **kwargs: P.kwargs) -> None:
        create(func(*args, **kwargs))

    return wrapper
