import pygame
import math
import random
import sys

pygame.init()

# Constants
WIDTH, HEIGHT = 1000, 600
FPS = 60
BLIP_FADE_TIME = 4000  # milliseconds

# Init
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Polished Submarine Simulator")
clock = pygame.time.Clock()

# Colors
BLACK = (10, 10, 20)
DARK_GRAY = (40, 40, 60)
GRAY = (100, 100, 120)
LIGHT_GRAY = (160, 160, 180)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 100, 100)
YELLOW = (255, 255, 0)
BLUE = (10, 40, 80)
CYAN = (0, 255, 255)
SONAR_BLIP = (0, 255, 180)

# Fonts
font = pygame.font.SysFont("consolas", 14)

# Submarine state
sub_x = 500
sub_depth = 100.0
speed = 0.0
heading = 0.0

# Terrain
terrain_width = 5000
seafloor = []
def generate_seafloor():
    y = 300
    for _ in range(terrain_width):
        y += random.uniform(-20, 20)
        y = max(100, min(500, y))
        seafloor.append(y)
generate_seafloor()

# Sonar system
sonar_angle = 0
sonar_radius = 120
sonar_center = (WIDTH - 180, HEIGHT - 180)
sonar_speed = 90
blips = []
sonar_mode = "active"  # can be 'active' or 'passive'

# Player system
interior_rect = pygame.Rect(50, 50, 600, 200)
pilot_seat = pygame.Rect(90, 210, 30, 30)
player = pygame.Rect(150, 210, 20, 40)
player_vel = 100
sitting = False

# Personal stats
oxygen = 100.0
stamina = 100.0
health = 100.0
room_sealed = True

# Draw gauges
def draw_gauge(x, y, radius, label, value, min_val, max_val, unit, color):
    pygame.draw.circle(screen, GRAY, (x, y), radius)
    pygame.draw.circle(screen, BLUE, (x, y), radius - 6)
    for i in range(11):
        angle = math.radians(135 - i * 27)
        dx = math.cos(angle) * (radius - 10)
        dy = math.sin(angle) * (radius - 10)
        pygame.draw.line(screen, WHITE, (x + int(dx), y + int(dy)), (x + int(dx / 2), y + int(dy / 2)), 2)
    pct = (value - min_val) / (max_val - min_val)
    angle = math.radians(135 - pct * 270)
    dx = math.cos(angle) * (radius - 15)
    dy = math.sin(angle) * (radius - 15)
    pygame.draw.line(screen, color, (x, y), (x + int(dx), y + int(dy)), 4)
    screen.blit(font.render(label, True, WHITE), (x - 25, y - radius + 5))
    screen.blit(font.render(f"{value:.0f} {unit}", True, WHITE), (x - 30, y + radius - 20))

