"""This module contains a few concrete colour cycles to play with"""

from colorcycletemplate import ColorCycleTemplate

class StrandTest(ColorCycleTemplate):
    """Runs a simple strand test (9 LEDs wander through the strip)."""

    color = None

    def init(self, strip, num_led):
        self.color = 0x000000  # Initialize with black

    def update(self, strip, num_led, num_steps_per_cycle, current_step,
               current_cycle):
        # One cycle = The 9 Test-LEDs wander through numStepsPerCycle LEDs.
        if current_step == 0:
            self.color >>= 8  # Red->green->blue->black
        if self.color == 0:
            self.color = 0xFF0000  # If black, reset to red
        len = 9
        if num_led - 1 < len:
            len = num_led - 1 
        # The head pixel that will be turned on in this cycle
        head = (current_step + len) % num_steps_per_cycle
        tail = current_step # The tail pixel that will be turned off
        strip.set_pixel_rgb(head, self.color)  # Paint head
        strip.set_pixel_rgb(tail, 0)  # Clear tail

        return 1 # Repaint is necessary


class TheaterChase(ColorCycleTemplate):
    """Runs a 'marquee' effect around the strip."""
    def update(self, strip, num_led=10, num_steps_per_cycle=35, current_step=1,
               current_cycle=1):
        # One cycle = One trip through the color wheel, 0..254
        # Few cycles = quick transition, lots of cycles = slow transition
        # Note: For a smooth transition between cycles, numStepsPerCycle must
        # be a multiple of 7
        start_index = current_step % 7 # One segment is 2 blank, and 5 filled
        color_index = strip.wheel(int(round(255/num_steps_per_cycle *
                                            current_step, 0)))
        for pixel in range(num_led):
            # Two LEDs out of 7 are blank. At each step, the blank
            # ones move one pixel ahead.
            if ((pixel+start_index) % 7 == 0) or ((pixel+start_index) % 7 == 1):
                strip.set_pixel_rgb(pixel, 0)
            else: strip.set_pixel_rgb(pixel, color_index)
        return 1


class RoundAndRound(ColorCycleTemplate):
    """Runs three LEDs around the strip."""

    def init(self, strip, num_led):
        strip.set_pixel_rgb(0, 0xFF0000)
        strip.set_pixel_rgb(1, 0xFF0000, 5) # Only 5% brightness
        strip.set_pixel_rgb(2, 0xFF0000)

    def update(self, strip, num_led, num_steps_per_cycle, current_step,
               current_cycle):
        # Simple class to demonstrate the "rotate" method
        strip.rotate()
        return 1

