"""Intents for the light integration."""
import voluptuous as vol

from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.core import HomeAssistant, State
from homeassistant.helpers import intent
import homeassistant.helpers.config_validation as cv
import homeassistant.util.color as color_util

from . import (
    ATTR_BRIGHTNESS_PCT,
    ATTR_RGB_COLOR,
    ATTR_SUPPORTED_COLOR_MODES,
    DOMAIN,
    SERVICE_TURN_ON,
    brightness_supported,
    color_supported,
)

INTENT_SET = "HassLightSet"


async def async_setup_intents(hass: HomeAssistant) -> None:
    """Set up the light intents."""
    hass.helpers.intent.async_register(SetIntentHandler())


def _test_supports_color(state: State) -> None:
    """Test if state supports colors."""
    supported_color_modes = state.attributes.get(ATTR_SUPPORTED_COLOR_MODES)
    if not color_supported(supported_color_modes):
        raise intent.IntentHandleError(
            f"Entity {state.name} does not support changing colors"
        )


def _test_supports_brightness(state: State) -> None:
    """Test if state supports brightness."""
    supported_color_modes = state.attributes.get(ATTR_SUPPORTED_COLOR_MODES)
    if not brightness_supported(supported_color_modes):
        raise intent.IntentHandleError(
            f"Entity {state.name} does not support changing brightness"
        )


class SetIntentHandler(intent.IntentHandler):
    """Handle set color intents."""

    intent_type = INTENT_SET
    slot_schema = {
        vol.Required("name"): cv.string,
        vol.Optional("color"): color_util.color_name_to_rgb,
        vol.Optional("brightness"): vol.All(vol.Coerce(int), vol.Range(0, 100)),
    }

    async def async_handle(self, intent_obj: intent.Intent) -> intent.IntentResponse:
        """Handle the hass intent."""
        hass = intent_obj.hass
        slots = self.async_validate_slots(intent_obj.slots)
        state = hass.helpers.intent.async_match_state(
            slots["name"]["value"], hass.states.async_all(DOMAIN)
        )

        service_data = {ATTR_ENTITY_ID: state.entity_id}
        speech_parts = []

        if "color" in slots:
            _test_supports_color(state)
            service_data[ATTR_RGB_COLOR] = slots["color"]["value"]
            # Use original passed in value of the color because we don't have
            # human readable names for that internally.
            speech_parts.append(f"the color {intent_obj.slots['color']['value']}")

        if "brightness" in slots:
            _test_supports_brightness(state)
            service_data[ATTR_BRIGHTNESS_PCT] = slots["brightness"]["value"]
            speech_parts.append(f"{slots['brightness']['value']}% brightness")

        await hass.services.async_call(
            DOMAIN, SERVICE_TURN_ON, service_data, context=intent_obj.context
        )

        response = intent_obj.create_response()

        if not speech_parts:  # No attributes changed
            speech = f"Turned on {state.name}"
        else:
            parts = [f"Changed {state.name} to"]
            for index, part in enumerate(speech_parts):
                if index == 0:
                    parts.append(f" {part}")
                elif index != len(speech_parts) - 1:
                    parts.append(f", {part}")
                else:
                    parts.append(f" and {part}")
            speech = "".join(parts)

        response.async_set_speech(speech)
        return response