import pyxel
import random
import math

# ============================================================
# OCEAN ESCAPE - mit Sprites (Nemo & Dori) - 512x512
# ============================================================

WIDTH = 512
HEIGHT = 512

# Skalierungsfaktor gegenüber Original (200x180)
SX = 512 / 200   # ~2.56
SY = 512 / 180   # ~2.844

# ============================================================
# SPRITE-KOORDINATEN (unverändert - kommen aus res.pyxres)
# ============================================================
NEMO_X = 0
NEMO_Y = 29
NEMO_W = 25
NEMO_H = 20

DORI_X = 16
DORI_Y = 86
DORI_W = 29
DORI_H = 30

DRAGON_ORANGE_X = 39
DRAGON_ORANGE_Y = 32
DRAGON_ORANGE_W = 27
DRAGON_ORANGE_H = 26

DRAGON_FIRE_X = 85
DRAGON_FIRE_Y = 0
DRAGON_FIRE_W = 40
DRAGON_FIRE_H = 26

DRAGON_RED_X = 96
DRAGON_RED_Y = 80
DRAGON_RED_W = 27
DRAGON_RED_H = 29

COIN_X = 74
COIN_Y = 58
COIN_W = 12
COIN_H = 12

JELLY_X = 63
JELLY_Y = 96
JELLY_W = 19
JELLY_H = 26

SHARK_X = 0
SHARK_Y = 2
SHARK_W = 16
SHARK_H = 11

OCTOPUS_X = 192
OCTOPUS_Y = 8
OCTOPUS_W = 26
OCTOPUS_H = 25

# Hitbox skaliert
FISH_HITBOX = int(12 * SX)

TRANSPARENT = 14

# ---- Spielzustand ----
state = "menu"
timer = 0
level = 1
score = 0
coins = 0
high_score = 0

# ---- Spieler ----
player_x = int(20 * SX)
player_y = int(90 * SY)
player_hp = 3
player_max_hp = 3
oxygen = 100
oxygen_max = 110
invincible_timer = 0
player_facing = 1

# ---- Statistiken ----
stats_start_time = 0
stats_total_coins = 0
stats_time_played = 0

# ---- First-hit warning ----
first_hit_shown = False
warning_timer = 0
warning_text = ""

# ---- Schwierigkeit ----
difficulty = "normal"

# ---- Facing-Timer ----
facing_timer = 0

# ---- Upgrades ----
upgrade_max_hp = 0
upgrade_oxygen = 0
upgrade_speed = 0
upgrade_magnet = 0

# ---- Listen ----
obstacles = []
powerups = []
bubbles = []
coins_list = []
particles = []

# ---- Dori ----
dori_x = -int(20 * SX)
dori_y = int(90 * SY)
dori_active = False

# ---- Effekte ----
effect_shield = 0
effect_slow = 0
effect_small = 0

# ---- Strömung ----
current_active = False
current_dir_x = 0
current_dir_y = 0
current_timer = 0

# ---- Parallax ----
bg_layer1 = 0
bg_layer2 = 0

# ---- Bonus-Level ----
bonus_timer = 0

# ---- BOSS ----
boss_active = False
boss_x = 0
boss_y = 0
boss_hp = 10
boss_hp_max = 10
boss_dir_x = 0.0
boss_dir_y = 0.0
boss_timer = 0
boss_facing = -1


def reset_run():
    global player_x, player_y, player_hp, oxygen, invincible_timer
    global obstacles, powerups, bubbles, coins_list, particles
    global effect_shield, effect_slow, effect_small, timer, score
    global dori_x, dori_y, dori_active
    global current_active, current_dir_x, current_dir_y, current_timer
    global bonus_timer, player_facing
    global first_hit_shown, warning_timer, warning_text
    global boss_active, boss_x, boss_y, boss_hp, boss_timer

    player_x = int(20 * SX)
    player_y = HEIGHT // 2
    player_facing = 1

    if difficulty == "easy":
        player_hp = player_max_hp + upgrade_max_hp + 2
    elif difficulty == "hard":
        player_hp = max(1, player_max_hp + upgrade_max_hp - 1)
    else:
        player_hp = player_max_hp + upgrade_max_hp

    oxygen = oxygen_max + upgrade_oxygen * 25
    invincible_timer = 0
    obstacles = []
    powerups = []
    bubbles = []
    coins_list = []
    particles = []
    effect_shield = 0
    effect_slow = 0
    effect_small = 0
    current_active = False
    current_dir_x = 0
    current_dir_y = 0
    current_timer = 0
    bonus_timer = 0
    timer = 0
    score = 0
    dori_x = WIDTH + int(20 * SX)
    dori_y = HEIGHT // 2
    dori_active = False
    first_hit_shown = False
    warning_timer = 0
    warning_text = ""
    boss_active = False
    boss_x = WIDTH + int(50 * SX)
    boss_y = HEIGHT // 2
    boss_hp = 10
    boss_timer = 0


def full_reset():
    global level, coins
    global upgrade_max_hp, upgrade_oxygen, upgrade_speed, upgrade_magnet
    global stats_total_coins, stats_time_played

    level = 1
    coins = 0
    upgrade_max_hp = 0
    upgrade_oxygen = 0
    upgrade_speed = 0
    upgrade_magnet = 0
    stats_total_coins = 0
    stats_time_played = 0
    reset_run()


def spawn_obstacle():
    choices = ["jelly", "dragon_red", "dragon_orange"]
    if level >= 3:
        choices.append("eel")
    if level >= 4:
        choices.append("shark")

    typ = random.choice(choices)
    y = random.randint(int(15 * SY), HEIGHT - int(15 * SY))
    speed = random.uniform(0.7, 1.5 + level * 0.15) * SX

    if difficulty == "easy":
        speed *= 0.7
    elif difficulty == "hard":
        speed *= 1.25

    if typ == "jelly":
        pattern = "wave"
        speed *= random.uniform(0.6, 0.9)
    elif typ == "shark":
        pattern = "homing"
        speed *= random.uniform(1.1, 1.4)
    elif typ == "dragon_red":
        pattern = "wave"
        speed *= random.uniform(0.8, 1.0)
    elif typ == "dragon_orange":
        pattern = "zigzag"
        speed *= random.uniform(0.7, 0.9)
    elif typ == "eel":
        pattern = "zigzag"
        speed *= random.uniform(1.0, 1.3)
    else:
        pattern = "straight"

    obstacles.append([float(WIDTH), float(y), speed, typ, pattern, 0.0, 0, False])


