import board
import neopixel
import time
import random
import digitalio
from analogio import AnalogIn
from adafruit_led_animation.color import RED, BLUE, GREEN, BLACK

# --- CONFIGURATION ---
NUM_PIXELS = 30

# Speed range (in seconds)
MAX_SPEED_DELAY = 8.0
MIN_SPEED_DELAY = 0.5

MOVING_COLOR = BLUE
TARGET_COLOR = RED
WIN_COLOR = GREEN

# --- SETUP HARDWARE ---
pixels = neopixel.NeoPixel(board.A1, NUM_PIXELS, brightness=0.3, auto_write=False)

ext_button = digitalio.DigitalInOut(board.A4)
ext_button.switch_to_input(pull=digitalio.Pull.UP)

potentiometer = AnalogIn(board.A6)

# --- INITIAL SETUP ---
target_position = random.randint(0, NUM_PIXELS - 1)
moving_position = 0
direction = 1
win_count = 0  # Tracks number of wins for cycling animations

# --- FUNCTIONS ---

def get_pot_speed_delay():
    pot_value = potentiometer.value
    normalized = pot_value / 65535
    speed_delay = MAX_SPEED_DELAY - (normalized * (MAX_SPEED_DELAY - MIN_SPEED_DELAY))
    return speed_delay

def draw_strip():
    for i in range(NUM_PIXELS):
        if i == target_position and i == moving_position:
            pixels[i] = WIN_COLOR
        elif i == target_position:
            pixels[i] = TARGET_COLOR
        elif i == moving_position:
            pixels[i] = MOVING_COLOR
        else:
            pixels[i] = BLACK
    pixels.show()

# --- CELEBRATION ANIMATIONS ---

def gentle_color_wipe():
    """A smooth, soothing color wipe with pastel colors."""
    pastel_colors = [
        (255, 182, 193),  # Light Pink
        (173, 216, 230),  # Light Blue
        (144, 238, 144),  # Light Green
        (255, 255, 224),  # Light Yellow
        (221, 160, 221)   # Light Purple
    ]
    for color in pastel_colors:
        for i in range(NUM_PIXELS):
            pixels[i] = color
            pixels.show()
            time.sleep(0.03)
        time.sleep(0.5)
    pixels.fill(BLACK)
    pixels.show()

def smooth_rainbow_flow():
    """Calm smooth rainbow flowing across strip."""
    for offset in range(256):
        for i in range(NUM_PIXELS):
            pixel_index = (i * 256 // NUM_PIXELS) + offset
            pixels[i] = colorwheel(pixel_index & 255)
        pixels.show()
        time.sleep(0.02)

def moving_rainbow_chase():
    """Smooth rainbow chase effect across the strip."""
    for cycle in range(5):
        for j in range(NUM_PIXELS):
            for i in range(NUM_PIXELS):
                idx = (i * 256 // NUM_PIXELS) + (j * 5)
                pixels[i] = colorwheel(idx & 255)
            pixels.show()
            time.sleep(0.03)

def colorwheel(pos):
    """Generate rainbow colors across 0-255 positions."""
    if pos < 0 or pos > 255:
        return (0, 0, 0)
    if pos < 85:
        return (255 - pos * 3, pos * 3, 0)
    if pos < 170:
        pos -= 85
        return (0, 255 - pos * 3, pos * 3)
    pos -= 170
    return (pos * 3, 0, 255 - pos * 3)

def celebrate_win():
    """Cycle through different celebration animations."""
    global win_count
    win_choice = win_count % 3
    if win_choice == 0:
        gentle_color_wipe()
    elif win_choice == 1:
        smooth_rainbow_flow()
    elif win_choice == 2:
        moving_rainbow_chase()
    win_count += 1
    pixels.fill(BLACK)
    pixels.show()

# --- MAIN LOOP ---

print("Game started! Adjust potentiometer to control speed. Press the button when lights overlap.")

while True:
    draw_strip()

    move_delay = get_pot_speed_delay()
    elapsed = 0
    slice_time = 0.01

    while elapsed < move_delay:
        if not ext_button.value:  # External button pressed
            if moving_position == target_position:
                print("You hit the target!")
                celebrate_win()
                target_position = random.randint(0, NUM_PIXELS - 1)
                moving_position = 0
                direction = 1
                time.sleep(1)
                break
            else:
                print("Missed!")
                time.sleep(0.3)
        time.sleep(slice_time)
        elapsed += slice_time

    moving_position += direction
    if moving_position >= NUM_PIXELS:
        moving_position = NUM_PIXELS - 2
        direction = -1
    elif moving_position < 0:
        moving_position = 1
        direction = 1
