"""
titlescreen.py — Procedural title-screen art for Micro Racers.
Call draw_title_art(frame_count) each frame on the title screen.
"""
from pyxel import rect, rectb, pset, line, circ, tri, text, cls
from math import sin, cos, pi

W = 1024
H = 512

SKY_BOT = int(H * 2 / 3)
HORIZON = SKY_BOT

# Cloud definitions: (base_x, y, width, height, speed_factor)
_CLOUDS = [
    # Far — small, high, moderate speed
    (50,   55,  55,  12, 0.25),
    (150,  68,  42,   9, 0.20),
    (280,  50,  60,  13, 0.22),
    (400,  62,  48,  10, 0.28),
    (520,  58,  52,  11, 0.24),
    (650,  48,  65,  14, 0.18),
    (780,  66,  40,   9, 0.26),
    (900,  54,  58,  12, 0.21),
    (1000, 70,  35,   8, 0.23),
    (70,   78,  38,   8, 0.19),
    (340,  75,  44,  10, 0.27),
    (560,  72,  50,  11, 0.22),
    (820,  76,  36,   8, 0.25),
    # Mid — medium speed
    (60,  100,  90,  20, 0.45),
    (210, 110, 110,  22, 0.40),
    (380,  95, 100,  19, 0.50),
    (540, 115,  85,  18, 0.42),
    (700, 105,  95,  20, 0.48),
    (860, 118,  80,  17, 0.38),
    (130, 125,  75,  16, 0.44),
    (470, 128,  70,  15, 0.46),
    (620, 100,  88,  19, 0.43),
    (950, 112,  72,  16, 0.41),
    # Near — large, fast
    (40,  150, 150,  30, 0.75),
    (250, 160, 170,  34, 0.68),
    (480, 145, 140,  28, 0.80),
    (700, 155, 160,  32, 0.72),
    (900, 165, 130,  26, 0.65),
    (150, 170, 120,  28, 0.78),
    (550, 175, 155,  35, 0.82),
    (800, 148, 110,  24, 0.70),
]

# Mountain peaks
_PEAKS = [
    (0, 0), (40, -25), (100, -10), (160, -40), (230, -15),
    (300, -50), (380, -20), (440, -55), (510, -30), (560, -45),
    (630, -18), (700, -42), (760, -12), (830, -38), (890, -22),
    (950, -48), (1024, -10),
]


def _sky():
    rect(0, 0, W, H, 6)