class Swirl(ColorCycleTemplate):
    

    def init(self, strip, num_led):
        strip.set_pixel_rgb(0, #WTG1#)
        strip.set_pixel_rgb(1, #WTG2#) 
        strip.set_pixel_rgb(2, #WTG2#)
        strip.set_pixel_rgb(3, #WTG2#)
        strip.set_pixel_rgb(4, #WTG2#)
        strip.set_pixel_rgb(5, #WTG1#)
        strip.set_pixel_rgb(6, #WTG3#)
        strip.set_pixel_rgb(7, #WTG3#)
        strip.set_pixel_rgb(8, #WTG3#)
        strip.set_pixel_rgb(9, #WTG3#)

    def update(self, strip, num_led, num_steps_per_cycle, current_step,
               current_cycle):
        # Simple class to demonstrate the "rotate" method
        strip.rotate()
        return 1



class Off(ColorCycleTemplate):
    """Paints the strip with one colour."""

    def init(self, strip, num_led=10):
        for led in range(0, num_led):
            strip.set_pixel_rgb(led,0x000000,0) # Paint 5% white

    def update(self, strip, num_led, num_steps_per_cycle, current_step,
               current_cycle):
        # Do nothing: Init lit the strip, and update just keeps it this way
        return 0


class Green(ColorCycleTemplate):
    """Paints the strip with one colour."""

    def init(self, strip, num_led=10):
        for led in range(0, num_led):
            strip.set_pixel_rgb(led,0x0000FF,100) # Paint 5% white

    def update(self, strip, num_led, num_steps_per_cycle, current_step,
               current_cycle):
        if current_step == 0:
            for led in range(0, num_led):
                strip.set_pixel_rgb(led,0x0000FF,100) # Paint 5% yellow
        if current_step ==1:
            for led in range(0, num_led):
                strip.set_pixel_rgb(led,0x000000,100)
        # Alternate on and off
        return 1
    
class Yellow(ColorCycleTemplate):
    """Paints the strip with one colour."""

    def init(self, strip, num_led=10):
        for led in range(0, num_led):
            strip.set_pixel_rgb(led,0xFF00FF,100) # Paint 5% white

    def update(self, strip, num_led, num_steps_per_cycle, current_step,
               current_cycle):
        if current_step == 0:
            for led in range(0, num_led):
                strip.set_pixel_rgb(led,0xFF00FF,100) # Paint 5% yellow
        if current_step ==1:
            for led in range(0, num_led):
                strip.set_pixel_rgb(led,0x000000,100)
        # Alternate on and off
        return 1

class Red(ColorCycleTemplate):
    """Paints the strip with one colour."""

    def init(self, strip, num_led=10):
        for led in range(0, num_led):
            strip.set_pixel_rgb(led,0xFF0000,100) # Paint 5% white

    def update(self, strip, num_led, num_steps_per_cycle, current_step,
               current_cycle):
        if current_step == 0:
            for led in range(0, num_led):
                strip.set_pixel_rgb(led,0xFF0000,100) # Paint 5% yellow
        if current_step ==1:
            for led in range(0, num_led):
                strip.set_pixel_rgb(led,0x000000,100)
        # Alternate on and off
        return 1


class RedSolid(ColorCycleTemplate):
    """Paints the strip with one colour."""

    def init(self, strip, num_led=10):
        for led in range(0, num_led):
            strip.set_pixel_rgb(led,0xFF0000,40) # Paint 5% white

    def update(self, strip, num_led, num_steps_per_cycle, current_step,
               current_cycle):
        # Do nothing: Init lit the strip, and update just keeps it this way
        return 0

class OrangeSolid(ColorCycleTemplate):
    """Paints the strip with one colour."""

    def init(self, strip, num_led=10):
        for led in range(0, num_led):
            strip.set_pixel_rgb(led,0xFF0058,40) # Paint 5% white

    def update(self, strip, num_led, num_steps_per_cycle, current_step,
               current_cycle):
        # Do nothing: Init lit the strip, and update just keeps it this way
        return 0



class Rainbow(ColorCycleTemplate):
    """Paints a rainbow effect across the entire strip."""
    def update(self, strip, num_led, num_steps_per_cycle, current_step,
               current_cycle):
        # One cycle = One trip through the color wheel, 0..254
        # Few cycles = quick transition, lots of cycles = slow transition
        # -> LED 0 goes from index 0 to 254 in numStepsPerCycle cycles.
        #     So it might have to step up more or less than one index
        #     depending on numStepsPerCycle.
        # -> The other LEDs go up to 254, then wrap around to zero and go up
        #     again until the last one is just below LED 0. This way, the
        #     strip always shows one full rainbow, regardless of the
        #     number of LEDs
        scale_factor = 255 / num_led # Index change between two neighboring LEDs
        start_index = 255 / num_steps_per_cycle * current_step # LED 0
        for i in range(num_led):
            # Index of LED i, not rounded and not wrapped at 255
            led_index = start_index + i * scale_factor
            # Now rounded and wrapped
            led_index_rounded_wrapped = int(round(led_index, 0)) % 255
            # Get the actual color out of the wheel
            pixel_color = strip.wheel(led_index_rounded_wrapped)
            strip.set_pixel_rgb(i, pixel_color)
        return 1 # All pixels are set in the buffer, so repaint the strip now
