"""Support for Russound multizone controllers using RIO Protocol."""
from __future__ import annotations

from russound_rio import Russound
import voluptuous as vol

from homeassistant.components.media_player import PLATFORM_SCHEMA, MediaPlayerEntity
from homeassistant.components.media_player.const import (
    MEDIA_TYPE_MUSIC,
    SUPPORT_SELECT_SOURCE,
    SUPPORT_TURN_OFF,
    SUPPORT_TURN_ON,
    SUPPORT_VOLUME_MUTE,
    SUPPORT_VOLUME_SET,
)
from homeassistant.const import (
    CONF_HOST,
    CONF_NAME,
    CONF_PORT,
    EVENT_HOMEASSISTANT_STOP,
    STATE_OFF,
    STATE_ON,
)
from homeassistant.core import HomeAssistant, callback
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType

SUPPORT_RUSSOUND = (
    SUPPORT_VOLUME_MUTE
    | SUPPORT_VOLUME_SET
    | SUPPORT_TURN_ON
    | SUPPORT_TURN_OFF
    | SUPPORT_SELECT_SOURCE
)

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
    {
        vol.Required(CONF_HOST): cv.string,
        vol.Required(CONF_NAME): cv.string,
        vol.Optional(CONF_PORT, default=9621): cv.port,
    }
)


async def async_setup_platform(
    hass: HomeAssistant,
    config: ConfigType,
    async_add_entities: AddEntitiesCallback,
    discovery_info: DiscoveryInfoType | None = None,
) -> None:
    """Set up the Russound RIO platform."""

    host = config.get(CONF_HOST)
    port = config.get(CONF_PORT)

    russ = Russound(hass.loop, host, port)

    await russ.connect()

    # Discover sources and zones
    sources = await russ.enumerate_sources()
    valid_zones = await russ.enumerate_zones()

    devices = []
    for zone_id, name in valid_zones:
        await russ.watch_zone(zone_id)
        dev = RussoundZoneDevice(russ, zone_id, name, sources)
        devices.append(dev)

    @callback
    def on_stop(event):
        """Shutdown cleanly when hass stops."""
        hass.loop.create_task(russ.close())

    hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, on_stop)

    async_add_entities(devices)


class RussoundZoneDevice(MediaPlayerEntity):
    """Representation of a Russound Zone."""

    def __init__(self, russ, zone_id, name, sources):
        """Initialize the zone device."""
        super().__init__()
        self._name = name
        self._russ = russ
        self._zone_id = zone_id
        self._sources = sources

    def _zone_var(self, name, default=None):
        return self._russ.get_cached_zone_variable(self._zone_id, name, default)

    def _source_var(self, name, default=None):
        current = int(self._zone_var("currentsource", 0))
        if current: