"""The Remote Python Debugger integration."""
from __future__ import annotations

from asyncio import Event, get_running_loop
import logging
from threading import Thread

import debugpy
import voluptuous as vol

from homeassistant.const import CONF_HOST, CONF_PORT
from homeassistant.core import HomeAssistant, ServiceCall
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.service import async_register_admin_service
from homeassistant.helpers.typing import ConfigType

DOMAIN = "debugpy"
CONF_START = "start"
CONF_WAIT = "wait"
SERVICE_START = "start"

CONFIG_SCHEMA = vol.Schema(
    {
        DOMAIN: vol.Schema(
            {
                vol.Optional(CONF_HOST, default="0.0.0.0"): cv.string,
                vol.Optional(CONF_PORT, default=5678): cv.port,
                vol.Optional(CONF_START, default=True): cv.boolean,
                vol.Optional(CONF_WAIT, default=False): cv.boolean,
            }
        )
    },
    extra=vol.ALLOW_EXTRA,
)

_LOGGER = logging.getLogger(__name__)


async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the Remote Python Debugger component."""
    conf = config[DOMAIN]

    async def debug_start(
        call: ServiceCall | None = None, *, wait: bool = True
    ) -> None:
        """Enable asyncio debugging and start the debugger."""
        get_running_loop().set_debug(True)

        debugpy.listen((conf[CONF_HOST], conf[CONF_PORT]))

        wait = conf[CONF_WAIT]
        if wait:
            _LOGGER.warning(
                "Waiting for remote debug connection on %s:%s",
                conf[CONF_HOST],
                conf[CONF_PORT],
            )
            ready = Event()

            def waitfor():
                debugpy.wait_for_client()
                hass.loop.call_soon_threadsafe(ready.set)

            Thread(target=waitfor).start()

            await ready.wait()
        else:
            _LOGGER.warning(
                "Listening for remote debug connection on %s:%s",
                conf[CONF_HOST],
                conf[CONF_PORT],
            )

    async_register_admin_service(
        hass, DOMAIN, SERVICE_START, debug_start, schema=vol.Schema({})
    )

    # If set to start the debugger on startup, do so
    if conf[CONF_START]:
        await debug_start(wait=conf[CONF_WAIT])

    return True
