#!/usr/bin/env python3
"""
╔══════════════════════════╗
║   WET FEET  3D           ║
║   Raycaster Edition      ║
║   Autor: Max Hauliš      ║
╚══════════════════════════╝
WASD = pohyb   Myš = otáčení   E = interakce   ESC = konec
"""
import pygame, sys, math, random, colorsys
from pygame.locals import *

pygame.init()
W, H = 1280, 720
screen = pygame.display.set_mode((W, H))
pygame.display.set_caption("WET FEET 3D")
clock = pygame.time.Clock()
FPS = 60

# Vnitřní rozlišení raycastereru (škálujeme 2x nahoru = výkon)
RW, RH = 640, 360
rsurf = pygame.Surface((RW, RH))

# ─── Fonty ───────────────────────────────────────────────────────────────
def mkfont(sz, bold=False):
    for nm in ("Arial", "DejaVu Sans", None):
        try: return pygame.font.SysFont(nm, sz, bold=bold)
        except: pass
    return pygame.font.Font(None, sz)

FH = mkfont(86, True)
FB = mkfont(54, True)
FM = mkfont(32)
FS = mkfont(22)
FC = mkfont(28, True)

# ─── Barvy ───────────────────────────────────────────────────────────────
BK=(0,0,0); WT=(255,255,255); LG=(150,155,160); RD=(180,20,20)
BLOOD=(110,0,0); GORE_C=(60,0,0); ELEC=(200,210,255)
CEIL_TOP=(30,32,38); CEIL_BOT=(48,52,60)
FLOOR_TOP=(60,64,72); FLOOR_BOT=(85,90,98)

# Barvy stěn: (světlá strana, tmavá strana)
WALL_COLS = {
    1: ((62,66,74),  (44,47,54)),   # locker
    2: ((78,82,90),  (58,62,70)),   # koupelna/sprchy
    3: ((38,40,46),  (26,28,33)),   # beton/vnější zeď
}

# ─── MAPA ────────────────────────────────────────────────────────────────
# 0=volno  1=skříňky  2=koupelna  3=beton
RAW_MAP = [
    "3333333333333333333333333",
    "3000000000000000000000003",
    "3010101010101010101010103",
    "3000000000000000000000003",
    "3010100000000000001010103",
    "3000002220000022200000003",
    "3010100200000002000010103",
    "3000002220000022200000003",
    "3010100000000000001010103",
    "3000000000000000000000003",
    "3010101010101010101010103",
    "3000000000000000000000003",
    "3333333333333333333333333",
]
MAP   = [[int(c) for c in row] for row in RAW_MAP]
MAP_H = len(MAP)
MAP_W = len(MAP[0])

def cell(x, y):
    mx, my = int(x), int(y)
    if mx < 0 or mx >= MAP_W or my < 0 or my >= MAP_H:
        return 3
    return MAP[my][mx]

def walkable(x, y):
    return cell(x, y) == 0

# ─── HRÁČ ────────────────────────────────────────────────────────────────
class Player:
    def __init__(self):
        self.x     = 3.5
        self.y     = 6.0
        self.angle = 0.0
        self.speed = 3.5
        self.bob_t = 0.0
        self.bob   = 0.0
        self.moved = False

    def update(self, dt, keys):
        dx = dy = 0.0
        if keys[K_w] or keys[K_UP]:
            dx += math.cos(self.angle) * self.speed * dt
            dy += math.sin(self.angle) * self.speed * dt
        if keys[K_s] or keys[K_DOWN]:
            dx -= math.cos(self.angle) * self.speed * dt
            dy -= math.sin(self.angle) * self.speed * dt
        if keys[K_a]:
            dx += math.cos(self.angle - math.pi/2) * self.speed * dt
            dy += math.sin(self.angle - math.pi/2) * self.speed * dt
        if keys[K_d]:
            dx += math.cos(self.angle + math.pi/2) * self.speed * dt
            dy += math.sin(self.angle + math.pi/2) * self.speed * dt

        margin = 0.25
        if walkable(self.x + dx, self.y):
            self.x += dx
        if walkable(self.x, self.y + dy):
            self.y += dy

        self.moved = abs(dx) > 0.001 or abs(dy) > 0.001
        if self.moved:
            self.bob_t += dt * 7
            self.bob = math.sin(self.bob_t) * 0.045
        else:
            self.bob *= 0.85

    def rotate(self, delta_rad):
        self.angle = (self.angle + delta_rad) % (2 * math.pi)

player = Player()

# ─── RAYCASTER (DDA) ──────────────────────────────────────────────────────
FOV      = math.pi / 2.8   # ~64°
HALF_FOV = FOV / 2.0
MAX_DIST = 18.0

