"""Matter ModeSelect Cluster Support."""

from __future__ import annotations

from chip.clusters import Objects as clusters

from homeassistant.components.select import SelectEntity, SelectEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory, Platform
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from .entity import MatterEntity
from .helpers import get_matter
from .models import MatterDiscoverySchema

type SelectCluster = (
    clusters.ModeSelect
    | clusters.OvenMode
    | clusters.LaundryWasherMode
    | clusters.RefrigeratorAndTemperatureControlledCabinetMode
    | clusters.RvcRunMode
    | clusters.RvcCleanMode
    | clusters.DishwasherMode
    | clusters.MicrowaveOvenMode
    | clusters.EnergyEvseMode
    | clusters.DeviceEnergyManagementMode
)


async def async_setup_entry(
    hass: HomeAssistant,
    config_entry: ConfigEntry,
    async_add_entities: AddEntitiesCallback,
) -> None:
    """Set up Matter ModeSelect from Config Entry."""
    matter = get_matter(hass)
    matter.register_platform_handler(Platform.SELECT, async_add_entities)


class MatterModeSelectEntity(MatterEntity, SelectEntity):
    """Representation of a select entity from Matter (Mode) Cluster attribute(s)."""

    async def async_select_option(self, option: str) -> None:
        """Change the selected mode."""
        cluster: SelectCluster = self._endpoint.get_cluster(
            self._entity_info.primary_attribute.cluster_id
        )
        # select the mode ID from the label string
        for mode in cluster.supportedModes:
            if mode.label != option:
                continue
            await self.matter_client.send_device_command(
                node_id=self._endpoint.node.node_id,
                endpoint_id=self._endpoint.endpoint_id,
                command=cluster.Commands.ChangeToMode(newMode=mode.mode),
            )
            break

    @callback
    def _update_from_device(self) -> None:
        """Update from device."""
        # NOTE: cluster can be ModeSelect or a variant of that,
        # such as DishwasherMode. They all have the same characteristics.
        cluster: SelectCluster = self._endpoint.get_cluster(
            self._entity_info.primary_attribute.cluster_id
        )
        modes = {mode.mode: mode.label for mode in cluster.supportedModes}
        self._attr_options = list(modes.values())
        self._attr_current_option = modes[cluster.currentMode]
        # handle optional Description attribute as descriptive name for the mode
        if desc := getattr(cluster, "description", None):
            self._attr_name = desc


# Discovery schema(s) to map Matter Attributes to HA entities
DISCOVERY_SCHEMAS = [
    MatterDiscoverySchema(
        platform=Platform.SELECT,
        entity_description=SelectEntityDescription(
            key="MatterModeSelect",
            entity_category=EntityCategory.CONFIG,
            translation_key="mode",
        ),
        entity_class=MatterModeSelectEntity,
        required_attributes=(
            clusters.ModeSelect.Attributes.CurrentMode,
            clusters.ModeSelect.Attributes.SupportedModes,
        ),
    ),
    MatterDiscoverySchema(
        platform=Platform.SELECT,
        entity_description=SelectEntityDescription(
            key="MatterOvenMode",
            translation_key="mode",
        ),
        entity_class=MatterModeSelectEntity,
        required_attributes=(
            clusters.OvenMode.Attributes.CurrentMode,
            clusters.OvenMode.Attributes.SupportedModes,
        ),
    ),
    MatterDiscoverySchema(
        platform=Platform.SELECT,
        entity_description=SelectEntityDescription(
            key="MatterLaundryWasherMode",
            translation_key="mode",
        ),
        entity_class=MatterModeSelectEntity,
        required_attributes=(
            clusters.LaundryWasherMode.Attributes.CurrentMode,
            clusters.LaundryWasherMode.Attributes.SupportedModes,
        ),
    ),
    MatterDiscoverySchema(
        platform=Platform.SELECT,
        entity_description=SelectEntityDescription(
            key="MatterRefrigeratorAndTemperatureControlledCabinetMode",
            translation_key="mode",
        ),
        entity_class=MatterModeSelectEntity,
        required_attributes=(
            clusters.RefrigeratorAndTemperatureControlledCabinetMode.Attributes.CurrentMode,
            clusters.RefrigeratorAndTemperatureControlledCabinetMode.Attributes.SupportedModes,
        ),
    ),
    MatterDiscoverySchema(
        platform=Platform.SELECT,
        entity_description=SelectEntityDescription(
            key="MatterRvcRunMode",
            translation_key="mode",
        ),
        entity_class=MatterModeSelectEntity,
        required_attributes=(
            clusters.RvcRunMode.Attributes.CurrentMode,
            clusters.RvcRunMode.Attributes.SupportedModes,
        ),
    ),
    MatterDiscoverySchema(
        platform=Platform.SELECT,
        entity_description=SelectEntityDescription(
            key="MatterRvcCleanMode",
            translation_key="mode",
        ),
        entity_class=MatterModeSelectEntity,
        required_attributes=(
            clusters.RvcCleanMode.Attributes.CurrentMode,
            clusters.RvcCleanMode.Attributes.SupportedModes,
        ),
    ),
    MatterDiscoverySchema(
        platform=Platform.SELECT,
        entity_description=SelectEntityDescription(
            key="MatterDishwasherMode",
            translation_key="mode",
        ),
        entity_class=MatterModeSelectEntity,
        required_attributes=(
            clusters.DishwasherMode.Attributes.CurrentMode,
            clusters.DishwasherMode.Attributes.SupportedModes,
        ),
    ),
    MatterDiscoverySchema(
        platform=Platform.SELECT,
        entity_description=SelectEntityDescription(
            key="MatterMicrowaveOvenMode",
            translation_key="mode",
        ),
        entity_class=MatterModeSelectEntity,
        required_attributes=(
            clusters.MicrowaveOvenMode.Attributes.CurrentMode,
            clusters.MicrowaveOvenMode.Attributes.SupportedModes,
        ),
    ),
    MatterDiscoverySchema(
        platform=Platform.SELECT,
        entity_description=SelectEntityDescription(
            key="MatterEnergyEvseMode",
            translation_key="mode",
        ),
        entity_class=MatterModeSelectEntity,
        required_attributes=(
            clusters.EnergyEvseMode.Attributes.CurrentMode,
            clusters.EnergyEvseMode.Attributes.SupportedModes,
        ),
    ),
    MatterDiscoverySchema(
        platform=Platform.SELECT,
        entity_description=SelectEntityDescription(
            key="MatterDeviceEnergyManagementMode",
            translation_key="mode",
        ),
        entity_class=MatterModeSelectEntity,
        required_attributes=(
            clusters.DeviceEnergyManagementMode.Attributes.CurrentMode,
            clusters.DeviceEnergyManagementMode.Attributes.SupportedModes,
        ),
    ),
]