def _draw_fluffy_cloud(cx, cy, w, h, col_main, col_shadow, col_highlight):
    """Fluffy cloud from overlapping circles with 3-color depth."""
    num_puffs = max(3, w // 14)
    # Shadow layer (bottom)
    for i in range(num_puffs):
        frac = i / max(1, num_puffs - 1)
        px = int(cx - w * 0.42 + frac * w * 0.84)
        py = cy + 4
        r = int(h * 0.38 + sin(frac * pi) * h * 0.22)
        circ(px, py, r, col_shadow)
    # Main body
    for i in range(num_puffs):
        frac = i / max(1, num_puffs - 1)
        px = int(cx - w * 0.42 + frac * w * 0.84)
        py = cy - int(sin(frac * pi) * h * 0.18)
        r = int(h * 0.42 + sin(frac * pi) * h * 0.28)
        circ(px, py, r, col_main)
    # Top highlight bumps (brighter)
    for i in range(max(2, num_puffs - 1)):
        frac = (i + 0.5) / max(1, num_puffs - 1)
        px = int(cx - w * 0.3 + frac * w * 0.6)
        py = cy - int(h * 0.35 + sin(frac * 2.5) * h * 0.12)
        r = int(h * 0.20 + sin(frac * pi) * h * 0.10)
        circ(px, py, r, col_highlight)


def _clouds(frame):
    for base_x, cy, cw, ch, spd in _CLOUDS:
        drift = frame * spd
        cx = int((base_x + drift) % (W + cw * 2) - cw)
        _draw_fluffy_cloud(cx, cy, cw, ch, 7, 13, 15)


def _sun():
    sx, sy = 850, 70
    circ(sx, sy, 24, 10)
    circ(sx, sy, 18, 10)


def _mountains():
    """Mountain silhouette with snow-capped peaks."""
    base_y = HORIZON
    # Dark mountain body (color 1)
    for i in range(len(_PEAKS) - 1):
        x1, dy1 = _PEAKS[i]
        x2, dy2 = _PEAKS[i + 1]
        y1 = base_y + dy1
        y2 = base_y + dy2
        tri(x1, y1, x2, y2, x1, base_y + 10, 1)
        tri(x2, y2, x2, base_y + 10, x1, base_y + 10, 1)

    # Snow caps — white triangles on the top portion of each peak
    for i in range(len(_PEAKS)):
        px, dy = _PEAKS[i]
        if dy < -20:  # only tall peaks get snow
            peak_y = base_y + dy
            snow_depth = int(abs(dy) * 0.4)
            snow_hw = int(abs(dy) * 0.35)
            # White snow triangle
            tri(px, peak_y, px - snow_hw, peak_y + snow_depth,
                px + snow_hw, peak_y + snow_depth, 7)
            # Lighter snow highlight at very top
            tiny_hw = max(2, snow_hw // 3)
            tiny_d = max(2, snow_depth // 3)
            tri(px, peak_y, px - tiny_hw, peak_y + tiny_d,
                px + tiny_hw, peak_y + tiny_d, 15)


def _ground():
    rect(0, HORIZON, W, H - HORIZON, 11)


def _road_and_barriers():
    road_top = HORIZON + 5
    road_bot = H
    vx = W // 2
    vy = road_top - 20

    num_slices = 80
    for i in range(num_slices):
        frac0 = i / num_slices
        frac1 = (i + 1) / num_slices
        spread0 = 12 + frac0 * (W * 0.56)
        spread1 = 12 + frac1 * (W * 0.56)
        y0 = int(vy + frac0 * (road_bot - vy))
        y1 = int(vy + frac1 * (road_bot - vy))
        lx0 = int(vx - spread0)
        rx0 = int(vx + spread0)
        lx1 = int(vx - spread1)
        rx1 = int(vx + spread1)
        for y in range(y0, min(y1 + 1, road_bot)):
            t = (y - y0) / max(1, y1 - y0)
            lx = max(0, int(lx0 + t * (lx1 - lx0)))
            rx = min(W, int(rx0 + t * (rx1 - rx0)))
            if rx > lx:
                rect(lx, y, rx - lx, 1, 13)

    barrier_base_w = 44
    num_segments = 30
    for side in (-1, 1):
        for i in range(num_segments):
            frac0 = i / num_segments
            frac1 = (i + 1) / num_segments
            spread0 = 12 + frac0 * (W * 0.56)
            spread1 = 12 + frac1 * (W * 0.56)
            bw0 = max(4, int(6 + frac0 * barrier_base_w))
            bw1 = max(4, int(6 + frac1 * barrier_base_w))
            y0 = int(vy + frac0 * (road_bot - vy))
            y1 = int(vy + frac1 * (road_bot - vy))
            x0 = int(vx + side * spread0)
            x1 = int(vx + side * spread1)
            col = 8 if i % 2 == 0 else 7
            if side == -1:
                tri(x0 - bw0, y0, x0, y0, x1, y1, col)
                tri(x0 - bw0, y0, x1, y1, x1 - bw1, y1, col)
            else:
                tri(x0, y0, x0 + bw0, y0, x1 + bw1, y1, col)
                tri(x0, y0, x1 + bw1, y1, x1, y1, col)

    for i in range(20):
        frac = i / 20.0
        y = int(vy + frac * (road_bot - vy))
        frac2 = frac + 0.025
        y2 = int(vy + frac2 * (road_bot - vy))
        dash_w = 15
        if i % 2 == 0:
            rect(vx - dash_w // 2, y, dash_w, y2 - y, 7)


def _draw_car_rear(cx, cy, body_col, accent_col):
    """Sleek racing car rear view — clean rectangle, no side triangles."""
    hw = 44
    h = 50

    top = cy
    bot = cy + h

    # Wide black tires
    tire_w = 18
    tire_h = 24
    tire_top = bot - tire_h - 2
    rect(cx - hw - tire_w, tire_top, tire_w, tire_h, 0)
    rect(cx + hw, tire_top, tire_w, tire_h, 0)

    # Main body — clean rectangle, no tapered roof triangles
    rect(cx - hw, top, hw * 2, h, body_col)

    # Roof accent — flat rectangle (no trapezoid = no side triangles)
    roof_hw = int(hw * 0.78)
    roof_h = int(h * 0.32)
    rect(cx - roof_hw, top, roof_hw * 2, roof_h, accent_col)

    # Two wide white racing stripes
    stripe_w = 7
    stripe_offset = 14
    rect(cx - stripe_offset - stripe_w // 2, top, stripe_w, h, 7)
    rect(cx + stripe_offset - stripe_w // 2, top, stripe_w, h, 7)

    # Rear window
    win_hw = int(hw * 0.5)
    win_h = int(h * 0.2)
    win_top = top + 3
    rect(cx - win_hw, win_top, win_hw * 2, win_h, 1)
    line(cx - win_hw + 3, win_top + 2, cx - win_hw + 3, win_top + win_h - 2, 6)

    # Side panel dark edges
    rect(cx - hw, top + 4, 2, h - 8, 0)
    rect(cx + hw - 2, top + 4, 2, h - 8, 0)

    # Tail lights
    tl_y = bot - 8
    tl_w = 10
    tl_h = 5
    rect(cx - hw + 3, tl_y, tl_w, tl_h, 8)
    rect(cx + hw - 3 - tl_w, tl_y, tl_w, tl_h, 8)
    rect(cx - hw + 5, tl_y + 1, 4, 3, 10)
    rect(cx + hw - 9, tl_y + 1, 4, 3, 10)

    # Bumper
    rect(cx - hw + 3, bot - 3, hw * 2 - 6, 3, 5)

    # Single center exhaust pipe — black rectangle
    pipe_w = 12
    pipe_h = 5
    rect(cx - pipe_w // 2, bot - 1, pipe_w, pipe_h, 0)
    # Metallic rim
    rect(cx - pipe_w // 2, bot - 1, pipe_w, 1, 5)

    # Spoiler
    rect(cx - hw + 6, top + roof_h + 1, hw * 2 - 12, 2, 0)
    rect(cx - hw + 9, top + roof_h - 1, 3, 4, 0)
    rect(cx + hw - 12, top + roof_h - 1, 3, 4, 0)


def _cars():
    car_y = HORIZON + 55
    _draw_car_rear(W // 2 - 130, car_y, 8, 2)
    _draw_car_rear(W // 2 + 130, car_y, 12, 1)


def _exhaust_smoke(frame):
    """White exhaust circles from center pipe of each car."""
    import random

    car_positions = [
        (W // 2 - 130,),
        (W // 2 + 130,),
    ]
    for (car_cx,) in car_positions:
        car_bot = HORIZON + 55 + 50 + 4  # car_y + height + pipe

        # Large puffs — all white
        random.seed(frame // 5 + car_cx)
        for i in range(12):
            sx = car_cx + random.randint(-40, 40)
            sy = car_bot + random.randint(5, 70)
            r = random.randint(4, 12)
            circ(sx, sy, r, 7)

        # Medium puffs
        random.seed(frame // 3 + car_cx + 1000)
        for i in range(8):
            sx = car_cx + random.randint(-25, 25)
            sy = car_bot + random.randint(0, 45)
            r = random.randint(2, 6)
            circ(sx, sy, r, 7)

        # Fine wisps near pipe
        random.seed(frame // 2 + car_cx + 2000)
        for i in range(5):
            sx = car_cx + random.randint(-8, 8)
            sy = car_bot + random.randint(0, 15)
            r = random.randint(1, 3)
            circ(sx, sy, r, 13)  # slightly grey near source


def _border():
    rectb(0, 0, W, H, 0)
    rectb(1, 1, W - 2, H - 2, 1)


def _draw_block_letter(x, y, letter, col, shadow_col, scale=6):
    font = {
        'M': ["X...X","XX.XX","X.X.X","X...X","X...X","X...X","X...X"],
        'I': ["XXX",".X.",".X.",".X.",".X.",".X.","XXX"],
        'C': [".XXX","X...","X...","X...","X...","X...",".XXX"],
        'R': ["XXXX","X..X","X..X","XXX.","X.X.","X..X","X..X"],
        'O': [".XX.","X..X","X..X","X..X","X..X","X..X",".XX."],
        'A': [".XX.","X..X","X..X","XXXX","X..X","X..X","X..X"],
        'E': ["XXXX","X...","X...","XXX.","X...","X...","XXXX"],
        'S': [".XXX","X...","X...",".XX.","...X","...X","XXX."],
    }
    glyph = font.get(letter, [])
    s = scale
    sh = max(3, scale // 3)
    for row_i, row in enumerate(glyph):
        for col_i, ch in enumerate(row):
            if ch == 'X':
                rect(x + col_i * s + sh, y + row_i * s + sh, s, s, shadow_col)
    for row_i, row in enumerate(glyph):
        for col_i, ch in enumerate(row):
            if ch == 'X':
                rect(x + col_i * s, y + row_i * s, s, s, col)
                rect(x + col_i * s, y + row_i * s, s, 1, 15)


def _title_text():
    """Draw 'MICRO RACERS' with alternating white and red letters."""
    scale = 14
    gap = 8
    widths = {'M':5,'I':3,'C':4,'R':4,'O':4,'A':4,'E':4,'S':4}

    def word_width(word):
        return sum(widths.get(ch, 4) * scale + gap for ch in word) - gap

    word1 = "MICRO"
    word2 = "RACERS"
    w1 = word_width(word1)
    w2 = word_width(word2)

    y1 = 20
    y2 = 20 + 7 * scale + 14

    # Alternating colors: white (7) and red (8), continuous index across both words
    colors = [7, 8]
    idx = 0

    cx = (W - w1) // 2
    for ch in word1:
        col = colors[idx % 2]
        _draw_block_letter(cx, y1, ch, col, 1, scale)
        cx += widths.get(ch, 4) * scale + gap
        idx += 1

    cx = (W - w2) // 2
    for ch in word2:
        col = colors[idx % 2]
        _draw_block_letter(cx, y2, ch, col, 1, scale)
        cx += widths.get(ch, 4) * scale + gap
        idx += 1


def _info_box(frame):
    """Controls info box — bigger text, tighter box, no extra lines."""
    lines = [
        ("CONTROLS", 7),
        ("Player 1 (Blue)  W/S/A/D", 12),
        ("Player 2 (Red)   Arrows", 8),
    ]

    # Pyxel text is 4px per char wide, 6px tall
    char_w = 4
    line_h = 12
    padding_x = 16
    padding_y = 10

    # Find widest line
    max_text_w = max(len(ln[0]) * char_w for ln in lines)
    box_w = max_text_w + padding_x * 2
    box_h = len(lines) * line_h + padding_y * 2

    bx = (W - box_w) // 2
    by = 280

    rect(bx, by, box_w, box_h, 0)
    rectb(bx, by, box_w, box_h, 7)

    for i, (ln, col) in enumerate(lines):
        tx = bx + (box_w - len(ln) * char_w) // 2
        ty = by + padding_y + i * line_h
        text(tx, ty, ln, col)

    # Blinking start prompt below box
    if (frame // 20) % 2 == 0:
        prompt = "Press SPACE to start"
        tx = bx + (box_w - len(prompt) * char_w) // 2
        text(tx, by + box_h + 8, prompt, 7)


def draw_title_art(frame):
    cls(12)
    _sky()
    _sun()
    _clouds(frame)
    _ground()
    _mountains()
    _road_and_barriers()
    _exhaust_smoke(frame)
    _cars()
    _border()
    _title_text()
    _info_box(frame)