from dataclasses import dataclass
from typing import Dict, Optional, Tuple, Union

ColourDict = Dict[str, int]
ColourTuple = Union[Tuple[int, int, int], Tuple[int, int, int, int]]
TwinklyColourTuple = Union[Tuple[int, int, int], Tuple[int, int, int, int]]


@dataclass(frozen=True)
class TwinklyColour:
    red: int
    green: int
    blue: int
    white: Optional[int] = None

    def as_twinkly_tuple(self) -> TwinklyColourTuple:
        """Convert TwinklyColour to a tuple as used by Twinkly: (R,G,B) or (W,R,G,B)"""
        if self.white is not None:
            return (self.white, self.red, self.green, self.blue)
        else:
            return (self.red, self.green, self.blue)

    def as_tuple(self) -> ColourTuple:
        """Convert TwinklyColour to a tuple: (R,G,B) or (R,G,B,W)"""
        if self.white is not None:
            return (self.red, self.green, self.blue, self.white)
        else:
            return (self.red, self.green, self.blue)

    def __iter__(self):
        yield from self.as_tuple()

    def as_dict(self) -> ColourDict:
        """Convert TwinklyColour to a dict wth color names used by set-led functions."""
        if self.white is not None:
            return {
                "red": self.red,
                "green": self.green,
                "blue": self.blue,
                "white": self.white,
            }
        else:
            return {"red": self.red, "green": self.green, "blue": self.blue}

    @classmethod
    def from_twinkly_tuple(cls, t):
        if len(t) == 4:
            return cls(red=t[1], green=t[2], blue=t[3], white=t[0])
        elif len(t) == 3:
            return cls(red=t[0], green=t[1], blue=t[2])
        raise TypeError("Unknown colour format")
