"""Command sets for wifi bridge version 5 and lower."""

import math

from limitlessled.group.commands import Command, CommandSet
from limitlessled.group.rgbw import RGBW
from limitlessled.group.white import WHITE


class CommandLegacy(Command):
    """Represents a single v6 command to be sent to the bridge."""

    SUFFIX_BYTE = 0x00
    BRIDGE_SHORT_VERSION_MIN = 3
    BRIDGE_LONG_BYTE = 0x55

    def __init__(self, cmd_1, cmd_2, group_number, select=False, select_command=None):
        """
        Initialize command.
        :param cmd_1: The first part of the command.
        :param cmd_1: The second part of the command.
        :param group_number: Group number (1-4).
        :param select: If command requires selection.
        :param select_command: Selection command bytes.
        """
        super().__init__(cmd_1, cmd_2, group_number, select, select_command)

    def get_bytes(self, bridge):
        """
        Gets the full command as bytes.
        :param bridge: The bridge, to which the command should be sent.
        """
        if self.cmd_2 is not None:
            cmd = [self.cmd_1, self.cmd_2]
        else:
            cmd = [self.cmd_1, self.SUFFIX_BYTE]

        if bridge.version < self.BRIDGE_SHORT_VERSION_MIN:
            cmd.append(self.BRIDGE_LONG_BYTE)

        return bytearray(cmd)


class CommandSetLegacy(CommandSet):
    """Base command set for legacy wifi bridges."""

    SUPPORTED_VERSIONS = [1, 2, 3, 4, 5]
    BRIGHTNESS_OFFSET = 2

    def convert_brightness(self, brightness):
        """
        Convert the brightness from decimal percent (0.0-1.0)
        to byte representation for use in commands.
        :param brightness: The brightness from in decimal percent (0.0-1.0).
        :return: The brightness in byte representation.
        """
        brightness = math.ceil(brightness * self.brightness_steps)
        return brightness + self.BRIGHTNESS_OFFSET

    @staticmethod
    def convert_hue(hue):
        """
        Converts the hue from HSV color circle to the LimitlessLED color wheel.
        :param hue: The hue in decimal percent (0.0-1.0).
        :return: The hue regarding the LimitlessLED color wheel.
        """
        hue = hue * -1 + 1 + (2.0 / 3.0)  # RGB -> BGR

        return int(math.floor((hue % 1) * 256))

    def _build_command(self, cmd_1, cmd_2=None, select=False, select_command=None):
        """
        Constructs the complete command.
        :param cmd_1: Light command 1.
        :param cmd_2: Light command 2.
        :param select: If command requires selection.
        :param select_command: Selection command bytes.
        :return: The complete command.
        """

        return CommandLegacy(cmd_1, cmd_2, self._group_number, select, select_command)


class CommandSetWhiteLegacy(CommandSetLegacy):
    """Command set for white led light connected to legacy wifi bridge."""

    SUPPORTED_LED_TYPES = [WHITE]
    ON_BYTES = [0x38, 0x3D, 0x37, 0x32]
    OFF_BYTES = [0x3B, 0x33, 0x3A, 0x36]
    NIGHT_BYTES = [0xBB, 0xB3, 0xBA, 0xB6]
    BRIGHTNESS_STEPS = 10
    TEMPERATURE_STEPS = 10

    def __init__(self, group_number):
        """
        Initializes the command set.
        :param group_number: The group number.
        """
        super().__init__(
            group_number, self.BRIGHTNESS_STEPS, temperature_steps=self.TEMPERATURE_STEPS
        )

    def on(self):
        """
        Build command for turning the led on.
        :return: The command.
        """
        return self._build_command(self.ON_BYTES[self._group_number - 1])

    def off(self):
        """
        Build command for turning the led off.
        :return: The command.
        """
        return self._build_command(self.OFF_BYTES[self._group_number - 1])

    def night_light(self):
        """
        Build command for turning the led to night light mode.
        :return: The command.
        """
        return self._build_command(
            self.NIGHT_BYTES[self._group_number - 1], select=True, select_command=self.off()
        )

    def dimmer(self):
        """
        Build command for setting the brightness one step dimmer.
        :return: The command.
        """
        return self._build_command(0x34, select=True, select_command=self.on())

    def brighter(self):
        """
        Build command for setting the brightness one step brighter.
        :return: The command.
        """
        return self._build_command(0x3C, select=True, select_command=self.on())

    def cooler(self):
        """
        Build command for setting the temperature one step cooler.
        :return: The command.
        """
        return self._build_command(0x3F, select=True, select_command=self.on())

    def warmer(self):
        """
        Build command for setting the temperature one step warmer.
        :return: The command.
        """
        return self._build_command(0x3E, select=True, select_command=self.on())


class CommandSetRgbwLegacy(CommandSetLegacy):
    """Command set for RGBW led light connected to legacy wifi bridge."""

    SUPPORTED_LED_TYPES = [RGBW]
    HUE_STEPS = 255
    BRIGHTNESS_STEPS = 25

    def __init__(self, group_number):
        """
        Initializes the command set.
        :param group_number: The group number.
        """
        super().__init__(group_number, self.BRIGHTNESS_STEPS, hue_steps=self.HUE_STEPS)

    def on(self):
        """
        Build command for turning the led on.
        :return: The command.
        """
        return self._build_command(self._offset(0x45))

    def off(self):
        """
        Build command for turning the led off.
        :return: The command.
        """
        return self._build_command(self._offset(0x46))

    def night_light(self):
        """
        Build command for turning the led to night light mode.
        :return: The command.
        """
        return self._build_command(self._offset(0xC6), select=True, select_command=self.off())

    def white(self):
        """
        Build command for turning the led into white mode.
        :return: The command.
        """
        return self._build_command(self._offset(0xC5), select=True, select_command=self.on())

    def hue(self, hue):
        """
        Build command for setting the hue of the led.
        :param hue: Value to set (0.0-1.0).
        :return: The command.
        """
        return self._build_command(
            0x40, self.convert_hue(hue), select=True, select_command=self.on()
        )

    def brightness(self, brightness):
        """
        Build command for setting the brightness of the led.
        :param brightness: Value to set (0.0-1.0).
        :return: The command.
        """
        return self._build_command(
            0x4E, self.convert_brightness(brightness), select=True, select_command=self.on()
        )

    def _offset(self, byte):
        """Calcuate group command offset.

        :param byte: Base byte.
        :returns: Appropriate byte for group.
        """
        index = self._group_number - 1
        return byte + (index * 2)