def spawn_powerup():
    typ = random.choice(["shield", "slow", "heal"])
    y = random.randint(int(15 * SY), HEIGHT - int(15 * SY))
    powerups.append([float(WIDTH), float(y), typ])


def spawn_bubble():
    x = random.randint(int(20 * SX), WIDTH - int(20 * SX))
    bubbles.append([float(x), float(HEIGHT + 5)])


def spawn_coin():
    y = random.randint(int(15 * SY), HEIGHT - int(15 * SY))
    coins_list.append([float(WIDTH), float(y)])


def add_particles(x, y, count, color):
    for _ in range(count):
        vx = random.uniform(-1.5, 1.5) * SX
        vy = random.uniform(-1.5, 1.5) * SY
        life = random.randint(15, 30)
        particles.append([x, y, vx, vy, life, color])


def update():
    global state, timer, level, score, coins, high_score
    global player_x, player_y, player_hp, oxygen, invincible_timer
    global player_facing, first_hit_shown, warning_timer, warning_text
    global facing_timer
    global stats_time_played, stats_total_coins, difficulty
    global effect_shield, effect_slow, effect_small
    global bg_layer1, bg_layer2
    global dori_x, dori_y, dori_active
    global current_active, current_dir_x, current_dir_y, current_timer
    global bonus_timer
    global coins_list, particles
    global boss_active, boss_x, boss_y, boss_hp, boss_timer, boss_facing

    timer += 1

    bg_layer1 = (bg_layer1 - 0.3 * SX) % WIDTH
    bg_layer2 = (bg_layer2 - 0.6 * SX) % WIDTH

    if state == "menu":
        if pyxel.btnp(pyxel.MOUSE_BUTTON_LEFT):
            mx, my = pyxel.mouse_x, pyxel.mouse_y
            # Button skaliert: x 179-333, y 120-171
            btn_x, btn_y = int(70 * SX), int(42 * SY)
            btn_w, btn_h = int(60 * SX), int(18 * SY)
            if btn_x < mx < btn_x + btn_w and btn_y < my < btn_y + btn_h:
                full_reset()
                pyxel.play(3, 41)
                state = "play"
                pyxel.playm(1, loop=True)

    elif state == "play":
        move_speed = (2 + upgrade_speed * 0.5) * SX
        if pyxel.btn(pyxel.KEY_UP) or pyxel.btn(pyxel.KEY_W):
            player_y -= move_speed
        if pyxel.btn(pyxel.KEY_DOWN) or pyxel.btn(pyxel.KEY_S):
            player_y += move_speed
        if pyxel.btn(pyxel.KEY_LEFT) or pyxel.btn(pyxel.KEY_A):
            player_x -= move_speed
            player_facing = -1
            facing_timer = 15
        if pyxel.btn(pyxel.KEY_RIGHT) or pyxel.btn(pyxel.KEY_D):
            player_x += move_speed
            player_facing = 1
            facing_timer = 0

        if facing_timer > 0:
            facing_timer -= 1
            if facing_timer == 0:
                player_facing = 1

        if level >= 5 and boss_active:
            if not current_active:
                if random.randint(0, 300) == 0:
                    current_active = True
                    current_timer = random.randint(90, 150)
                    dirs = [(-1, 0), (1, 0), (0, -1), (0, 1)]
                    current_dir_x, current_dir_y = random.choice(dirs)
            else:
                current_timer -= 1
                player_x += current_dir_x * 0.6 * SX
                player_y += current_dir_y * 0.6 * SY
                if current_timer <= 0:
                    current_active = False

        player_x = max(FISH_HITBOX, min(WIDTH - FISH_HITBOX, player_x))
        player_y = max(FISH_HITBOX, min(HEIGHT - FISH_HITBOX, player_y))

        if timer % 60 == 0:
            stats_time_played += 1

        if difficulty == "easy":
            oxygen -= 0.08
        elif difficulty == "hard":
            oxygen -= 0.18
        else:
            oxygen -= 0.12
        if oxygen <= 0:
            player_hp -= 1
            oxygen = 30
            add_particles(player_x, player_y, 8, 12)
            if player_hp <= 0:
                if score > high_score:
                    high_score = score
                state = "gameover"

        if effect_shield > 0:
            effect_shield -= 1
        if effect_slow > 0:
            effect_slow -= 1
        if effect_small > 0:
            effect_small -= 1
        if invincible_timer > 0:
            invincible_timer -= 1
        if warning_timer > 0:
            warning_timer -= 1

        level_duration = 900 + level * 120
        dori_appear_time = level_duration - 200

        if level == 5:
            if timer >= dori_appear_time and not boss_active and not dori_active:
                boss_active = True
                boss_x = WIDTH + int(20 * SX)
                boss_y = HEIGHT // 2
                boss_hp = boss_hp_max
                boss_timer = 0
                warning_text = "BOSS KOMMT!"
                warning_timer = 120
        else:
            if timer >= dori_appear_time and not dori_active:
                dori_active = True
                dori_x = WIDTH + int(10 * SX)
                dori_y = random.randint(int(30 * SY), HEIGHT - int(30 * SY))

        if dori_active:
            dori_x -= 1.0 * SX
            dori_y += math.sin(timer * 0.05) * 0.5 * SY
            if dori_x < int(30 * SX):
                dori_x = int(30 * SX)

        if boss_active:
            boss_timer += 1
            if boss_x > WIDTH - int(50 * SX):
                boss_x -= 0.8 * SX
            else:
                if boss_y < player_y:
                    boss_y += 1.0 * SY
                elif boss_y > player_y:
                    boss_y -= 1.0 * SY
                boss_x += math.sin(boss_timer * 0.05) * 2.0 * SX

                if boss_timer % 90 == 0:
                    for i in range(3):
                        angle_offset = (i - 1) * 0.3
                        dx_to_player = player_x - boss_x
                        dy_to_player = player_y - boss_y
                        dist = math.sqrt(dx_to_player ** 2 + dy_to_player ** 2)
                        if dist > 0:
                            vx = (dx_to_player / dist) * 2.0 * SX
                            vy = (dy_to_player / dist) * 2.0 * SY
                            vx_rot = vx * math.cos(angle_offset) - vy * math.sin(angle_offset)
                            vy_rot = vx * math.sin(angle_offset) + vy * math.cos(angle_offset)
                            obstacles.append([
                                float(boss_x), float(boss_y),
                                0, "ink", "projectile", 0.0,
                                vx_rot, vy_rot
                            ])
                    pyxel.play(3, 38)

            boss_y = max(int(20 * SY), min(HEIGHT - int(20 * SY), boss_y))

            if abs(boss_x - player_x) < int(16 * SX) and abs(boss_y - player_y) < int(16 * SY):
                if effect_shield > 0:
                    effect_shield = 0
                    boss_hp -= 2
                    add_particles(player_x, player_y, 20, 11)
                    pyxel.play(3, 33)
                elif invincible_timer <= 0:
                    player_hp -= 1
                    invincible_timer = 60
                    add_particles(player_x, player_y, 15, 8)
                    pyxel.play(3, 32)
                    if player_hp <= 0:
                        if score > high_score:
                            high_score = score
                        pyxel.play(3, 36)
                        state = "gameover"

            if boss_timer > 720:
                boss_active = False
                score += 500
                stats_total_coins += 10
                coins += 10
                add_particles(boss_x, boss_y, 30, 10)
                add_particles(boss_x, boss_y, 20, 8)
                obstacles[:] = [o for o in obstacles if o[3] != "ink"]
                if score > high_score:
                    high_score = score
                pyxel.play(3, 35)
                state = "win"

        if not dori_active and not boss_active:
            spawn_chance = 1.5 + level * 0.5
            if difficulty == "easy":
                spawn_chance *= 0.7
            elif difficulty == "hard":
                spawn_chance *= 1.3
            if random.randint(0, 100) < spawn_chance:
                spawn_obstacle()

            if random.randint(0, 180) == 0:
                spawn_powerup()

            if level == 1:
                bubble_rate = 40
            elif level <= 3:
                bubble_rate = 70
            else:
                bubble_rate = 100
            if timer % bubble_rate == 0 or random.randint(0, 200) == 0:
                spawn_bubble()

            if random.randint(0, 70) == 0:
                spawn_coin()

        speed_mod = 0.4 if effect_slow > 0 else 1.0

        for o in obstacles:
            o[5] += 0.1

            if o[3] == "dragon_orange" and level >= 3:
                o[6] += 1
                if o[7]:
                    if o[6] > random.randint(20, 40):
                        o[7] = False
                        o[6] = 0
                else:
                    if o[6] > random.randint(40, 90):
                        o[7] = True
                        o[6] = 0

            if o[4] == "wave":
                o[0] -= o[2] * speed_mod
                if o[3] == "dragon_red":
                    o[1] += math.sin(o[5] * 0.6) * 2.0 * SY
                else:
                    o[1] += math.sin(o[5]) * 1.5 * SY
            elif o[4] == "homing":
                if o[1] < player_y:
                    o[1] += 0.5 * SY * speed_mod
                elif o[1] > player_y:
                    o[1] -= 0.5 * SY * speed_mod
                o[0] -= o[2] * speed_mod
            elif o[4] == "zigzag":
                o[0] -= o[2] * speed_mod
                o[1] += math.sin(o[5] * 2) * 2 * SY
            elif o[4] == "projectile":
                o[0] += o[6] * speed_mod
                o[1] += o[7] * speed_mod
            else:
                o[0] -= o[2] * speed_mod

        for o in obstacles:
            if o[3] != "ink":
                o[1] = max(int(10 * SY), min(HEIGHT - int(10 * SY), o[1]))

        obstacles[:] = [o for o in obstacles
                        if (o[3] == "ink" and -10 < o[0] < WIDTH + 10 and -10 < o[1] < HEIGHT + 10)
                        or (o[3] != "ink" and o[0] > int(-15 * SX))]

        for p in powerups:
            p[0] -= 1.2 * SX * speed_mod
        powerups[:] = [p for p in powerups if p[0] > -10]

        for b in bubbles:
            b[1] -= 1.2 * SY * speed_mod
            b[0] += math.sin(b[1] * 0.05) * 0.3 * SX
        bubbles[:] = [b for b in bubbles if b[1] > -10]

        for c in coins_list:
            c[0] -= 1.0 * SX * speed_mod
            if upgrade_magnet > 0:
                dx = player_x - c[0]
                dy = player_y - c[1]
                dist = math.sqrt(dx * dx + dy * dy)
                magnet_range = (20 + upgrade_magnet * 15) * SX
                if dist < magnet_range and dist > 0:
                    c[0] += (dx / dist) * 1.5 * SX
                    c[1] += (dy / dist) * 1.5 * SY
        coins_list[:] = [c for c in coins_list if c[0] > -10]

        for p in particles:
            p[0] += p[2]
            p[1] += p[3]
            p[4] -= 1
        particles[:] = [p for p in particles if p[4] > 0]

        hitbox = FISH_HITBOX
        for o in obstacles[:]:
            check_hitbox = hitbox
            if o[3] in ("dragon_red", "dragon_orange"):
                check_hitbox = hitbox + int(4 * SX)
            elif o[3] == "jelly":
                check_hitbox = hitbox + int(2 * SX)
            elif o[3] == "ink":
                check_hitbox = int(6 * SX)

            if abs(o[0] - player_x) < check_hitbox and abs(o[1] - player_y) < check_hitbox:
                if effect_shield > 0:
                    effect_shield = 0
                    add_particles(o[0], o[1], 12, 7)
                    pyxel.play(3, 33)
                    obstacles.remove(o)
                elif invincible_timer <= 0:
                    damage = 1
                    if o[3] == "dragon_orange" and o[7]:
                        damage = 2
                        add_particles(player_x, player_y, 15, 9)
                        pyxel.play(3, 38)
                    player_hp -= damage
                    invincible_timer = 60
                    add_particles(player_x, player_y, 10, 8)
                    pyxel.play(3, 32)
                    obstacles.remove(o)

                    if not first_hit_shown and player_hp > 0:
                        first_hit_shown = True
                        warning_text = f"ACHTUNG! Noch {player_hp} HP!"
                        warning_timer = 120

                    if player_hp <= 0:
                        if score > high_score:
                            high_score = score
                        pyxel.play(3, 36)
                        state = "gameover"

        for p in powerups[:]:
            if abs(p[0] - player_x) < int(8 * SX) and abs(p[1] - player_y) < int(8 * SY):
                if p[2] == "shield":
                    effect_shield = 300
                    pyxel.play(3, 33)
                elif p[2] == "slow":
                    effect_slow = 240
                    pyxel.play(3, 33)
                elif p[2] == "heal":
                    max_hp = player_max_hp + upgrade_max_hp
                    if player_hp < max_hp:
                        player_hp += 1
                    add_particles(p[0], p[1], 12, 8)
                    pyxel.play(3, 34)
                add_particles(p[0], p[1], 8, 11)
                powerups.remove(p)

        for b in bubbles[:]:
            if abs(b[0] - player_x) < int(7 * SX) and abs(b[1] - player_y) < int(7 * SY):
                oxygen = min(oxygen_max + upgrade_oxygen * 25, oxygen + 30)
                add_particles(b[0], b[1], 5, 12)
                pyxel.play(3, 31)
                bubbles.remove(b)

        for c in coins_list[:]:
            if abs(c[0] - player_x) < int(10 * SX) and abs(c[1] - player_y) < int(10 * SY):
                coins += 1
                stats_total_coins += 1
                score += 10
                add_particles(c[0], c[1], 4, 10)
                pyxel.play(3, 30)
                coins_list.remove(c)

        if dori_active:
            dori_cx = dori_x + DORI_W // 2
            dori_cy = dori_y + DORI_H // 2
            if abs(dori_cx - player_x) < FISH_HITBOX + int(4 * SX) and abs(dori_cy - player_y) < FISH_HITBOX + int(4 * SY):
                score += 100
                add_particles(dori_cx, dori_cy, 20, 12)
                add_particles(dori_cx, dori_cy, 15, 10)
                if score > high_score:
                    high_score = score
                pyxel.play(3, 35)
                state = "win"

        if timer % 10 == 0:
            score += 1

    elif state == "win":
        if pyxel.btnp(pyxel.KEY_SPACE):
            level += 1
            reset_run()
            if (level - 1) % 2 == 0 and level > 1:
                state = "bonus"
                pyxel.play(3, 42)
                pyxel.playm(1, loop=True)
            else:
                state = "play"
                pyxel.playm(1, loop=True)
        elif pyxel.btnp(pyxel.KEY_S):
            state = "shop"

    elif state == "bonus":
        move_speed = (2 + upgrade_speed * 0.5) * SX
        if pyxel.btn(pyxel.KEY_UP) or pyxel.btn(pyxel.KEY_W):
            player_y -= move_speed
        if pyxel.btn(pyxel.KEY_DOWN) or pyxel.btn(pyxel.KEY_S):
            player_y += move_speed
        if pyxel.btn(pyxel.KEY_LEFT) or pyxel.btn(pyxel.KEY_A):
            player_x -= move_speed
        if pyxel.btn(pyxel.KEY_RIGHT) or pyxel.btn(pyxel.KEY_D):
            player_x += move_speed
        player_x = max(FISH_HITBOX, min(WIDTH - FISH_HITBOX, player_x))
        player_y = max(FISH_HITBOX, min(HEIGHT - FISH_HITBOX, player_y))

        bonus_timer += 1

        if bonus_timer % 8 == 0:
            x = random.randint(int(10 * SX), WIDTH - int(10 * SX))
            coins_list.append([float(x), float(-5)])

        for c in coins_list:
            c[1] += 1.5 * SY
            if upgrade_magnet > 0:
                dx = player_x - c[0]
                dy = player_y - c[1]
                dist = math.sqrt(dx * dx + dy * dy)
                magnet_range = (30 + upgrade_magnet * 15) * SX
                if dist < magnet_range and dist > 0:
                    c[0] += (dx / dist) * 2 * SX
                    c[1] += (dy / dist) * 2 * SY
        coins_list[:] = [c for c in coins_list if c[1] < HEIGHT + 10]

        for c in coins_list[:]:
            if abs(c[0] - player_x) < int(10 * SX) and abs(c[1] - player_y) < int(10 * SY):
                coins += 1
                stats_total_coins += 1
                score += 20
                add_particles(c[0], c[1], 4, 10)
                pyxel.play(3, 30)
                coins_list.remove(c)

        for p in particles:
            p[0] += p[2]
            p[1] += p[3]
            p[4] -= 1
        particles[:] = [p for p in particles if p[4] > 0]

        if bonus_timer > 480:
            coins_list = []
            particles = []
            bonus_timer = 0
            state = "play"
            reset_run()
            pyxel.playm(1, loop=True)

    elif state == "shop":
        if pyxel.btnp(pyxel.MOUSE_BUTTON_LEFT):
            mx, my = pyxel.mouse_x, pyxel.mouse_y
            # Shop-Bereiche skaliert
            left = int(20 * SX)
            right = int(180 * SX)
            if left < mx < right:
                if int(40 * SY) < my < int(55 * SY) and coins >= 5 and upgrade_max_hp < 5:
                    coins -= 5
                    globals()['upgrade_max_hp'] = upgrade_max_hp + 1
                    pyxel.play(3, 40)
                elif int(60 * SY) < my < int(75 * SY) and coins >= 5 and upgrade_oxygen < 5:
                    coins -= 5
                    globals()['upgrade_oxygen'] = upgrade_oxygen + 1
                    pyxel.play(3, 40)
                elif int(80 * SY) < my < int(95 * SY) and coins >= 8 and upgrade_speed < 5:
                    coins -= 8
                    globals()['upgrade_speed'] = upgrade_speed + 1
                    pyxel.play(3, 40)
                elif int(100 * SY) < my < int(115 * SY) and coins >= 10 and upgrade_magnet < 3:
                    coins -= 10
                    globals()['upgrade_magnet'] = upgrade_magnet + 1
                    pyxel.play(3, 40)
            if int(70 * SX) < mx < int(130 * SX) and int(150 * SY) < my < int(165 * SY):
                pyxel.play(3, 41)
                state = "win"

    elif state == "gameover":
        if pyxel.btnp(pyxel.KEY_SPACE):
            state = "menu"
            pyxel.playm(0, loop=True)