def cast_ray(px, py, angle):
    """
    DDA algoritmus. Vrátí (kolmá_vzdálenost, typ_stěny, strana 0=NS 1=EW).
    """
    rdx = math.cos(angle)
    rdy = math.sin(angle)
    mx  = int(px)
    my  = int(py)

    ddx = abs(1.0 / rdx) if rdx != 0 else 1e30
    ddy = abs(1.0 / rdy) if rdy != 0 else 1e30

    if rdx < 0:
        sx = -1; sdx = (px - mx) * ddx
    else:
        sx = 1;  sdx = (mx + 1.0 - px) * ddx
    if rdy < 0:
        sy = -1; sdy = (py - my) * ddy
    else:
        sy = 1;  sdy = (my + 1.0 - py) * ddy

    side = 0
    wt   = 0
    for _ in range(64):
        if sdx < sdy:
            sdx += ddx; mx += sx; side = 0
        else:
            sdy += ddy; my += sy; side = 1
        wt = cell(mx, my)
        if wt > 0:
            break
    else:
        return MAX_DIST, 3, 0

    dist = (sdx - ddx) if side == 0 else (sdy - ddy)
    return max(0.05, dist), wt, side

def render_scene(surf, px, py, angle, bob):
    sw, sh = surf.get_size()
    half_h = sh // 2
    bob_px = int(bob * sh)

    # ── Strop (gradient) ──
    for y in range(half_h + bob_px):
        t = y / half_h
        r = int(CEIL_TOP[0] + (CEIL_BOT[0]-CEIL_TOP[0])*t)
        g = int(CEIL_TOP[1] + (CEIL_BOT[1]-CEIL_TOP[1])*t)
        b = int(CEIL_TOP[2] + (CEIL_BOT[2]-CEIL_TOP[2])*t)
        pygame.draw.line(surf, (r,g,b), (0,y), (sw,y))

    # ── Podlaha (gradient) ──
    for y in range(half_h + bob_px, sh):
        t = (y - half_h) / half_h
        r = int(FLOOR_TOP[0] + (FLOOR_BOT[0]-FLOOR_TOP[0])*t)
        g = int(FLOOR_TOP[1] + (FLOOR_BOT[1]-FLOOR_TOP[1])*t)
        b = int(FLOOR_TOP[2] + (FLOOR_BOT[2]-FLOOR_TOP[2])*t)
        pygame.draw.line(surf, (r,g,b), (0,y), (sw,y))

    # ── Zářivky na stropě ──
    for lx in (sw//5, sw//2, 4*sw//5):
        pygame.draw.rect(surf, (175,190,170), (lx-35, 1, 70, 5))
        glow_surf = pygame.Surface((90, 30), pygame.SRCALPHA)
        for gy in range(30):
            a = max(0, 35 - gy*2)
            pygame.draw.line(glow_surf, (190,210,185,a), (0,gy),(90,gy))
        surf.blit(glow_surf, (lx-45, 0))

    # ── Stěny ──
    n_cols = sw
    zbuf   = [MAX_DIST] * n_cols

    for i in range(n_cols):
        ray_angle = angle - HALF_FOV + FOV * i / n_cols
        dist, wt, side = cast_ray(px, py, ray_angle)
        zbuf[i] = dist

        wall_h  = min(sh * 2, int(sh / (dist + 1e-5)))
        wall_top = half_h - wall_h // 2 + bob_px
        wall_bot = wall_top + wall_h

        bright, dark = WALL_COLS.get(wt, WALL_COLS[3])
        base = bright if side == 0 else dark

        shade = max(0.1, 1.0 - dist / MAX_DIST)
        col   = tuple(int(c * shade) for c in base)

        # Locker seams — tmavé linky každých N pixelů
        if wt == 1 and dist < 8:
            seam_freq = max(4, int(wall_h / 4))
            col_in_wall = int((ray_angle % (math.pi*2)) * 50) % seam_freq
            if col_in_wall < 2:
                col = tuple(max(0, c - 18) for c in col)
        # Tile pattern (koupelna)
        elif wt == 2 and dist < 8:
            tile = int((ray_angle % (math.pi*2)) * 30) % 8
            if tile < 1:
                col = tuple(min(255, c + 12) for c in col)

        pygame.draw.line(surf, col, (i, wall_top), (i, wall_bot))

    return zbuf

# ─── SPRITY ───────────────────────────────────────────────────────────────
# (id, world_x, world_y, barva, label)
SPRITE_DEFS = [
    (0,  4.5,  1.5, (55,90,115), "FÉN"),
    (1, 16.5,  1.5, (200,200,185),"KAPESNÍK"),
    (2, 12.5,  5.5, (225,225,215),"TOALEŤÁK"),
    (3,  4.5, 10.5, (115,125,138),"RADIÁTOR"),
    (4, 20.5,  3.0, (48,50,58),  "SKŘÍŇKA"),
    (5, 12.5,  9.5, (175,208,228),"STŘEP"),
    (6,  7.5,  6.0, (65,72,84),  "VYSOUŠEČ"),
    (7, 17.5,  6.0, (16,16,18),  "PIJAVICE"),
    (8, 21.5,  6.0, (48,50,58),  "MIKROVLNKA"),
    (9, 17.5,  9.5, (28,28,36),  "KABEL"),
]
INTERACT_DIST = 1.8

def render_sprites(surf, px, py, angle, zbuf, completed):
    sw, sh = surf.get_size()
    half_h = sh // 2

    items = []
    for (mid, sx, sy, col, lbl) in SPRITE_DEFS:
        if mid in completed:
            continue
        dx = sx - px; dy = sy - py
        dist = math.hypot(dx, dy)
        if dist < 0.2:
            continue
        spr_angle = math.atan2(dy, dx)
        diff = spr_angle - angle
        while diff >  math.pi: diff -= 2*math.pi
        while diff < -math.pi: diff += 2*math.pi
        if abs(diff) > HALF_FOV * 1.3:
            continue
        items.append((dist, mid, sx, sy, col, lbl, diff))

    items.sort(reverse=True)  # back-to-front

    for dist, mid, sx, sy, col, lbl, diff in items:
        screen_cx = int((0.5 + diff / FOV) * sw)
        spr_h = min(sh, int(sh / (dist + 1e-5)))
        spr_w = spr_h // 2
        top_y = half_h - spr_h // 2

        shade = max(0.15, 1.0 - dist / MAX_DIST)
        dcol  = tuple(int(c * shade) for c in col)

        # Vykreslení sloupce po sloupci s z-testem
        x0 = max(0, screen_cx - spr_w // 2)
        x1 = min(sw, screen_cx + spr_w // 2)
        for x in range(x0, x1):
            if zbuf[x] > dist:
                pygame.draw.line(surf, dcol, (x, top_y), (x, top_y + spr_h))

        # Prompt [E] pokud dost blízko
        if dist < INTERACT_DIST * 1.3:
            bright = min(255, int(shade * 320))
            tcol = (bright, bright, bright)
            t = FS.render(f"[E] {lbl}", True, tcol)
            surf.blit(t, t.get_rect(center=(screen_cx, top_y - 14)))

# ─── MINIMAP ─────────────────────────────────────────────────────────────
def draw_minimap(surf, px, py, angle, completed):
    cs = 8   # cell size in pixels
    ox, oy = 10, 10
    for my in range(MAP_H):
        for mx in range(MAP_W):
            v = MAP[my][mx]
            c = {0:(35,38,44), 1:(55,60,70), 2:(65,70,80), 3:(20,22,26)}.get(v,(0,0,0))
            pygame.draw.rect(surf, c, (ox+mx*cs, oy+my*cs, cs-1, cs-1))
    # Sprity
    for (mid, sx, sy, col, lbl) in SPRITE_DEFS:
        if mid not in completed:
            pygame.draw.circle(surf, col,
                               (int(ox+sx*cs), int(oy+sy*cs)), 3)
    # Hráč
    px_s = int(ox + px*cs); py_s = int(oy + py*cs)
    pygame.draw.circle(surf, (255,220,100), (px_s, py_s), 4)
    ex = int(px_s + math.cos(angle)*10)
    ey = int(py_s + math.sin(angle)*10)
    pygame.draw.line(surf, (255,220,100), (px_s,py_s), (ex,ey), 2)

# ─── STAV HRY ────────────────────────────────────────────────────────────
completed   = set()
TOTAL       = 10
state       = "playing"   # playing | interacting | transition | ending
interact_id = -1
interact_t  = 0.0
interact_dur= 0.0
trans_phase = 0
trans_alpha = 0.0
trans_timer = 0.0
trans_name  = ""
trans_count = 0
ending_t    = 0.0
gore_flash  = 0.0
particles   = []
hovered_id  = -1

INTERACT_DURATIONS = [4.5, 4.0, 5.0, 5.0, 6.0, 6.0, 6.0, 7.0, 7.0, 5.5]
METHODS_NAMES = [
    "fén kámo", "kapesník", "toaleťák", "radiátor",
    "jakobych necítil bolest", "výměna kůže",
    "vysoušeč rukou (vylepšený)", "pijavice",
    "mikrovlnka (cože?)", "krvavý odpařovák",
]

# ─── PARTIKULKY ──────────────────────────────────────────────────────────
def spawn_p(x, y, col, n=20, spd=3, life=45, sz=(3,8)):
    for _ in range(n):
        a = random.uniform(0, 2*math.pi)
        s = random.uniform(0.4, spd)
        particles.append([x, y, math.cos(a)*s, math.sin(a)*s,
                          random.randint(life//2,life), life, col,
                          random.randint(*sz)])

def upd_p(surf):
    global particles
    keep = []
    for p in particles:
        p[0]+=p[2]; p[1]+=p[3]; p[3]+=0.12; p[4]-=1
        if p[4]>0:
            a=p[4]/p[5]
            c=tuple(int(v*a) for v in p[6])
            r=max(1,int(p[7]*a))
            pygame.draw.circle(surf,c,(int(p[0]),int(p[1])),r)
            keep.append(p)
    particles[:]=keep

# ─── POMOCNÉ ─────────────────────────────────────────────────────────────
def lerp(a,b,t): return a+(b-a)*t
def clamp(v,lo,hi): return max(lo,min(hi,v))

def draw_feet(surf, x, y, dry=False, gore=0):
    skin  = (195,155,125) if not dry else (170,130,95)
    if gore==1: skin=(155,55,55)
    elif gore==2: skin=(95,75,65)
    elif gore==3: skin=(35,25,20)
    for ox in (-125, 55):
        bx=x+ox
        pts=[(bx,y),(bx+78,y-18),(bx+88,y+38),(bx,y+58),(bx-10,y+28)]
        pygame.draw.polygon(surf,skin,pts)
        pygame.draw.polygon(surf,tuple(max(0,c-30) for c in skin),pts,2)
        for i in range(5):
            tx=bx+i*15; ty=y-12-max(0,(2-abs(i-2))*7)
            pygame.draw.circle(surf,skin,(tx,ty),7-abs(i-2))

def draw_prog(surf, t, dur):
    if dur<=0: return
    p=clamp(t/dur,0,1)
    bx,by,bw,bh=40,H-35,W-80,12
    pygame.draw.rect(surf,(40,44,50),(bx,by,bw,bh),border_radius=6)
    pygame.draw.rect(surf,(140,148,158),(bx,by,int(bw*p),bh),border_radius=6)

# ─── INTERAKCE (close-up sekvence) ───────────────────────────────────────
def draw_interaction(surf, mid, t):
    surf.fill((28,30,36))
    if   mid==0: _i_hairdryer(surf,t)
    elif mid==1: _i_tissue(surf,t)
    elif mid==2: _i_toiletpaper(surf,t)
    elif mid==3: _i_radiator(surf,t)
    elif mid==4: _i_locker(surf,t)
    elif mid==5: _i_shard(surf,t)
    elif mid==6: _i_handdryer(surf,t)
    elif mid==7: _i_leeches(surf,t)
    elif mid==8: _i_microwave(surf,t)
    elif mid==9: _i_cable(surf,t)
    draw_prog(surf,t,interact_dur)

def _i_hairdryer(surf,t):
    cx,cy=W//2-60,H//2-60
    pygame.draw.rect(surf,(46,50,58),(cx,cy,120,180),border_radius=10)
    pygame.draw.rect(surf,(90,95,102),(cx,cy,120,180),3,border_radius=10)
    pygame.draw.rect(surf,(46,50,58),(cx+120,cy+60,60,60))
    pygame.draw.rect(surf,(90,95,102),(cx+120,cy+60,60,60),2)
    pygame.draw.circle(surf,(60,210,60),(cx+20,cy+20),6)
    if t>0.5:
        for i in range(5):
            ax=cx+188+int(t*18+i*14)
            ay=cy+78+i*7
            pygame.draw.arc(surf,(210,150,70),(ax,ay,38,28),0,math.pi,3)
    draw_feet(surf,W//2,H-180,dry=t>3.2)
    if t<1:
        s=FM.render("ZAPÍNÁM FÉN...",True,(150,155,162))
        surf.blit(s,s.get_rect(center=(W//2,55)))

def _i_tissue(surf,t):
    kx,ky=W//2-80,H//2-90
    pygame.draw.rect(surf,(205,205,195),(kx,ky,160,78),border_radius=6)
    pygame.draw.rect(surf,(155,158,162),(kx,ky,160,78),2,border_radius=6)
    pygame.draw.rect(surf,(240,240,235),(kx+60,ky-18,40,28))
    if t>0.8:
        hx,hy=W//2-28,H//2
        pygame.draw.rect(surf,(240,240,235),(hx,hy,58,78),border_radius=5)
    draw_feet(surf,W//2,H-162,dry=t>3.2)
    if t<1:
        s=FM.render("BERU KAPESNÍK...",True,(150,155,162))
        surf.blit(s,s.get_rect(center=(W//2,55)))

def _i_toiletpaper(surf,t):
    cx,cy=W//2,H//2-40
    pygame.draw.circle(surf,(238,238,232),(cx,cy),50)
    pygame.draw.circle(surf,(160,162,165),(cx,cy),50,2)
    pygame.draw.circle(surf,(48,52,60),(cx,cy),18)
    pl=clamp(int(t*75),0,280)
    if pl>0:
        pygame.draw.rect(surf,(238,238,232),(cx+50,cy-10,pl,20))
    draw_feet(surf,W//2,H-162,dry=t>3.8)
    if t<1:
        s=FM.render("OMOTÁVÁM NOHY...",True,(150,155,162))
        surf.blit(s,s.get_rect(center=(W//2,55)))

def _i_radiator(surf,t):
    rx,ry=W//2-150,H//2-30
    pygame.draw.rect(surf,(135,145,158),(rx,ry,300,100),border_radius=5)
    pygame.draw.rect(surf,(115,128,142),(rx,ry,300,100),3,border_radius=5)
    for i in range(10):
        lx=rx+20+i*26
        pygame.draw.line(surf,(110,122,136),(lx,ry+10),(lx,ry+90),8)
    if t>0.5:
        for i in range(4):
            sx=rx+38+i*58
            sy=ry-int(t*12)-28
            pulse=0.5+0.5*math.sin(t*3+i)
            for s in range(3):
                pygame.draw.circle(surf,(175,185,195),(sx+int(math.sin(t+i+s)*8),sy-s*18),9-s*2)
    draw_feet(surf,W//2,H-142,dry=t>4.0)
    if t<1:
        s=FM.render("PŘIKLÁDÁM CHODIDLA...",True,(150,155,162))
        surf.blit(s,s.get_rect(center=(W//2,55)))

def _i_locker(surf,t):
    global gore_flash
    lx,ly=W//2-100,95; lw,lh=200,400
    pygame.draw.rect(surf,(48,52,60),(lx,ly,lw,lh),border_radius=5)
    pygame.draw.rect(surf,(88,94,102),(lx,ly,lw,lh),3,border_radius=5)
    slam=(t%0.8)
    if slam<0.3 and t>0.5:
        da=slam/0.3*38
        door=[
            (lx,ly),
            (lx-int(38*math.cos(math.radians(da))),ly+int(38*math.sin(math.radians(da)))),
            (lx-int(38*math.cos(math.radians(da))),ly+lh+int(38*math.sin(math.radians(da)))),
            (lx,ly+lh)
        ]
        pygame.draw.polygon(surf,(68,74,84),door)
        pygame.draw.polygon(surf,(90,96,104),door,2)
    ba=clamp(int((t-1.0)*55),0,180)
    for i in range(ba):
        random.seed(i*7+13)
        bx=lx+random.randint(-48,lw+48)
        by=ly+lh-random.randint(0,145)
        pygame.draw.circle(surf,BLOOD,(bx,by),random.randint(2,8))
    random.seed()
    if t>1.0 and int(t*4)%2==0: gore_flash=0.6
    if t<3.5:
        draw_feet(surf,W//2+80,H-142,gore=1)
    else:
        draw_feet(surf,W//2,H-100,gore=2)
        s=FM.render("...UTÍRÁM SI JE O VLASY...",True,RD)
        surf.blit(s,s.get_rect(center=(W//2,75)))
    spawn_p(lx,ly+lh,BLOOD,n=3,spd=3,life=25)
    upd_p(surf)

def _i_shard(surf,t):
    sx,sy=W//2-18,H//2-95
    pts=[(sx,sy-58),(sx+38,sy-14),(sx+24,sy+18),(sx-18,sy+24),(sx-43,sy-18)]
    pygame.draw.polygon(surf,(175,210,232),pts)
    pygame.draw.polygon(surf,(230,240,248),pts,2)
    pygame.draw.line(surf,(240,248,255),(sx-8,sy-42),(sx+14,sy-4),3)
    cp=clamp((t-0.5)/5.0,0,1)
    if cp>0:
        for i in range(int(cp*10)):
            pygame.draw.circle(surf,BLOOD,(W//2-128+i*22,H-168),5)
    gore=1 if t<3 else 2
    draw_feet(surf,W//2,H-142,gore=gore)
    if t>1.0: spawn_p(W//2-58,H-172,BLOOD,n=2,spd=2,life=30)
    upd_p(surf)
    if t>3.2:
        s=FM.render("POD KŮŽÍ JE TO... SUCHÉ.",True,RD)
        surf.blit(s,s.get_rect(center=(W//2,58)))

def _i_handdryer(surf,t):
    dx,dy_=W//2-150,75; dw,dh=300,240
    if t<2.0:
        pygame.draw.rect(surf,(46,50,58),(dx,dy_,dw,dh),border_radius=14)
        pygame.draw.rect(surf,(90,96,104),(dx,dy_,dw,dh),3,border_radius=14)
        pygame.draw.rect(surf,(28,30,36),(dx+28,dy_+28,dw-58,58),border_radius=5)
        pygame.draw.circle(surf,RD,(dx+dw//2,dy_+108),10)
        s=FM.render("NORMÁLNÍ VYSOUŠEČ...",True,(150,155,162))
        surf.blit(s,s.get_rect(center=(W//2,45)))
    else:
        pd=clamp((t-2.0)/2.0,0,1)
        py_=int(dy_+dh+pd*195)
        pygame.draw.rect(surf,(105,28,28),(dx,py_-18,dw,38))
        pygame.draw.rect(surf,RD,(dx,py_-18,dw,38),3)
        if pd>0.5: spawn_p(W//2,py_,BLOOD,n=4,spd=5,life=40)
        s=FM.render("— LIS —",True,RD)
        surf.blit(s,s.get_rect(center=(W//2,45)))
    gore=0 if t<2 else (1 if t<3 else 3)
    draw_feet(surf,W//2,H-142,gore=gore)
    upd_p(surf)

def _i_leeches(surf,t):
    pygame.draw.rect(surf,(62,66,74),(0,H//2,W,H//2))
    pygame.draw.rect(surf,(52,56,62),(0,H//2,W,5))
    for i in range(80):
        random.seed(i*11+7)
        lx=W//2+random.randint(-275,275)
        ly=H-102+random.randint(-28,28)
        wig=math.sin(t*4+i*0.5)*5
        lw=random.randint(24,54); lh=14
        ls=pygame.Surface((lw,lh),pygame.SRCALPHA)
        fill=clamp(t/5.0,0,1)
        pygame.draw.ellipse(ls,(18,18,20),(0,0,lw,lh))
        fc=int(lerp(18,115,fill))
        pygame.draw.ellipse(ls,(fc,0,0),(2,2,lw-4,10))
        surf.blit(ls,(int(lx+wig),ly))
    random.seed()
    gore=0 if t<1 else (1 if t<4 else 2)
    draw_feet(surf,W//2,H-102,gore=gore)
    if t>4.2:
        s=FM.render("ZBYLY JEN ŠLACHY...",True,RD)
        surf.blit(s,s.get_rect(center=(W//2,58)))

def _i_microwave(surf,t):
    mx,my_=W//2-160,95; mw,mh=320,240
    pygame.draw.rect(surf,(46,50,58),(mx,my_,mw,mh),border_radius=8)
    pygame.draw.rect(surf,(90,96,104),(mx,my_,mw,mh),3,border_radius=8)
    pygame.draw.rect(surf,(26,28,34),(mx+14,my_+18,mw-88,mh-48),border_radius=5)
    if t>1.5:
        gi=0.5+0.5*math.sin(t*14)
        glow=(int(215*gi),int(95*gi),0)
        pygame.draw.rect(surf,glow,(mx+18,my_+22,mw-92,mh-52))
        if int(t*10)%3==0:
            for _ in range(3):
                sx=mx+20+random.randint(0,mw-95)
                sy2=my_+22+random.randint(0,mh-55)
                pygame.draw.circle(surf,(235,240,245),(sx,sy2),random.randint(2,5))
    if t>5.5:
        pygame.draw.rect(surf,(46,50,58),(mx-58,my_,54,mh))
        pygame.draw.rect(surf,(90,96,104),(mx-58,my_,54,mh),2)
    gore=0 if t<1.5 else (1 if t<3 else 3)
    draw_feet(surf,W//2,H-142,gore=gore)
    if t>3: spawn_p(W//2,H-162,(145,75,28),n=2,spd=1,life=62,sz=(4,12))
    upd_p(surf)
    if t<1.5:
        s=FM.render("PLNÝ VÝKON...",True,(150,155,162))
        surf.blit(s,s.get_rect(center=(W//2,48)))
    elif t>5.0:
        s=FM.render("KŘUPAVĚ SUCHÉ.",True,RD)
        surf.blit(s,s.get_rect(center=(W//2,48)))

def _i_cable(surf,t):
    pts2=[]
    for i in range(20):
        ti=i/19.0
        cx=W//2+int((ti-0.5)*245)+int(math.sin(ti*math.pi*3+t*2)*14)
        cy=H//2+int(ti*78)
        pts2.append((cx,cy))
    if len(pts2)>1:
        pygame.draw.lines(surf,(28,28,36),False,pts2,10)
        pygame.draw.lines(surf,(55,55,65),False,pts2,5)
    pygame.draw.circle(surf,(215,115,18),pts2[-1],14)
    if t>1.5:
        zt=t-1.5
        if zt<0.5:
            fa=int(255*(1-zt/0.5))
            fs=pygame.Surface((W,H)); fs.fill(ELEC); fs.set_alpha(fa)
            surf.blit(fs,(0,0))
            for _ in range(8):
                ax=W//2+random.randint(-145,145)
                ay=H//2+random.randint(-95,95)
                pygame.draw.line(surf,ELEC,(W//2,H//2),(ax,ay),random.randint(1,4))
        elif zt<2.5:
            spawn_p(W//2,H-152,BLOOD,n=3,spd=2,life=82,sz=(6,18))
            spawn_p(W//2,H-152,(38,28,22),n=2,spd=1,life=105,sz=(8,20))
    upd_p(surf)
    gore=0 if t<1.5 else 3
    draw_feet(surf,W//2,H-142,gore=gore)
    if t<1.0:
        s=FM.render("PŘIKLÁDÁM KABEL K NOHÁM...",True,(150,155,162))
        surf.blit(s,s.get_rect(center=(W//2,58)))
    elif t>2.5:
        s=FM.render("VODA SE V MŽIKU VYPAŘÍ.",True,ELEC)
        surf.blit(s,s.get_rect(center=(W//2,58)))

# ─── PŘECHOD ─────────────────────────────────────────────────────────────
def draw_transition(surf, alpha, count, name):
    ov=pygame.Surface((W,H)); ov.fill(BK); ov.set_alpha(int(clamp(alpha,0,255)))
    surf.blit(ov,(0,0))
    if alpha>210:
        t=FC.render(f"{count}/{TOTAL}   -{name}-",True,WT)
        surf.blit(t,t.get_rect(center=(W//2,H//2)))

# ─── ENDING ──────────────────────────────────────────────────────────────
def draw_ending(surf, t):
    hue=(t*0.14)%1.0
    r,g,b=colorsys.hsv_to_rgb(hue,0.95,1.0)
    surf.fill((int(r*255),int(g*255),int(b*255)))
    for i in range(0,W,80):
        for j in range(0,H,80):
            bh=(i/W+j/H+t*0.28)%1.0
            br,bg2,bb=colorsys.hsv_to_rgb(bh,1.0,1.0)
            if int((i//80+j//80+int(t*8)))%2==0:
                pygame.draw.rect(surf,(int(br*255),int(bg2*255),int(bb*255)),(i,j,80,80))
    th=(t*0.38+0.3)%1.0
    tr,tg,tb=colorsys.hsv_to_rgb(th,1.0,1.0)
    tc=(int(tr*255),int(tg*255),int(tb*255))
    sh2=FH.render("JÓOO VYHRÁL JSI!!!",True,BK)
    surf.blit(sh2,sh2.get_rect(center=(W//2+4,H//2-82+4)))
    wt=FH.render("JÓOO VYHRÁL JSI!!!",True,tc)
    surf.blit(wt,wt.get_rect(center=(W//2,H//2-82)))
    sh2=FB.render("10 / 10",True,BK)
    surf.blit(sh2,sh2.get_rect(center=(W//2+3,H//2+18+3)))
    sc_h=(t*0.5+0.6)%1.0
    sr,sg2,sb=colorsys.hsv_to_rgb(sc_h,1.0,1.0)
    sc=FB.render("10 / 10",True,(int(sr*255),int(sg2*255),int(sb*255)))
    surf.blit(sc,sc.get_rect(center=(W//2,H//2+18)))
    au=FM.render("tuto hru vymyslel Max Hauliš",True,WT)
    surf.blit(au,au.get_rect(center=(W//2,H//2+98)))
    es=FS.render("[ESC] Ukončit",True,(200,200,200))
    surf.blit(es,(W-182,H-30))

# ─── HUD ─────────────────────────────────────────────────────────────────
def draw_hud(surf, completed, hov_id):
    # Counter
    ct=FC.render(f"{len(completed)}/{TOTAL}",True,(145,150,158))
    surf.blit(ct,(16,16))
    # Crosshair
    cx,cy=W//2,H//2
    pygame.draw.line(surf,(200,205,210,180),(cx-12,cy),(cx-4,cy),1)
    pygame.draw.line(surf,(200,205,210,180),(cx+4,cy),(cx+12,cy),1)
    pygame.draw.line(surf,(200,205,210,180),(cx,cy-12),(cx,cy-4),1)
    pygame.draw.line(surf,(200,205,210,180),(cx,cy+4),(cx,cy+12),1)
    # Prompt pokud hráč kouká na objekt
    if hov_id >= 0:
        name = METHODS_NAMES[hov_id]
        pt = FM.render(f"[E]  {name}", True, WT)
        surf.blit(pt, pt.get_rect(center=(W//2, H - 90)))

# ─── DETEKCE INTERAKTIVNÍHO OBJEKTU ──────────────────────────────────────
def find_hovered():
    """Vrátí id metody pokud hráč stojí blízko a kouká na objekt."""
    for (mid, sx, sy, col, lbl) in SPRITE_DEFS:
        if mid in completed:
            continue
        dx = sx - player.x; dy = sy - player.y
        dist = math.hypot(dx, dy)
        if dist > INTERACT_DIST:
            continue
        # Úhel od hráče k objektu vs směr pohledu
        obj_angle = math.atan2(dy, dx)
        diff = obj_angle - player.angle
        while diff >  math.pi: diff -= 2*math.pi
        while diff < -math.pi: diff += 2*math.pi
        if abs(diff) < math.pi / 2.5:  # v přibližném výhledu
            return mid
    return -1

# ─── HERNÍ SMYČKA ────────────────────────────────────────────────────────
def main():
    global state, completed, interact_id, interact_t, interact_dur
    global trans_phase, trans_alpha, trans_timer, trans_name, trans_count
    global ending_t, gore_flash, hovered_id

    # Zachytit myš
    pygame.event.set_grab(True)
    pygame.mouse.set_visible(False)

    flicker_v   = 1.0
    flicker_t   = 0.0

    while True:
        dt = min(clock.tick(FPS) / 1000.0, 0.05)

        # ── Eventy ──────────────────────────────────────────────────────
        for ev in pygame.event.get():
            if ev.type == QUIT:
                pygame.quit(); sys.exit()

            if ev.type == KEYDOWN:
                if ev.key == K_ESCAPE:
                    pygame.event.set_grab(False)
                    pygame.mouse.set_visible(True)
                    pygame.quit(); sys.exit()

                if state == "playing" and ev.key == K_e:
                    if hovered_id >= 0:
                        interact_id  = hovered_id
                        interact_dur = INTERACT_DURATIONS[interact_id]
                        interact_t   = 0.0
                        state        = "interacting"

            if ev.type == MOUSEMOTION and state == "playing":
                player.rotate(ev.rel[0] * 0.0022)

            if ev.type == MOUSEBUTTONDOWN and ev.button == 1 and state == "playing":
                if hovered_id >= 0:
                    interact_id  = hovered_id
                    interact_dur = INTERACT_DURATIONS[interact_id]
                    interact_t   = 0.0
                    state        = "interacting"

        # ── Update ──────────────────────────────────────────────────────
        if state == "playing":
            keys = pygame.key.get_pressed()
            player.update(dt, keys)
            hovered_id = find_hovered()

            # Blikání světel
            flicker_t -= dt
            if flicker_t <= 0:
                flicker_t = random.uniform(0.08, 3.5)
                flicker_v = random.uniform(0.35,0.8) if random.random()<0.12 else 1.0

            gore_flash = max(0, gore_flash - dt*3)

        elif state == "interacting":
            interact_t += dt
            gore_flash = max(0, gore_flash - dt*2)
            if interact_t >= interact_dur:
                # Dokončení metody → přechod
                completed.add(interact_id)
                trans_count = len(completed)
                trans_name  = METHODS_NAMES[interact_id]
                trans_phase = 0
                trans_alpha = 0.0
                trans_timer = 0.0
                state = "transition"

        elif state == "transition":
            trans_timer += dt
            FADE=0.7; HOLD=2.5; FADEBACK=0.7
            if trans_phase == 0:
                trans_alpha = clamp(trans_timer/FADE*255,0,255)
                if trans_timer >= FADE: trans_phase=1; trans_timer=0.0
            elif trans_phase == 1:
                trans_alpha = 255
                if trans_timer >= HOLD:
                    if trans_count >= TOTAL:
                        state="ending"; ending_t=0.0; continue
                    trans_phase=2; trans_timer=0.0
            elif trans_phase == 2:
                trans_alpha = clamp((1-trans_timer/FADEBACK)*255,0,255)
                if trans_timer >= FADEBACK:
                    trans_alpha=0; state="playing"
                    pygame.event.set_grab(True)
                    pygame.mouse.set_visible(False)

        elif state == "ending":
            ending_t += dt

        # ── Render ──────────────────────────────────────────────────────
        screen.fill((26,28,34))

        if state in ("playing","transition"):
            # Raycaster na rsurf (640x360), pak scale
            zbuf = render_scene(rsurf, player.x, player.y, player.angle, player.bob)
            render_sprites(rsurf, player.x, player.y, player.angle, zbuf, completed)

            # Blikání světel (tmavý overlay)
            if flicker_v < 0.98:
                fov2 = pygame.Surface((RW,RH)); fov2.fill(BK)
                fov2.set_alpha(int((1.0-flicker_v)*200))
                rsurf.blit(fov2,(0,0))

            scaled = pygame.transform.scale(rsurf, (W, H))
            screen.blit(scaled, (0,0))

            # Minimap
            draw_minimap(screen, player.x, player.y, player.angle, completed)
            # HUD
            draw_hud(screen, completed, hovered_id)

            # Gore červený tint
            if gore_flash > 0:
                gt=pygame.Surface((W,H)); gt.fill(GORE_C)
                gt.set_alpha(int(gore_flash*115))
                screen.blit(gt,(0,0))

        elif state == "interacting":
            draw_interaction(screen, interact_id, interact_t)

        elif state == "ending":
            draw_ending(screen, ending_t)

        if state == "transition":
            draw_transition(screen, trans_alpha, trans_count, trans_name)

        # Nápověda na začátku
        if state=="playing" and len(completed)==0:
            h=FS.render("WASD = pohyb   Myš = otáčení   E = interakce",True,(75,80,88))
            screen.blit(h,h.get_rect(center=(W//2,H-14)))

        pygame.display.flip()

if __name__ == "__main__":
    main()
