# Rainbow lightsaber in MicroPython for the Micro:bit V2.
# Addressable LED strip: data on pin 1, power from 3V and GND. Button A ignites, B retracts,
# shake flashes, tilt left and right changes the colour.
from microbit import *
import neopixel

LEDS = 10                # one strip; each extra strip adds 10
BRIGHTNESS = 40          # of 255: the Micro:bit powers the whole strip, keep it low

strip = neopixel.NeoPixel(pin1, LEDS)


def hue_color(hue):
    """A colour on the colour wheel (hue 0 to 359), already made dimmer."""
    hue = hue % 360
    part = hue % 60 * 255 // 60
    if hue < 60:
        red, green, blue = 255, part, 0
    elif hue < 120:
        red, green, blue = 255 - part, 255, 0
    elif hue < 180:
        red, green, blue = 0, 255, part
    elif hue < 240:
        red, green, blue = 0, 255 - part, 255
    elif hue < 300:
        red, green, blue = part, 0, 255
    else:
        red, green, blue = 255, 0, 255 - part
    return (red * BRIGHTNESS // 255, green * BRIGHTNESS // 255, blue * BRIGHTNESS // 255)


def fill(color):
    for index in range(LEDS):
        strip[index] = color
    strip.show()


def ignite(color):
    for index in range(LEDS):
        strip[index] = color
        strip.show()
        sleep(20)


def retract():
    for index in range(LEDS - 1, -1, -1):
        strip[index] = (0, 0, 0)
        strip.show()
        sleep(20)


lit = False
hue = 200
strip.clear()

while True:
    if button_a.was_pressed() and not lit:
        ignite(hue_color(hue))
        lit = True
    if button_b.was_pressed() and lit:
        retract()
        lit = False
    if lit:
        if accelerometer.was_gesture('shake'):
            fill((BRIGHTNESS, BRIGHTNESS, BRIGHTNESS))
            sleep(80)
        tilt = max(-1023, min(1023, accelerometer.get_x()))
        hue = (tilt + 1023) * 359 // 2046
        fill(hue_color(hue))
    sleep(50)