def draw_background():
    pyxel.cls(1)
    for i in range(8):
        bx = (i * int(28 * SX) + int(10 * SX)) % WIDTH
        by = int(HEIGHT - (timer * 0.5 * SY + i * int(35 * SY)) % (HEIGHT + 20))
        pyxel.pset(int(bx), int(by), 5)


def draw_player():
    if invincible_timer > 0 and invincible_timer % 10 < 3:
        return

    px = int(player_x) - NEMO_W // 2
    py = int(player_y) - NEMO_H // 2
    if player_facing == -1:
        pyxel.blt(px, py, 0, NEMO_X, NEMO_Y, -NEMO_W, NEMO_H, TRANSPARENT)
    else:
        pyxel.blt(px, py, 0, NEMO_X, NEMO_Y, NEMO_W, NEMO_H, TRANSPARENT)

    if effect_shield > 0:
        r = int(20 * SX)
        pyxel.circb(int(player_x), int(player_y), r, 11)
        pyxel.circb(int(player_x), int(player_y), r + 1, 12)


def draw_dori():
    if not dori_active:
        return
    pyxel.blt(int(dori_x), int(dori_y), 0, DORI_X, DORI_Y, DORI_W, DORI_H, TRANSPARENT)
    if timer % 20 < 10:
        pyxel.circb(int(dori_x) + DORI_W // 2, int(dori_y) + DORI_H // 2, int(20 * SX), 10)


def draw_boss():
    if not boss_active:
        return

    bx = int(boss_x) - OCTOPUS_W // 2
    by = int(boss_y) - OCTOPUS_H // 2

    pyxel.blt(bx, by, 0, OCTOPUS_X, OCTOPUS_Y, -OCTOPUS_W, OCTOPUS_H, TRANSPARENT)

    hp_ratio = boss_hp / boss_hp_max if boss_hp_max > 0 else 0
    bar_w = int(30 * SX)
    pyxel.rect(bx - 2, by - int(6 * SY), bar_w, 3, 0)
    pyxel.rect(bx - 2, by - int(6 * SY), int(bar_w * hp_ratio), 3, 8)
    pyxel.text(bx + 2, by - int(14 * SY), "BOSS", 8)


def draw_obstacle(o):
    x, y, _, typ, _, phase, _, fire_on = o
    x, y = int(x), int(y)

    if typ == "dragon_red":
        pyxel.blt(x - DRAGON_RED_W // 2, y - DRAGON_RED_H // 2,
                  0, DRAGON_RED_X, DRAGON_RED_Y,
                  DRAGON_RED_W, DRAGON_RED_H, TRANSPARENT)
    elif typ == "dragon_orange":
        if fire_on:
            pyxel.blt(x - DRAGON_FIRE_W // 2, y - DRAGON_FIRE_H // 2,
                      0, DRAGON_FIRE_X, DRAGON_FIRE_Y,
                      DRAGON_FIRE_W, DRAGON_FIRE_H, TRANSPARENT)
        else:
            pyxel.blt(x - DRAGON_ORANGE_W // 2, y - DRAGON_ORANGE_H // 2,
                      0, DRAGON_ORANGE_X, DRAGON_ORANGE_Y,
                      DRAGON_ORANGE_W, DRAGON_ORANGE_H, TRANSPARENT)
    elif typ == "jelly":
        pyxel.blt(x - JELLY_W // 2, y - JELLY_H // 2,
                  0, JELLY_X, JELLY_Y, JELLY_W, JELLY_H, TRANSPARENT)
    elif typ == "shark":
        pyxel.blt(x - SHARK_W // 2, y - SHARK_H // 2,
                  0, SHARK_X, SHARK_Y, SHARK_W, SHARK_H, TRANSPARENT)
    elif typ == "ink":
        r = int(3 * SX)
        pyxel.circ(x, y, r, 2)
        pyxel.circ(x, y, max(1, r - 1), 14)
        if timer % 4 < 2:
            pyxel.pset(x - 1, y - 1, 7)
        pyxel.pset(x + int(2 * SX), y, 2)
        pyxel.pset(x + int(3 * SX), y - 1, 2)
    elif typ == "eel":
        seg_count = 5
        seg_step = int(5 * SX)
        for i in range(seg_count):
            seg_x = x - int(10 * SX) + i * seg_step
            seg_y = y + int(math.sin(phase * 3 + i * 0.5) * 2 * SY)
            r = max(1, int(2 * SX))
            pyxel.circ(seg_x, seg_y, r, 11)
            pyxel.circb(seg_x, seg_y, r, 9)
        head_x = x + int(10 * SX)
        pyxel.circ(head_x, y, int(3 * SX), 10)
        pyxel.pset(head_x + 1, y - 1, 0)
        if timer % 10 < 3:
            for _ in range(3):
                bx2 = x + random.randint(int(-12 * SX), int(12 * SX))
                by2 = y + random.randint(int(-6 * SY), int(6 * SY))
                pyxel.pset(bx2, by2, 10)
                pyxel.pset(bx2 + 1, by2, 7)


def draw_hud():
    # HP-Herzen - skaliert
    heart_size = int(9 * SX)
    for i in range(player_hp):
        hx = int(4 * SX) + i * heart_size
        hy = int(4 * SY)
        s = max(1, int(SX))
        # Vereinfachtes Herz in Skalierung
        for dx, dy in [(1,0),(2,0),(4,0),(5,0),
                       (0,1),(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),
                       (1,2),(2,2),(3,2),(4,2),(5,2),
                       (2,3),(3,3),(4,3),(3,4)]:
            pyxel.rect(hx + dx * s, hy + dy * s, s, s, 8)

    bar_x = int(4 * SX)
    bar_y = int(12 * SY)
    bar_w = int(50 * SX)
    bar_h = int(4 * SY)
    pyxel.rect(bar_x, bar_y, bar_w, bar_h, 0)
    o2_width = int((oxygen / (oxygen_max + upgrade_oxygen * 25)) * bar_w)
    o2_color = 12 if oxygen > 30 else 8
    pyxel.rect(bar_x, bar_y, o2_width, bar_h, o2_color)
    pyxel.text(bar_x + bar_w + int(4 * SX), bar_y, "O2", 7)

    pyxel.text(WIDTH - int(60 * SX), int(4 * SY), f"SCORE {score}", 7)
    pyxel.text(WIDTH - int(60 * SX), int(12 * SY), f"LEVEL {level}", 7)

    pyxel.circ(WIDTH - int(70 * SX), int(22 * SY), int(2 * SX), 10)
    pyxel.text(WIDTH - int(65 * SX), int(20 * SY), f"{coins}", 7)

    if dori_active:
        pyxel.text(WIDTH // 2 - int(44 * SX), int(25 * SY), "DORI GEFUNDEN! FANG SIE!", 10)

    if boss_active:
        survive_frames = max(0, 720 - boss_timer)
        survive_sec = survive_frames // 60 + 1
        if timer % 20 < 10:
            pyxel.text(WIDTH // 2 - int(40 * SX), int(25 * SY), f"UEBERLEBE: {survive_sec}s", 8)
        else:
            pyxel.text(WIDTH // 2 - int(40 * SX), int(25 * SY), f"UEBERLEBE: {survive_sec}s", 10)

    if warning_timer > 0:
        w = int(100 * SX)
        h = int(12 * SY)
        pyxel.rect(WIDTH // 2 - w // 2, int(45 * SY), w, h, 8)
        pyxel.text(WIDTH // 2 - len(warning_text) * 2, int(49 * SY), warning_text, 7)

    if current_active:
        if timer % 10 < 5:
            pyxel.text(WIDTH // 2 - int(30 * SX), int(35 * SY), "STROEMUNG!", 8)
        for _ in range(5):
            px2 = WIDTH // 2 + random.randint(-WIDTH // 2, WIDTH // 2)
            py2 = HEIGHT // 2 + random.randint(-HEIGHT // 2, HEIGHT // 2)
            pyxel.line(px2, py2,
                       int(px2 + current_dir_x * 3 * SX),
                       int(py2 + current_dir_y * 3 * SY), 12)

    fx = int(4 * SX)
    if effect_shield > 0:
        pyxel.text(fx, HEIGHT - int(10 * SY), "SHIELD", 11)
        fx += int(40 * SX)
    if effect_slow > 0:
        pyxel.text(fx, HEIGHT - int(10 * SY), "SLOW", 12)


def draw():
    if state == "menu":
        draw_background()

        nemo_float = math.sin(timer * 0.05) * 3 * SY
        dori_float = math.sin(timer * 0.05 + 1.5) * 3 * SY
        pyxel.blt(int(5 * SX), int(40 * SY) + int(nemo_float),
                  0, NEMO_X, NEMO_Y, NEMO_W, NEMO_H, TRANSPARENT)
        pyxel.blt(WIDTH - DORI_W - int(5 * SX), int(35 * SY) + int(dori_float),
                  0, DORI_X, DORI_Y, DORI_W, DORI_H, TRANSPARENT)

        title = "CRAZY OCEAN"
        title_x = WIDTH // 2 - len(title) * 2 - 2
        pyxel.text(title_x + 1, int(16 * SY), title, 1)
        colors = [8, 9, 10, 11, 12, 14, 8, 9, 10, 11, 12]
        for i, ch in enumerate(title):
            c = colors[(i + timer // 8) % len(colors)]
            pyxel.text(title_x + i * 4, int(15 * SY), ch, c)

        pyxel.text(WIDTH // 2 - 34, int(26 * SY), "Finde Dori, rette sie!", 7)

        btn_x = int(70 * SX)
        btn_y = int(42 * SY)
        btn_w = int(60 * SX)
        btn_h = int(18 * SY)
        hover = btn_x < pyxel.mouse_x < btn_x + btn_w and btn_y < pyxel.mouse_y < btn_y + btn_h

        pyxel.rect(btn_x + 2, btn_y + 2, btn_w, btn_h, 0)
        pyxel.rect(btn_x, btn_y, btn_w, btn_h, 11 if hover else 3)
        pyxel.rectb(btn_x, btn_y, btn_w, btn_h, 7)
        pulse = int(math.sin(timer * 0.1) * 1)
        pyxel.text(btn_x + int(22 * SX) + pulse, btn_y + int(6 * SY), "PLAY", 7)
        pyxel.tri(btn_x + int(14 * SX), btn_y + int(6 * SY),
                  btn_x + int(14 * SX), btn_y + int(12 * SY),
                  btn_x + int(18 * SX), btn_y + int(9 * SY), 7)

        info_y = int(70 * SY)
        info_w = WIDTH - int(20 * SX)
        info_h = int(85 * SY)
        pyxel.rectb(int(10 * SX), info_y, info_w, info_h, 5)
        pyxel.rect(int(11 * SX), info_y + 1, info_w - int(2 * SX), info_h - 2, 1)

        pyxel.text(WIDTH // 2 - 20, info_y + int(3 * SY), "SO GEHT'S:", 10)

        y = info_y + int(13 * SY)
        pyxel.text(int(15 * SX), y, "STEUERUNG:", 11)
        pyxel.text(int(15 * SX), y + int(7 * SY), "Pfeiltasten oder WASD", 7)

        y = info_y + int(28 * SY)
        pyxel.text(int(15 * SX), y, "ZIEL:", 11)
        pyxel.text(int(15 * SX), y + int(7 * SY), "Weiche Hindernissen aus,", 7)
        pyxel.text(int(15 * SX), y + int(14 * SY), "sammle Coins & finde Dori!", 7)

        y = info_y + int(52 * SY)
        pyxel.text(int(15 * SX), y, "SAMMLE:", 11)
        pyxel.circ(int(18 * SX), int(y + 11 * SY), int(2 * SX), 10)
        pyxel.text(int(22 * SX), int(y + 9 * SY), "Coin", 7)
        pyxel.circb(int(50 * SX), int(y + 11 * SY), int(2 * SX), 12)
        pyxel.text(int(54 * SX), int(y + 9 * SY), "O2", 7)
        pyxel.text(int(78 * SX), int(y + 9 * SY), "HP", 7)
        pyxel.rect(int(95 * SX), int(y + 9 * SY), int(4 * SX), int(4 * SY), 12)
        pyxel.text(int(101 * SX), int(y + 9 * SY), "Power-Ups", 7)

        y = info_y + int(67 * SY)
        pyxel.text(int(15 * SX), y, "NACH JEDEM LEVEL: SHOP oeffnen [S]", 10)
        pyxel.text(int(15 * SX), y + int(7 * SY), "Kaufe Upgrades mit deinen Coins!", 7)

        if high_score > 0:
            pyxel.text(WIDTH // 2 - int(30 * SX), HEIGHT - int(10 * SY), f"HIGH SCORE: {high_score}", 10)
        else:
            pyxel.text(WIDTH // 2 - int(42 * SX), HEIGHT - int(10 * SY), "Mach den ersten Highscore!", 6)

    elif state == "play":
        draw_background()

        for b in bubbles:
            bx, by = int(b[0]), int(b[1])
            r = int(3 * SX)
            pyxel.circb(bx, by, r, 12)
            pyxel.circ(bx, by, max(1, r - 1), 1)
            pyxel.pset(bx - 1, by - 1, 7)
            pyxel.pset(bx, by - 2, 7)

        for c in coins_list:
            cx, cy = int(c[0]), int(c[1])
            pyxel.blt(cx - COIN_W // 2, cy - COIN_H // 2,
                      0, COIN_X, COIN_Y, COIN_W, COIN_H, TRANSPARENT)

        for p in powerups:
            x, y, typ = int(p[0]), int(p[1]), p[2]
            s = max(1, int(SX))

            if typ == "shield":
                pw = int(9 * SX)
                ph = int(10 * SY)
                pyxel.rect(x - pw // 2 - 1, y - ph // 2 - 1, pw + 2, ph + 2, 5)
                pyxel.rect(x - pw // 2, y - ph // 2, pw, ph, 12)
                pyxel.line(x, y - ph // 2, x, y + ph // 2, 7)
                pyxel.line(x - pw // 2, y, x + pw // 2, y, 7)

            elif typ == "slow":
                r = int(6 * SX)
                pyxel.circ(x, y, r, 1)
                pyxel.line(x - r, y - r, x + r, y - r, 10)
                pyxel.line(x - r, y + r, x + r, y + r, 10)
                pyxel.tri(x - r, y - r + 1, x + r, y - r + 1, x, y, 7)
                pyxel.tri(x - r, y + r - 1, x + r, y + r - 1, x, y, 7)

            elif typ == "heal":
                r = int(6 * SX)
                pyxel.circ(x, y, r, 2)
                hw = int(4 * SX)
                hh = int(4 * SY)
                pyxel.rect(x - 1, y - hh, 3, hh * 2 + 1, 8)
                pyxel.rect(x - hw, y - 1, hw * 2 + 1, 3, 8)

        for o in obstacles:
            draw_obstacle(o)

        for p in particles:
            pyxel.pset(int(p[0]), int(p[1]), int(p[5]))

        draw_dori()
        draw_boss()
        draw_player()
        draw_hud()

    elif state == "win":
        draw_background()
        cx = WIDTH // 2
        cy = HEIGHT // 2
        pyxel.blt(cx - 40, cy - 20, 0, NEMO_X, NEMO_Y, NEMO_W, NEMO_H, TRANSPARENT)
        pyxel.blt(cx + 10, cy - 20, 0, DORI_X, DORI_Y, DORI_W, DORI_H, TRANSPARENT)

        pyxel.text(WIDTH // 2 - int(40 * SX), int(35 * SY), f"LEVEL {level} GESCHAFFT!", 11)
        pyxel.text(WIDTH // 2 - int(50 * SX), int(85 * SY), "Dori ist gerettet!", 7)
        pyxel.text(WIDTH // 2 - int(60 * SX), int(100 * SY), f"Score: {score}", 7)
        pyxel.text(WIDTH // 2 - int(60 * SX), int(110 * SY), f"Coins: {coins}", 10)
        pyxel.text(WIDTH // 2 - int(60 * SX), int(130 * SY), "SPACE: Naechstes Level", 7)
        pyxel.text(WIDTH // 2 - int(60 * SX), int(140 * SY), "S: Shop besuchen", 10)

    elif state == "bonus":
        pyxel.cls(12)

        for i in range(20):
            gx = (i * 13 + bonus_timer * 2) % WIDTH
            gy = (i * 17 + bonus_timer) % HEIGHT
            if (bonus_timer + i) % 8 < 4:
                pyxel.pset(int(gx), int(gy), 10)
            else:
                pyxel.pset(int(gx), int(gy), 9)

        for c in coins_list:
            cx2, cy2 = int(c[0]), int(c[1])
            pyxel.blt(cx2 - COIN_W // 2, cy2 - COIN_H // 2,
                      0, COIN_X, COIN_Y, COIN_W, COIN_H, TRANSPARENT)

        draw_player()

        for p in particles:
            pyxel.pset(int(p[0]), int(p[1]), int(p[5]))

        if bonus_timer % 30 < 20:
            pyxel.text(WIDTH // 2 - int(30 * SX), int(10 * SY), "*** BONUS ***", 10)
        pyxel.text(WIDTH // 2 - int(42 * SX), int(20 * SY), "MUENZEN-REGEN!", 7)

        remaining = max(0, 480 - bonus_timer)
        bar_width = int((remaining / 480) * (WIDTH - int(20 * SX)))
        pyxel.rect(int(10 * SX), HEIGHT - int(8 * SY), WIDTH - int(20 * SX), int(4 * SY), 1)
        pyxel.rect(int(10 * SX), HEIGHT - int(8 * SY), bar_width, int(4 * SY), 10)

        pyxel.circ(int(12 * SX), int(6 * SY), int(3 * SX), 10)
        pyxel.text(int(18 * SX), int(4 * SY), f"COINS: {coins}", 7)

    elif state == "shop":
        pyxel.cls(1)
        pyxel.text(WIDTH // 2 - 8, int(8 * SY), "SHOP", 10)

        pyxel.circ(WIDTH // 2 - int(12 * SX), int(20 * SY), int(3 * SX), 10)
        pyxel.text(WIDTH // 2 - int(5 * SX), int(18 * SY), f"{coins} Coins", 7)

        items = [
            (int(40 * SY), "MAX HP",  "+1 Herz mehr Leben",       upgrade_max_hp,   5,  5),
            (int(60 * SY), "OXYGEN",  "+25 Sauerstoff Reserve",   upgrade_oxygen,   5,  5),
            (int(80 * SY), "SPEED",   "Nemo schwimmt schneller",  upgrade_speed,    5,  8),
            (int(100 * SY), "MAGNET", "Zieht Coins automatisch",  upgrade_magnet,   3,  10),
        ]

        hovered_info = None
        item_h = int(15 * SY)

        for y, name, desc, lvl, max_lvl, cost in items:
            hover = int(20 * SX) < pyxel.mouse_x < int(180 * SX) and y < pyxel.mouse_y < y + item_h
            is_max = lvl >= max_lvl
            can_afford = coins >= cost and not is_max

            if is_max:
                color = 3
            elif hover and can_afford:
                color = 11
                hovered_info = desc
            elif can_afford:
                color = 5
            else:
                color = 2

            pyxel.rect(int(20 * SX), y, int(160 * SX), item_h, color)

            if is_max:
                text = f"{name}  [MAX Lvl {lvl}/{max_lvl}]"
            else:
                text = f"{name}  [Lvl {lvl}/{max_lvl}]  {cost}c"
            pyxel.text(int(28 * SX), y + int(5 * SY), text, 7)

        desc_y = int(122 * SY)
        if hovered_info:
            pyxel.rect(int(20 * SX), desc_y, int(160 * SX), int(12 * SY), 3)
            pyxel.rectb(int(20 * SX), desc_y, int(160 * SX), int(12 * SY), 11)
            pyxel.text(WIDTH // 2 - len(hovered_info) * 2, desc_y + int(4 * SY), hovered_info, 7)
        else:
            pyxel.text(int(30 * SX), desc_y, "Fahre ueber ein Upgrade fuer Infos", 6)

        back_x = int(70 * SX)
        back_y = int(150 * SY)
        back_w = int(60 * SX)
        back_h = int(15 * SY)
        hover_back = back_x < pyxel.mouse_x < back_x + back_w and back_y < pyxel.mouse_y < back_y + back_h
        pyxel.rect(back_x, back_y, back_w, back_h, 11 if hover_back else 3)
        pyxel.text(back_x + int(15 * SX), back_y + int(4 * SY), "ZURUECK", 7)

    elif state == "gameover":
        draw_background()
        pyxel.text(WIDTH // 2 - int(20 * SX), int(20 * SY), "GAME OVER", 8)

        box_x = int(20 * SX)
        box_y = int(40 * SY)
        box_w = WIDTH - int(40 * SX)
        box_h = int(80 * SY)
        pyxel.rectb(box_x, box_y, box_w, box_h, 5)
        pyxel.rect(box_x + 1, box_y + 1, box_w - 2, box_h - 2, 1)

        pyxel.text(WIDTH // 2 - int(22 * SX), box_y + int(4 * SY), "STATISTIK", 10)
        pyxel.text(box_x + int(8 * SX), box_y + int(16 * SY), f"Score:        {score}", 7)
        pyxel.text(box_x + int(8 * SX), box_y + int(24 * SY), f"Level:        {level}", 7)

        minutes = stats_time_played // 60
        seconds = stats_time_played % 60
        pyxel.text(box_x + int(8 * SX), box_y + int(32 * SY), f"Zeit:         {minutes}:{seconds:02d}", 7)
        pyxel.text(box_x + int(8 * SX), box_y + int(40 * SY), f"Coins total:  {stats_total_coins}", 10)

        if score >= high_score and score > 0:
            if timer % 20 < 10:
                pyxel.text(WIDTH // 2 - int(36 * SX), box_y + int(55 * SY), "NEUER HIGHSCORE!", 10)
        else:
            pyxel.text(box_x + int(8 * SX), box_y + int(55 * SY), f"High Score:   {high_score}", 14)

        if level == 1:
            msg = "Nicht aufgeben!"
        elif level <= 3:
            msg = "Gut gemacht!"
        elif level <= 5:
            msg = "Sehr stark!"
        else:
            msg = "UNGLAUBLICH!"
        pyxel.text(WIDTH // 2 - len(msg) * 2, box_y + int(68 * SY), msg, 11)

        pyxel.text(WIDTH // 2 - int(50 * SX), HEIGHT - int(15 * SY), "SPACE: Zurueck zum Menue", 7)


def setup_sounds():
    pyxel.sounds[30].set("e3g3c4", "t", "5", "n", 15)
    pyxel.sounds[31].set("c3e3", "s", "4", "f", 20)
    pyxel.sounds[32].set("c2a1f1", "n", "7", "f", 15)
    pyxel.sounds[33].set("c3e3g3c4", "t", "6", "f", 10)
    pyxel.sounds[34].set("c3e3g3c4", "s", "5", "f", 15)
    pyxel.sounds[35].set("c3e3g3c4e4g4", "t", "6", "n", 12)
    pyxel.sounds[36].set("c4a3f3d3c3", "p", "5", "f", 25)
    pyxel.sounds[37].set("c3g3c4e4g4", "t", "6", "n", 15)
    pyxel.sounds[38].set("c2c3c2", "n", "4", "f", 10)
    pyxel.sounds[39].set("g2", "n", "5", "f", 8)
    pyxel.sounds[40].set("g3c4e4", "t", "5", "n", 12)
    pyxel.sounds[41].set("e3", "s", "4", "n", 8)
    pyxel.sounds[42].set("c3e3g3c4e4g4", "t", "6", "n", 10)


# ============================================================
# START
# ============================================================
pyxel.init(WIDTH, HEIGHT, title="Crazy Ocean 512", fps=60)
pyxel.load("res.pyxres")
pyxel.mouse(True)
setup_sounds()
pyxel.playm(0, loop=True)
pyxel.run(update, draw)