"""Handle forward of events transmitted by Hue devices to HASS."""
import logging
from typing import TYPE_CHECKING

from aiohue.v2 import HueBridgeV2
from aiohue.v2.controllers.events import EventType
from aiohue.v2.models.button import Button
from aiohue.v2.models.relative_rotary import RelativeRotary

from homeassistant.const import CONF_DEVICE_ID, CONF_ID, CONF_TYPE, CONF_UNIQUE_ID
from homeassistant.core import callback
from homeassistant.helpers import device_registry as dr
from homeassistant.util import slugify

from ..const import ATTR_HUE_EVENT, CONF_SUBTYPE, DOMAIN

CONF_CONTROL_ID = "control_id"
CONF_DURATION = "duration"
CONF_STEPS = "steps"

if TYPE_CHECKING:
    from ..bridge import HueBridge

LOGGER = logging.getLogger(__name__)


async def async_setup_hue_events(bridge: "HueBridge"):
    """Manage listeners for stateless Hue sensors that emit events."""
    hass = bridge.hass
    api: HueBridgeV2 = bridge.api  # to satisfy typing
    conf_entry = bridge.config_entry
    dev_reg = dr.async_get(hass)

    btn_controller = api.sensors.button
    rotary_controller = api.sensors.relative_rotary

    @callback
    def handle_button_event(evt_type: EventType, hue_resource: Button) -> None:
        """Handle event from Hue button resource controller."""
        LOGGER.debug("Received button event: %s", hue_resource)

        # guard for missing button object on the resource
        if hue_resource.button is None:
            return

        hue_device = btn_controller.get_device(hue_resource.id)
        device = dev_reg.async_get_device(identifiers={(DOMAIN, hue_device.id)})

        # Fire event
        data = {
            # send slugified entity name as id = backwards compatibility with previous version
            CONF_ID: slugify(f"{hue_device.metadata.name} Button"),
            CONF_DEVICE_ID: device.id,  # type: ignore[union-attr]
            CONF_UNIQUE_ID: hue_resource.id,
            CONF_TYPE: hue_resource.button.last_event.value,
            CONF_SUBTYPE: hue_resource.metadata.control_id,
        }
        hass.bus.async_fire(ATTR_HUE_EVENT, data)

    # add listener for updates from `button` resource
    conf_entry.async_on_unload(
        btn_controller.subscribe(
            handle_button_event, event_filter=EventType.RESOURCE_UPDATED
        )
    )

    @callback
    def handle_rotary_event(evt_type: EventType, hue_resource: RelativeRotary) -> None:
        """Handle event from Hue relative_rotary resource controller."""
        LOGGER.debug("Received relative_rotary event: %s", hue_resource)

        hue_device = btn_controller.get_device(hue_resource.id)
        device = dev_reg.async_get_device(identifiers={(DOMAIN, hue_device.id)})

        # Fire event
        data = {
            CONF_DEVICE_ID: device.id,  # type: ignore[union-attr]
            CONF_UNIQUE_ID: hue_resource.id,
            CONF_TYPE: hue_resource.relative_rotary.last_event.action.value,
            CONF_SUBTYPE: hue_resource.relative_rotary.last_event.rotation.direction.value,
            CONF_DURATION: hue_resource.relative_rotary.last_event.rotation.duration,
            CONF_STEPS: hue_resource.relative_rotary.last_event.rotation.steps,
        }
        hass.bus.async_fire(ATTR_HUE_EVENT, data)

    # add listener for updates from `relative_rotary` resource
    conf_entry.async_on_unload(
        rotary_controller.subscribe(
            handle_rotary_event, event_filter=EventType.RESOURCE_UPDATED
        )
    )