# Main loop
running = True
while running:
    dt = clock.tick(FPS) / 1000.0
    now = pygame.time.get_ticks()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_e and not sitting and player.colliderect(pilot_seat):
                sitting = True
                player.topleft = pilot_seat.topleft
            elif event.key == pygame.K_ESCAPE and sitting:
                sitting = False
            elif event.key == pygame.K_TAB:
                sonar_mode = "passive" if sonar_mode == "active" else "active"

    keys = pygame.key.get_pressed()

    if not sitting:
        if keys[pygame.K_a] or keys[pygame.K_LEFT]: player.x -= int(player_vel * dt)
        if keys[pygame.K_d] or keys[pygame.K_RIGHT]: player.x += int(player_vel * dt)
        player.x = max(interior_rect.left, min(interior_rect.right - player.width, player.x))
        if not room_sealed:
            oxygen = max(0, oxygen - 10 * dt)
    else:
        if keys[pygame.K_w]: speed += 20 * dt
        if keys[pygame.K_s]: speed -= 20 * dt
        if keys[pygame.K_q]: heading -= 90 * dt
        if keys[pygame.K_e]: heading += 90 * dt
        if keys[pygame.K_r]: sub_depth -= 50 * dt
        if keys[pygame.K_f]: sub_depth += 50 * dt

    # Clamp values
    speed = max(0, min(speed, 30))
    sub_depth = max(0, min(sub_depth, 500))
    heading %= 360
    sub_x += math.cos(math.radians(heading)) * speed * dt

    # Sonar logic
    sonar_angle += sonar_speed * dt
    sonar_angle %= 360
    sweep_radians = math.radians(sonar_angle)
    dx = math.cos(sweep_radians)
    dy = math.sin(sweep_radians)
    if sonar_mode == "active":
        for i in range(20, sonar_radius):
            ray_x = sub_x + dx * i
            ray_y = sub_depth + dy * i
            if 0 <= int(ray_x) < len(seafloor):
                if ray_y >= seafloor[int(ray_x)]:
                    blips.append((sonar_angle, i, now))
                    break

    elif sonar_mode == "passive":
        for _ in range(2):
            angle = random.uniform(0, 360)
            distance = random.randint(30, sonar_radius)
            rad = math.radians(angle)
            px = sub_x + math.cos(rad) * distance
            py = sub_depth + math.sin(rad) * distance
            if 0 <= int(px) < len(seafloor) and py >= seafloor[int(px)]:
                blips.append((angle, distance, now))

    # Clean expired blips
    blips = [(a, d, t) for a, d, t in blips if now - t < BLIP_FADE_TIME]

    # Draw everything
    screen.fill(BLACK)
    pygame.draw.rect(screen, DARK_GRAY, interior_rect, border_radius=15)
    pygame.draw.rect(screen, LIGHT_GRAY, pilot_seat, border_radius=5)
    pygame.draw.rect(screen, (220, 220, 255), player)
    pygame.draw.line(screen, GRAY, (interior_rect.left + 10, interior_rect.bottom), (interior_rect.right - 10, interior_rect.bottom), 2)
    pygame.draw.circle(screen, GRAY, (pilot_seat.centerx, pilot_seat.top - 10), 4)

    # UI overlays
    if sitting:
        draw_gauge(100, HEIGHT - 120, 60, "Depth", sub_depth, 0, 500, "m", GREEN)
        draw_gauge(220, HEIGHT - 120, 60, "Speed", speed, 0, 30, "kt", RED)
        draw_gauge(340, HEIGHT - 120, 60, "Heading", heading, 0, 360, "°", YELLOW)
    else:
        draw_gauge(100, HEIGHT - 120, 60, "O₂", oxygen, 0, 100, "%", GREEN)
        draw_gauge(220, HEIGHT - 120, 60, "Stamina", stamina, 0, 100, "%", YELLOW)
        draw_gauge(340, HEIGHT - 120, 60, "Health", health, 0, 100, "%", RED)

    # Sonar
    pygame.draw.circle(screen, (0, 60, 100), sonar_center, sonar_radius)
    pygame.draw.circle(screen, CYAN, sonar_center, sonar_radius, 2)
    for angle, dist, timestamp in blips:
        fade = max(0, min(255, 255 - ((now - timestamp) / BLIP_FADE_TIME) * 255))
        rad = math.radians(angle)
        bx = sonar_center[0] + math.cos(rad) * dist
        by = sonar_center[1] + math.sin(rad) * dist
        surf = pygame.Surface((4, 4), pygame.SRCALPHA)
        pygame.draw.circle(surf, SONAR_BLIP + (int(fade),), (2, 2), 2)
        screen.blit(surf, (bx - 2, by - 2))
    end_x = sonar_center[0] + math.cos(sweep_radians) * sonar_radius
    end_y = sonar_center[1] + math.sin(sweep_radians) * sonar_radius
    if sonar_mode == "active":
        pygame.draw.line(screen, CYAN, sonar_center, (end_x, end_y), 2)
        pygame.draw.circle(screen, CYAN, sonar_center, 3)

    else:
        pygame.draw.circle(screen, CYAN, sonar_center, 1)
    mode_text = font.render(f"Sonar: {sonar_mode.upper()} (TAB)", True, WHITE)
    screen.blit(mode_text, (sonar_center[0] - 60, sonar_center[1] + sonar_radius + 10))

    # Prompts
    if not sitting and player.colliderect(pilot_seat):
        msg = font.render("Press E to sit", True, WHITE)
        screen.blit(msg, (pilot_seat.x, pilot_seat.y - 20))
    elif sitting:
        msg = font.render("Press ESC to stand", True, WHITE)
        screen.blit(msg, (pilot_seat.x, pilot_seat.y - 20))

    pygame.display.flip()

pygame.quit()
sys.exit()