"""Endless runner med 3 lanes, oändligt spel (man dör aldrig).
- UP/DOWN-klick byter lane ETT steg
- Röd hinder = -1 poäng (min 0), regnbågs-collectible = +1
- Topp-raden visar score 0-7. Vid 8 -> liten regnbågs-show -> reset
- Difficulty rampar långsamt upp över tid
- Håll KLICK i 2 sek -> reset hela spelet (score + difficulty)
"""
import machine, neopixel, time, random

LED_PIN = 4
JOY_UP, JOY_DOWN, JOY_LEFT, JOY_RIGHT, JOY_CLICK = 10, 9, 7, 8, 6

W = H = 8
NUM = W * H
np = neopixel.NeoPixel(machine.Pin(LED_PIN), NUM)

up_btn    = machine.Pin(JOY_UP,    machine.Pin.IN, machine.Pin.PULL_UP)
down_btn  = machine.Pin(JOY_DOWN,  machine.Pin.IN, machine.Pin.PULL_UP)
click_btn = machine.Pin(JOY_CLICK, machine.Pin.IN, machine.Pin.PULL_UP)

def xy(x, y):
    return y * W + x

def clear():
    for i in range(NUM):
        np[i] = (0, 0, 0)

def wheel(pos, peak=28):
    pos &= 255
    if pos < 85:
        return (pos * peak // 85, (85 - pos) * peak // 85, 0)
    elif pos < 170:
        pos -= 85
        return ((85 - pos) * peak // 85, 0, pos * peak // 85)
    else:
        pos -= 170
        return (0, pos * peak // 85, (85 - pos) * peak // 85)

PLAYER_X = 1
LANES = [2, 4, 6]
COLOR_PLAYER    = (16, 16, 24)
COLOR_LANE_HINT = (1, 1, 1)
COLOR_SCORE     = (0, 28, 4)
COLOR_RESET     = (16, 0, 16)

def play_show():
    """Regnbågs-show ~1,3 sek vid 8 poäng."""
    clear()
    for i in range(8):
        np[xy(i, 0)] = (0, 32, 0)
    np.write()
    time.sleep_ms(250)
    t0 = time.ticks_ms()
    f = 0
    while time.ticks_diff(time.ticks_ms(), t0) < 1300:
        for y in range(H):
            for x in range(W):
                hue = (f * 10 + x * 24 + y * 18) & 255
                np[xy(x, y)] = wheel(hue, peak=32)
        for _ in range(5):
            i = random.randint(0, NUM - 1)
            np[i] = (40, 40, 40)
        np.write()
        f += 1
        time.sleep_ms(45)

def reset_anim():
    """Lila puls + släck när klick hållits i 2 sek."""
    for _ in range(2):
        for i in range(NUM):
            np[i] = COLOR_RESET
        np.write()
        time.sleep_ms(150)
        clear()
        np.write()
        time.sleep_ms(120)

def spawn_entity():
    lane = random.randint(0, 2)
    kind = 0 if random.random() < 0.55 else 1
    return [7, lane, kind]

# --- outer loop: kör spelet, restartar vid hold-click ---
while True:
    player_lane = 1
    entities = []
    score = 0
    tick = 0
    up_prev = 1
    down_prev = 1
    click_pressed_ms = 0

    while True:
        tick += 1
        up_now = up_btn.value()
        down_now = down_btn.value()
        click_now = click_btn.value()
        up_just = (up_prev == 1 and up_now == 0)
        down_just = (down_prev == 1 and down_now == 0)
        up_prev = up_now
        down_prev = down_now

        if up_just and player_lane > 0:
            player_lane -= 1
        if down_just and player_lane < 2:
            player_lane += 1
        player_y = LANES[player_lane]

        # Klick-hold: 2 sek = restart
        now_ms = time.ticks_ms()
        if click_now == 0:  # pressed
            if click_pressed_ms == 0:
                click_pressed_ms = now_ms
            elif time.ticks_diff(now_ms, click_pressed_ms) >= 2000:
                reset_anim()
                break  # restart outer loop -> initierar allt
        else:
            click_pressed_ms = 0

        # Score-baserad difficulty:
        # 0 poäng = långsamt, fler poäng = snabbare. Tappar man röd sänks farten igen.
        # score 0 -> speed 10 (~600ms/pixel), score 7 -> speed 3 (~180ms/pixel)
        speed = max(3, 10 - score)
        spawn_chance = 0.18 + score * 0.035   # 0.18 -> 0.43

        if tick % speed == 0:
            kept = []
            for e in entities:
                e[0] -= 1
                if e[0] >= 0:
                    kept.append(e)
            entities = kept
            if random.random() < spawn_chance:
                ent = spawn_entity()
                if not any(e[0] == 7 for e in entities):
                    entities.append(ent)

        # Kollisioner
        survivors = []
        for e in entities:
            x, lane, k = e
            if x == PLAYER_X and lane == player_lane:
                if k == 0:
                    score = max(0, score - 1)
                else:
                    score += 1
                continue
            survivors.append(e)
        entities = survivors

        # Render
        clear()
        for i in range(min(score, 8)):
            np[xy(i, 0)] = COLOR_SCORE
        for y in LANES:
            np[xy(W - 1, y)] = COLOR_LANE_HINT
        for e in entities:
            x, lane, k = e
            if 0 <= x < W:
                y = LANES[lane]
                if k == 0:
                    np[xy(x, y)] = (48, 0, 0)
                else:
                    hue = (tick * 10 + x * 32 + y * 16) & 255
                    np[xy(x, y)] = wheel(hue, peak=30)
        np[xy(PLAYER_X, player_y)] = COLOR_PLAYER
        np.write()

        if score >= 8:
            play_show()
            score = 0
            entities = []

        time.sleep_ms(60)
