import pygame
import math
import random
import os

pygame.init()
W, H = 1200, 700
screen = pygame.display.set_mode((W, H))
pygame.display.set_caption("Ultimate 2D Ship Navigation Simulator")
clock = pygame.time.Clock()
FPS = 60

# ===================== 颜色定义 =====================
OCEAN_DEEP = (10, 60, 130)
WAVE_LIGHT = (140, 210, 255)
FOAM_WHITE = (240, 250, 255)
SHIP_RED = (190, 25, 25)
SHIP_LIGHT = (255, 130, 130)
ROCK_GRAY = (55, 55, 55)
ROCK_DARK = (25, 25, 25)
LAND_SAND = (220, 200, 150)
LAND_GREEN = (60, 160, 40)
PORT_ZONE = (80, 220, 120, 100)
UI_WHITE = (255, 255, 255)
UI_BLACK = (0, 0, 0)
FLASH_WHITE = (255, 255, 255)
FOG_COLOR = (200, 220, 240)
LIGHT_RAY = (255, 240, 180)
BUOY_COLOR = (255, 160, 0)

# ===================== 船舶物理 =====================
world_x = 0.0
world_y = 0.0
ship_angle = 0.0
ship_tilt = 0.0
vel_x = 0.0
vel_y = 0.0
max_forward_speed = 9.0
max_reverse_speed = -4.0
thrust_power = 0.16
reverse_thrust = 0.09
water_drag = 0.042
base_turn_speed = 2.4
anchor_lock = False
auto_dock = False  # 自动停泊开关

# 风力系统 1~5级
wind_level = 2
wind_base_strength = [0.008, 0.016, 0.028, 0.045, 0.07]
wind_dir = random.uniform(0, 360)
wind_rad = math.radians(wind_dir)
wind_force_x = 0
wind_force_y = 0
wave_amplitude = 2.0

# 镜头偏移 + 风暴抖动
cam_x = 0.0
cam_y = 0.0
shake_offset_x = 0
shake_offset_y = 0

# 雾系统
fog_density = 0.0
fog_max_range = 620

# 海浪分层
far_waves = []
near_waves = []
for _ in range(400):
    wx = random.randint(-3000, 3000)
    wy = random.randint(-3000, 3000)
    size = random.randint(1, 3)
    phase = random.uniform(0, math.pi * 2)
    far_waves.append([wx, wy, size, phase])
for _ in range(200):
    wx = random.randint(-2000, 2000)
    wy = random.randint(-2000, 2000)
    size = random.randint(3, 6)
    phase = random.uniform(0, math.pi * 2)
    near_waves.append([wx, wy, size, phase])

# 礁石、岛屿、港口、灯塔、浮标
rocks = []
islands = []
ports = []
lighthouses = []
buoys = []

# 礁石
for _ in range(35):
    rx = random.randint(-2200, 2200)
    ry = random.randint(-2200, 2200)
    r_radius = random.randint(24, 72)
    rocks.append([rx, ry, r_radius])

# 岛屿+港口+灯塔
for _ in range(6):
    ix = random.randint(-1800, 1800)
    iy = random.randint(-1800, 1800)
    i_radius = random.randint(45, 110)
    islands.append([ix, iy, i_radius])
    # 港口
    port_rad = math.radians(random.uniform(0, 360))
    port_x = ix + math.sin(port_rad) * (i_radius + 60)
    port_y = iy - math.cos(port_rad) * (i_radius + 60)
    ports.append([port_x, port_y, 75])
    # 灯塔生成在岛屿边角
    lh_rad = math.radians(random.uniform(0, 360))
    lh_x = ix + math.sin(lh_rad) * (i_radius + 35)
    lh_y = iy - math.cos(lh_rad) * (i_radius + 35)
    lighthouses.append([lh_x, lh_y])

# 航道浮标
for _ in range(12):
    bx = random.randint(-2500, 2500)
    by = random.randint(-2500, 2500)
    buoys.append([bx, by])

# 船尾浪花粒子
foam_particles = []
# 航行轨迹点
ship_trace = []
max_trace_len = 800

# 撞击闪光特效
flash_alpha = 0

# 字体兜底兼容
try:
    font = pygame.font.SysFont("msyh", 22)
    font_small = pygame.font.SysFont("msyh", 16)
