from __future__ import annotations

import asyncio
import threading
from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
    from collections.abc import Coroutine


class BackgroundEventLoop:
    def __init__(self) -> None:
        self.loop = asyncio.new_event_loop()
        thread = threading.Thread(
            target=self.loop.run_forever,
            name="DaftBackgroundEventLoop",
            daemon=True,
        )
        thread.start()

    @classmethod
    def from_existing_loop(cls, loop: asyncio.AbstractEventLoop) -> BackgroundEventLoop:
        obj = cls.__new__(cls)
        obj.loop = loop
        return obj

    def run(self, future: Coroutine[Any, Any, Any]) -> Any:
        return asyncio.run_coroutine_threadsafe(future, self.loop).result()


LOOP: BackgroundEventLoop | None = None


def set_event_loop(loop: asyncio.AbstractEventLoop) -> None:
    global LOOP
    LOOP = BackgroundEventLoop.from_existing_loop(loop)


def get_or_init_event_loop() -> BackgroundEventLoop:
    global LOOP
    if LOOP is None:
        LOOP = BackgroundEventLoop()
    return LOOP