"""Class to control the lights."""
from ..color import COLORS
from ..command import Command
from ..const import (
    ATTR_DEVICE_STATE,
    ATTR_LIGHT_COLOR_HEX,
    ATTR_LIGHT_COLOR_HUE,
    ATTR_LIGHT_COLOR_SATURATION,
    ATTR_LIGHT_COLOR_X,
    ATTR_LIGHT_COLOR_Y,
    ATTR_LIGHT_CONTROL,
    ATTR_LIGHT_DIMMER,
    ATTR_LIGHT_MIREDS,
    ATTR_TRANSITION_TIME,
    RANGE_BRIGHTNESS,
    RANGE_HUE,
    RANGE_MIREDS,
    RANGE_SATURATION,
    RANGE_X,
    RANGE_Y,
)
from ..error import ColorError
from .base_controller import BaseController
from .light import Light


class LightControl(BaseController):
    """Class to control the lights."""

    def __init__(self, device):
        """Create object of class."""
        super().__init__(device)

        self.can_set_dimmer = None
        self.can_set_temp = None
        self.can_set_xy = None
        self.can_set_color = None
        self.can_combine_commands = None

        if ATTR_LIGHT_DIMMER in self.raw[0]:
            self.can_set_dimmer = True

        if ATTR_LIGHT_MIREDS in self.raw[0]:
            self.can_set_temp = True

        if ATTR_LIGHT_COLOR_X in self.raw[0]:
            self.can_set_xy = True

        if ATTR_LIGHT_COLOR_HUE in self.raw[0]:
            self.can_set_color = True

        # Currently uncertain which bulbs are capable of setting
        # multiple values simultaneously. As of gateway firmware
        # 1.3.14 1st party bulbs do not seem to support this properly,
        # but (at least some) hue bulbs do.
        if "Philips" in self._device.device_info.manufacturer:
            self.can_combine_commands = True

        self.min_mireds = RANGE_MIREDS[0]
        self.max_mireds = RANGE_MIREDS[1]

        self.min_hue = RANGE_HUE[0]
        self.max_hue = RANGE_HUE[1]

        self.min_saturation = RANGE_SATURATION[0]
        self.max_saturation = RANGE_SATURATION[1]

    @property
    def raw(self):
        """Return raw data that it represents."""
        return self._device.raw[ATTR_LIGHT_CONTROL]

    @property
    def lights(self):
        """Return light objects of the light control."""
        return [Light(self._device, i) for i in range(len(self.raw))]

    def set_state(self, state, *, index=0):
        """Set state of a light."""
        return self.set_values({ATTR_DEVICE_STATE: int(state)}, index=index)

    def set_dimmer(self, dimmer, *, index=0, transition_time=None):
        """Set dimmer value of a light.

        transition_time: Integer representing tenth of a second (default None)
        """
        self._value_validate(dimmer, RANGE_BRIGHTNESS, "Dimmer")

        values = {ATTR_LIGHT_DIMMER: dimmer}

        if transition_time is not None:
            values[ATTR_TRANSITION_TIME] = transition_time

        return self.set_values(values, index=index)

    def set_color_temp(self, color_temp, *, index=0, transition_time=None):
        """Set color temp a light."""
        self._value_validate(color_temp, RANGE_MIREDS, "Color temperature")

        values = {ATTR_LIGHT_MIREDS: color_temp}

        if transition_time is not None:
            values[ATTR_TRANSITION_TIME] = transition_time

        return self.set_values(values, index=index)

    def set_hex_color(self, color, *, index=0, transition_time=None):
        """Set hex color of the light."""
        values = {
            ATTR_LIGHT_COLOR_HEX: color,
        }

        if transition_time is not None:
            values[ATTR_TRANSITION_TIME] = transition_time

        return self.set_values(values, index=index)

    def set_xy_color(self, color_x, color_y, *, index=0, transition_time=None):
        """Set xy color of the light."""
        self._value_validate(color_x, RANGE_X, "X color")
        self._value_validate(color_y, RANGE_Y, "Y color")

        values = {ATTR_LIGHT_COLOR_X: color_x, ATTR_LIGHT_COLOR_Y: color_y}

        if transition_time is not None:
            values[ATTR_TRANSITION_TIME] = transition_time

        return self.set_values(values, index=index)

    def set_hsb(
        self, hue, saturation, brightness=None, *, index=0, transition_time=None
    ):
        """Set HSB color settings of the light."""
        self._value_validate(hue, RANGE_HUE, "Hue")
        self._value_validate(saturation, RANGE_SATURATION, "Saturation")

        values = {ATTR_LIGHT_COLOR_SATURATION: saturation, ATTR_LIGHT_COLOR_HUE: hue}

        if brightness is not None:
            values[ATTR_LIGHT_DIMMER] = brightness
            self._value_validate(brightness, RANGE_BRIGHTNESS, "Brightness")

        if transition_time is not None:
            values[ATTR_TRANSITION_TIME] = transition_time

        return self.set_values(values, index=index)

    def set_predefined_color(self, colorname, *, index=0, transition_time=None):
        """Set predefined color."""
        try:
            color = COLORS[colorname.lower().replace(" ", "_")]
            return self.set_hex_color(
                color, index=index, transition_time=transition_time
            )
        except KeyError:
            raise ColorError("Invalid color specified: %s", colorname)

    def set_values(self, values, *, index=0):
        """Set values on light control.

        Returns a Command.
        """
        assert len(self.raw) == 1, "Only devices with 1 light supported"

        return Command("put", self._device.path, {ATTR_LIGHT_CONTROL: [values]})