except:
    font = pygame.font.Font(None, 22)
    font_small = pygame.font.Font(None, 16)

# ===================== 工具函数 =====================
def draw_ship(surface, cx, cy, angle, tilt):
    hull_points = [
        (0, -24), (-16, 18), (-9, 13),
        (0, 15), (9, 13), (16, 18)
    ]
    rad = math.radians(angle)
    tilt_rad = math.radians(tilt)
    cos_a, sin_a = math.cos(rad), math.sin(rad)
    cos_t, sin_t = math.cos(tilt_rad), math.sin(tilt_rad)
    final_pts = []
    for px, py in hull_points:
        tx = px * cos_t - py * sin_t
        ty = px * sin_t + py * cos_t
        rx = tx * cos_a - ty * sin_a + cx
        ry = tx * sin_a + ty * cos_a + cy
        final_pts.append((rx, ry))
    pygame.draw.polygon(surface, SHIP_RED, final_pts)
    pygame.draw.polygon(surface, SHIP_LIGHT, final_pts, 3)

def circle_hit(sx, sy, rx, ry, r):
    dist = math.hypot(sx - rx, sy - ry)
    return dist < r + 20

def point_in_circle(px, py, cx, cy, cr):
    return math.hypot(px - cx, py - cy) < cr

def spawn_foam(ship_world_x, ship_world_y, ship_ang, spd):
    if abs(spd) < 0.3:
        return
    rad = math.radians(ship_ang + 180)
    back_x = ship_world_x + math.sin(rad) * 18
    back_y = ship_world_y - math.cos(rad) * 18
    foam_particles.append({
        "x": back_x, "y": back_y, "life": 60,
        "vx": random.uniform(-0.25, 0.25),
        "vy": random.uniform(-0.25, 0.25),
        "size": random.randint(2, 5)
    })

def draw_compass(surface, x, y, heading):
    radius = 50
    pygame.draw.circle(surface, UI_BLACK, (x, y), radius, 3)
    pygame.draw.circle(surface, (30, 80, 160), (x, y), radius - 3)
    rad = math.radians(heading)
    px = x + math.sin(rad) * (radius - 8)
    py = y - math.cos(rad) * (radius - 8)
    pygame.draw.line(surface, (255, 30, 30), (x, y), (px, py), 4)
    npx = x + math.sin(math.radians(0)) * (radius - 12)
    npy = y - math.cos(math.radians(0)) * (radius - 12)
    pygame.draw.circle(surface, UI_WHITE, (int(npx), int(npy)), 4)

def draw_radar(surface, cx, cy, radar_range=600, radar_size=130):
    radar_surf = pygame.Surface((radar_size, radar_size), pygame.SRCALPHA)
    r = radar_size // 2
    pygame.draw.circle(radar_surf, (0, 40, 80, 180), (r, r), r)
    pygame.draw.circle(radar_surf, UI_WHITE, (r, r), r, 2)
    for i in range(1,4):
        pygame.draw.circle(radar_surf, (80,150,220,100), (r,r), int(r*i/4),1)
    scale = r / radar_range
    for (rx, ry, rr) in rocks:
        dx = rx - world_x
        dy = ry - world_y
        dist = math.hypot(dx, dy)
        if dist < radar_range:
            px = r + dx * scale
            py = r + dy * scale
            pygame.draw.circle(radar_surf, (120,120,120), (int(px), int(py)), 3)
    for (ix, iy, ir) in islands:
        dx = ix - world_x
        dy = iy - world_y
        dist = math.hypot(dx, dy)
        if dist < radar_range:
            px = r + dx * scale
            py = r + dy * scale
            pygame.draw.circle(radar_surf, LAND_GREEN, (int(px), int(py)),5)
    for (bx, by) in buoys:
        dx = bx - world_x
        dy = by - world_y
        dist = math.hypot(dx, dy)
        if dist < radar_range:
            px = r + dx * scale
            py = r + dy * scale
            pygame.draw.circle(radar_surf, BUOY_COLOR, (int(px), int(py)), 2)
    pygame.draw.circle(radar_surf, SHIP_RED, (r, r), 4)
    rad = math.radians(ship_angle)
    end_x = r + math.sin(rad) * (r-10)
    end_y = r - math.cos(rad) * (r-10)
    pygame.draw.line(radar_surf, SHIP_LIGHT, (r,r), (end_x, end_y),2)
    surface.blit(radar_surf, (cx - r, cy - r))

