import pygame
import sys
import time

# --- 初始化 Pygame ---
pygame.init()

# --- 常量定义 ---
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
FPS = 60

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (220, 220, 220)
DARK_GRAY = (50, 50, 50)
BLUE = (70, 130, 180)
GREEN = (50, 205, 50)
ORANGE = (255, 140, 0)

# 设置屏幕
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Pygame 高精度秒表")
clock = pygame.time.Clock()

# 字体设置
font_time = pygame.font.SysFont("Consolas", 90, bold=True) # 等宽字体防止数字跳动
font_lap = pygame.font.SysFont("Consolas", 24)
font_ui = pygame.font.SysFont("Arial", 20)

class Stopwatch:
    def __init__(self):
        self.start_time = 0
        self.elapsed_time = 0 # 累计经过的时间（秒，浮点数）
        self.is_running = False
        self.laps = [] # 存储计圈时间

    def start(self):
        if not self.is_running:
            self.start_time = time.perf_counter() - self.elapsed_time
            self.is_running = True

    def stop(self):
        if self.is_running:
            self.elapsed_time = time.perf_counter() - self.start_time
            self.is_running = False

    def reset(self):
        self.is_running = False
        self.elapsed_time = 0
        self.start_time = 0
        self.laps = []

    def lap(self):
        if self.is_running:
            current_total = time.perf_counter() - self.start_time
            # 计算上一圈到这一圈的时间差
            if len(self.laps) == 0:
                lap_time = current_total
            else:
                last_lap_total = self.laps[-1]
                lap_time = current_total - last_lap_total
            
            self.laps.append(current_total)
            return lap_time, current_total
        return None, None

    def get_current_time(self):
        if self.is_running:
            return time.perf_counter() - self.start_time
        return self.elapsed_time

def format_time(seconds):
    """将秒数转换为 MM:SS:ms 格式"""
    mins = int(seconds // 60)
    secs = int(seconds % 60)
    # 取小数点后两位作为毫秒显示 (实际上显示的是厘秒，为了美观)
    ms = int((seconds % 1) * 100) 
    return f"{mins:02d}:{secs:02d}:{ms:02d}"

def main():
    stopwatch = Stopwatch()
    
    # 用于控制计圈列表的滚动
    lap_scroll_offset = 0
    
    running = True
    while running:
        # 1. 事件处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    running = False
                
                elif event.key == pygame.K_SPACE:
                    if stopwatch.is_running:
                        stopwatch.stop()
                    else:
                        stopwatch.start()
                
                elif event.key == pygame.K_r:
                    stopwatch.reset()
                    lap_scroll_offset = 0
                
                elif event.key == pygame.K_l:
                    if stopwatch.is_running:
                        lap, total = stopwatch.lap()
                        # 如果计圈太多，自动向下滚动视图（简单逻辑）
                        if len(stopwatch.laps) > 15:
                            lap_scroll_offset += 30

        # 2. 获取当前时间用于显示
        current_total = stopwatch.get_current_time()
        time_string = format_time(current_total)

        # 3. 绘图渲染
        screen.fill(WHITE)

        # --- 绘制主时间 ---
        # 根据状态改变颜色
        color = BLACK if stopwatch.is_running else DARK_GRAY
        if len(stopwatch.laps) > 0 and not stopwatch.is_running:
            color = BLUE # 暂停且有过计圈时变蓝
            
        text_surface = font_time.render(time_string, True, color)
        text_rect = text_surface.get_rect(center=(SCREEN_WIDTH // 2, 150))
        screen.blit(text_surface, text_rect)

        # --- 绘制状态指示 ---
        status_text = "RUNNING" if stopwatch.is_running else ("PAUSED" if stopwatch.elapsed_time > 0 else "READY")
        status_color = GREEN if stopwatch.is_running else ORANGE
        status_surf = font_ui.render(status_text, True, status_color)
        status_rect = status_surf.get_rect(center=(SCREEN_WIDTH // 2, 210))
        screen.blit(status_surf, status_rect)

        # --- 绘制计圈列表 (Laps) ---
        lap_title = font_ui.render("Laps (Press 'L' to Lap)", True, DARK_GRAY)
        screen.blit(lap_title, (SCREEN_WIDTH // 2 - 100, 260))
        
        # 绘制背景框
        list_y_start = 290
        list_height = 280
        pygame.draw.rect(screen, GRAY, (150, list_y_start, 500, list_height), border_radius=5)
        pygame.draw.rect(screen, BLACK, (150, list_y_start, 500, list_height), 2, border_radius=5)

        # 渲染具体的圈数
        # 只显示最近的 10-12 条，避免溢出
        visible_laps = stopwatch.laps[::-1] # 反转，最新的在上面
        
        for i, total_time in enumerate(visible_laps):
            if i >= 12: break # 最多显示12行
            
            # 计算单圈时间
            if i == 0:
                single_lap = total_time
            else:
                # 注意列表是反转的，所以索引要对应好
                # visible_laps[0] 是最新的一圈 (总时间 T_n)
                # visible_laps[1] 是上一圈 (总时间 T_n-1)
                single_lap = visible_laps[i] - visible_laps[i+1] if i+1 < len(visible_laps) else total_time
            
            lap_num = len(stopwatch.laps) - i
            row_y = list_y_start + 10 + (i * 22) - lap_scroll_offset
            
            # 只绘制在可视区域内的
            if list_y_start <= row_y < list_y_start + list_height:
                text_lap_num = font_lap.render(f"Lap {lap_num}", True, BLACK)
                text_single = font_lap.render(format_time(single_lap), True, BLUE)
                text_total = font_lap.render(format_time(total_time), True, DARK_GRAY)
                
                screen.blit(text_lap_num, (160, row_y))
                screen.blit(text_single, (350, row_y))
                screen.blit(text_total, (550, row_y))

        # --- 绘制操作提示 ---
        hints = [
            "[SPACE] 开始/暂停",
            "[R] 重置",
            "[L] 计圈 (Lap)",
            "[ESC] 退出"
        ]
        for i, hint in enumerate(hints):
            h_surf = font_ui.render(hint, True, GRAY)
            screen.blit(h_surf, (20, 550 + i * 25))

        pygame.display.flip()
        clock.tick(FPS)

    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()