"""Support for Lutron events."""

from enum import StrEnum
from typing import cast, override

from pylutron import Button, Keypad, Lutron, LutronEntity, LutronEvent

from homeassistant.components.event import EventEntity
from homeassistant.const import ATTR_ID
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.util import slugify

from . import ATTR_ACTION, ATTR_FULL_ID, ATTR_UUID, LutronConfigEntry
from .entity import LutronKeypad


class LutronEventType(StrEnum):
    """Lutron event types."""

    SINGLE_PRESS = "single_press"
    PRESS = "press"
    RELEASE = "release"


LEGACY_EVENT_TYPES: dict[LutronEventType, str] = {
    LutronEventType.SINGLE_PRESS: "single",
    LutronEventType.PRESS: "pressed",
    LutronEventType.RELEASE: "released",
}


async def async_setup_entry(
    hass: HomeAssistant,
    config_entry: LutronConfigEntry,
    async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
    """Set up the Lutron event platform."""
    entry_data = config_entry.runtime_data

    async_add_entities(
        LutronEventEntity(
            hass, area_name, keypad, button, entry_data.client, config_entry.entry_id
        )
        for area_name, keypad, button in entry_data.buttons
    )


class LutronEventEntity(LutronKeypad, EventEntity):
    """Representation of a Lutron keypad button."""

    _attr_translation_key = "button"

    def __init__(
        self,
        hass: HomeAssistant,
        area_name: str,
        keypad: Keypad,
        button: Button,
        controller: Lutron,
        config_entry_id: str,
    ) -> None:
        """Initialize the button."""
        super().__init__(hass, area_name, button, controller, keypad, config_entry_id)
        if (name := button.name) == "Unknown Button":
            name += f" {button.number}"
        self._attr_name = name
        self._has_release_event = (
            button.button_type is not None and "RaiseLower" in button.button_type
        )
        if self._has_release_event:
            self._attr_event_types = [LutronEventType.PRESS, LutronEventType.RELEASE]
        else:
            self._attr_event_types = [LutronEventType.SINGLE_PRESS]

        self._full_id = slugify(f"{area_name} {name}")
        self._id = slugify(name)

    @override
    async def async_added_to_hass(self) -> None:
        """Register callbacks."""
        await super().async_added_to_hass()
        self.async_on_remove(self._lutron_device.subscribe(self.handle_event, None))

    @callback
    def handle_event(
        self, button: LutronEntity, _context: None, event: LutronEvent, _params: dict
    ) -> None:
        """Handle received event."""
        button = cast(Button, button)
        action: LutronEventType | None = None
        if self._has_release_event:
            if event == Button.Event.PRESSED:
                action = LutronEventType.PRESS
            else:
                action = LutronEventType.RELEASE
        elif event == Button.Event.PRESSED:
            action = LutronEventType.SINGLE_PRESS

        if action:
            data = {
                ATTR_ID: self._id,
                ATTR_ACTION: LEGACY_EVENT_TYPES[action],
                ATTR_FULL_ID: self._full_id,
                ATTR_UUID: button.uuid,
            }
            self.hass.bus.fire("lutron_event", data)
            self._trigger_event(action)
            self.schedule_update_ha_state()