def draw_trace_line(surface):
    if len(ship_trace) < 2:
        return
    screen_points = []
    for (tx, ty) in ship_trace:
        sx = tx - cam_x + shake_offset_x
        sy = ty - cam_y + shake_offset_y
        screen_points.append((sx, sy))
    pygame.draw.lines(surface, (255,220,60), False, screen_points, 2)

def export_trace_file():
    with open("trace_log.txt", "w", encoding="utf-8") as f:
        f.write("Ship Track Coordinate Log\n")
        f.write("X\tY\n")
        for x, y in ship_trace:
            f.write(f"{x:.2f}\t{y:.2f}\n")

def draw_fog_overlay(surface, density):
    if density <= 0:
        return
    fog_surf = pygame.Surface((W, H), pygame.SRCALPHA)
    alpha = int(density * 160)
    fog_surf.fill((*FOG_COLOR, alpha))
    # 中心淡化，近处看得清
    mask = pygame.Surface((W, H), pygame.SRCALPHA)
    for r in range(fog_max_range, 0, -4):
        a = int(255 - r / fog_max_range * 255)
        pygame.draw.circle(mask, (0,0,0,a), (W//2, H//2), r)
    fog_surf.blit(mask, (0,0), special_flags=pygame.BLEND_RGBA_SUB)
    surface.blit(fog_surf, (0,0))

# ===================== 主循环 =====================
running = True
while running:
    dt = clock.tick(FPS) / 1000.0
    keys = pygame.key.get_pressed()
    t = pygame.time.get_ticks() / 1000
    screen.fill(OCEAN_DEEP)

    # 风暴屏幕抖动
    shake_strength = wind_level * 2.2
    shake_offset_x = random.uniform(-shake_strength, shake_strength)
    shake_offset_y = random.uniform(-shake_strength, shake_strength)

    # 撞击闪光叠加层
    if flash_alpha > 0:
        flash_surf = pygame.Surface((W,H), pygame.SRCALPHA)
        flash_surf.fill((*FLASH_WHITE, int(flash_alpha)))
        screen.blit(flash_surf, (0,0))
        flash_alpha -= 8

    # 事件处理
    for ev in pygame.event.get():
        if ev.type == pygame.QUIT:
            running = False
        if ev.type == pygame.KEYDOWN:
            if ev.key == pygame.K_SPACE:
                anchor_lock = not anchor_lock
            # 风力等级 1~5
            if pygame.K_1 <= ev.key <= pygame.K_5:
                wind_level = ev.key - pygame.K_1 + 1
                wind_dir = random.uniform(0, 360)
                wind_rad = math.radians(wind_dir)
            # 清空航迹
            if ev.key == pygame.K_c:
                ship_trace.clear()
            # 导出航迹文件 O
            if ev.key == pygame.K_o:
                export_trace_file()
            # 一键自动停泊
            if ev.key == pygame.K_d:
                auto_dock = not auto_dock

    # 更新风力、海浪、雾浓度
    wind_str = wind_base_strength[wind_level - 1]
    wind_force_x = math.sin(wind_rad) * wind_str
    wind_force_y = -math.cos(wind_rad) * wind_str
    wave_amplitude = 1.2 + wind_level * 1.6
    # 雾：4、5级起雾
    fog_density = max(0, wind_level - 3) / 2

    # 判断是否在港口区域
    in_port = False
    for (px, py, pr) in ports:
        if point_in_circle(world_x, world_y, px, py, pr):
            in_port = True
            break

    # 抛锚/自动停泊逻辑
    if anchor_lock:
        vel_x *= 0.0
        vel_y *= 0.0
        ship_tilt *= 0.8
    else:
        current_speed = math.hypot(vel_x, vel_y)
        turn_mod = max(0.35, 1 - current_speed / max_forward_speed * 0.65)
        real_turn = base_turn_speed * turn_mod

        # 转向
        if keys[pygame.K_a] or keys[pygame.K_LEFT]:
            ship_angle += real_turn
            ship_tilt = min(ship_tilt + 1.2, 14)
        elif keys[pygame.K_d] or keys[pygame.K_RIGHT]:
            ship_angle -= real_turn
            ship_tilt = max(ship_tilt - 1.2, -14)
        else:
            ship_tilt *= 0.92

        # 推力
        thrust_x, thrust_y = 0.0, 0.0
        ang_rad = math.radians(ship_angle)
        if keys[pygame.K_w] or keys[pygame.K_UP]:
            thrust_x = math.sin(ang_rad) * thrust_power
            thrust_y = -math.cos(ang_rad) * thrust_power
        if keys[pygame.K_s] or keys[pygame.K_DOWN]:
            thrust_x = -math.sin(ang_rad) * reverse_thrust
            thrust_y = math.cos(ang_rad) * reverse_thrust

        # 港口减速奖励
        port_drag_mod = 1.0
        if in_port:
            port_drag_mod = 0.65
        # 自动停泊持续减速
        if auto_dock and in_port:
            port_drag_mod = 0.22

        # 风力+推力叠加
        vel_x += thrust_x + wind_force_x
        vel_y += thrust_y + wind_force_y
        vel_x *= (1 - water_drag * port_drag_mod)
        vel_y *= (1 - water_drag * port_drag_mod)

        # 限速
        spd = math.hypot(vel_x, vel_y)
        if spd > max_forward_speed:
            scale = max_forward_speed / spd
            vel_x *= scale
            vel_y *= scale

        # 碰撞检测
        next_wx = world_x + vel_x
        next_wy = world_y + vel_y
        crash = False
        for (rx, ry, rr) in rocks:
            if circle_hit(next_wx, next_wy, rx, ry, rr):
                crash = True
                vel_x *= -0.42
                vel_y *= -0.42
                flash_alpha = 120
                break
        for (ix, iy, ir) in islands:
            if circle_hit(next_wx, next_wy, ix, iy, ir):
                crash = True
                vel_x *= -0.35
                vel_y *= -0.35
                flash_alpha = 90
                break
        if not crash:
            world_x = next_wx
            world_y = next_wy

        # 记录航迹
        ship_trace.append((world_x, world_y))
        if len(ship_trace) > max_trace_len:
            ship_trace.pop(0)

        spawn_foam(world_x, world_y, ship_angle, spd)

    # 镜头跟随+风暴抖动偏移
    cam_x = world_x - W / 2
    cam_y = world_y - H / 2

    # 绘制海浪
    for w in far_waves:
        wx, wy, sz, phase = w
        dx = wx - cam_x + shake_offset_x % 2400
        dy = wy - cam_y + shake_offset_y % 2400
        wave_off = math.sin(t * 0.7 + phase) * wave_amplitude
        pygame.draw.circle(screen, WAVE_LIGHT, (int(dx), int(dy + wave_off)), sz)
    for w in near_waves:
        wx, wy, sz, phase = w
        dx = wx - cam_x + shake_offset_x % 2400
        dy = wy - cam_y + shake_offset_y % 2400
        wave_off = math.sin(t * 1.3 + phase) * wave_amplitude * 1.4
        pygame.draw.circle(screen, WAVE_LIGHT, (int(dx), int(dy + wave_off)), sz)

    # 港口停靠区
    for (px, py, pr) in ports:
        draw_x = px - cam_x + shake_offset_x
        draw_y = py - cam_y + shake_offset_y
        port_surf = pygame.Surface((pr*2, pr*2), pygame.SRCALPHA)
        pygame.draw.circle(port_surf, PORT_ZONE, (pr, pr), pr)
        screen.blit(port_surf, (draw_x - pr, draw_y - pr))

    # 岛屿陆地
    for (ix, iy, ir) in islands:
        draw_x = ix - cam_x + shake_offset_x
        draw_y = iy - cam_y + shake_offset_y
        pygame.draw.circle(screen, LAND_SAND, (int(draw_x), int(draw_y)), ir)
        pygame.draw.circle(screen, LAND_GREEN, (int(draw_x), int(draw_y)), ir - ir*0.35)

    # 礁石
    for (rx, ry, rr) in rocks:
        draw_x = rx - cam_x + shake_offset_x
        draw_y = ry - cam_y + shake_offset_y
        pygame.draw.circle(screen, ROCK_GRAY, (int(draw_x), int(draw_y)), rr)
        pygame.draw.circle(screen, ROCK_DARK, (int(draw_x), int(draw_y)), rr - 11)

    # 航道浮标
    for (bx, by) in buoys:
        dx = bx - cam_x + shake_offset_x
        dy = by - cam_y + shake_offset_y
        pygame.draw.circle(screen, BUOY_COLOR, (int(dx), int(dy)), 7)
        pygame.draw.circle(screen, UI_WHITE, (int(dx), int(dy)), 3)

    # 灯塔+旋转光束
    light_ang = t * 35
    for (lx, ly) in lighthouses:
        dx = lx - cam_x + shake_offset_x
        dy = ly - cam_y + shake_offset_y
        pygame.draw.rect(screen, (40,40,40), [dx-6, dy-22,12,24])
        pygame.draw.circle(screen, LIGHT_RAY, (int(dx), int(dy)-16), 6)
        # 旋转光束
        rad = math.radians(light_ang)
        ray_len = 220
        rx = dx + math.sin(rad) * ray_len
        ry = dy -16 - math.cos(rad) * ray_len
        ray_surf = pygame.Surface((W,H), pygame.SRCALPHA)
        pygame.draw.line(ray_surf, (*LIGHT_RAY, 70), (dx, dy-16), (rx, ry), 3)
        screen.blit(ray_surf, (0,0))

    # 航行轨迹线
    draw_trace_line(screen)

    # 浪花粒子
    new_foam = []
    for p in foam_particles:
        p["x"] += p["vx"]
        p["y"] += p["vy"]
        p["life"] -= 1
        if p["life"] > 0:
            fx = p["x"] - cam_x + shake_offset_x
            fy = p["y"] - cam_y + shake_offset_y
            alpha = int(255 * (p["life"] / 60))
            foam_surf = pygame.Surface((p["size"]*2, p["size"]*2), pygame.SRCALPHA)
            pygame.draw.circle(foam_surf, (*FOAM_WHITE, alpha), (p["size"], p["size"]), p["size"])
            screen.blit(foam_surf, (fx, fy))
            new_foam.append(p)
    foam_particles = new_foam

    # 中心船体
    draw_ship(screen, W//2 + shake_offset_x, H//2 + shake_offset_y, ship_angle, ship_tilt)

    # 雾气覆盖（最后绘制）
    draw_fog_overlay(screen, fog_density)

    # ========== UI文字 ==========
    speed_val = math.hypot(vel_x, vel_y)
    heading_val = ship_angle % 360
    anchor_text = "ANCHOR LOCKED" if anchor_lock else "ANCHOR OFF [SPACE]"
    dock_text = "AUTO DOCK ON" if auto_dock else "AUTO DOCK OFF [D]"
    wind_text = f"WIND Lv.{wind_level}  Wave:{wave_amplitude:.1f}  Fog:{fog_density:.1f}"
    port_text = "IN HARBOR SLOW DOWN!" if in_port else "Open Sea"
    txt_spd = font.render(f"Speed: {speed_val:.2f} kts", True, UI_WHITE)
    txt_head = font.render(f"Heading: {heading_val:.0f}°", True, UI_WHITE)
    txt_anchor = font.render(anchor_text, True, (255, 80, 80) if anchor_lock else UI_WHITE)
    txt_dock = font.render(dock_text, True, (100,255,180) if auto_dock else UI_WHITE)
    txt_wind = font.render(wind_text, True, (255,255,120))
    txt_port = font.render(port_text, True, (100,255,100) if in_port else (220,220,220))
    txt_tip = font_small.render("W=Fwd S=Rev A/D=Steer 1-5=Wind C=ClearTrace O=ExportLog D=AutoDock", True, UI_WHITE)
    screen.blit(txt_spd, (14, 10))
    screen.blit(txt_head, (14, 36))
    screen.blit(txt_anchor, (14, 62))
    screen.blit(txt_dock, (14, 88))
    screen.blit(txt_wind, (14, 114))
    screen.blit(txt_port, (14, 140))
    screen.blit(txt_tip, (14, H - 34))

    # 右下角罗盘 + 雷达小地图
    draw_compass(screen, W - 60, H - 210, heading_val)
    draw_radar(screen, W - 70, H - 80)

    pygame.display.update()

pygame.quit()