import pygame
import random
import sys
import os

# Initialize Pygame
pygame.init()

# Game Constants
SCREEN_WIDTH = 400
SCREEN_HEIGHT = 600
BLOCK_SIZE = 30
COLS = 10
ROWS = 20
PREVIEW_SIZE = 4

# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (128, 128, 128)
CYAN = (0, 255, 255)
BLUE = (0, 0, 255)
ORANGE = (255, 165, 0)
YELLOW = (255, 255, 0)
GREEN = (0, 255, 0)
PURPLE = (128, 0, 128)
RED = (255, 0, 0)

# Tetromino shapes
SHAPES = {
    'I': [[1, 1, 1, 1]],
    'O': [[1, 1],
          [1, 1]],
    'T': [[0, 1, 0],
          [1, 1, 1]],
    'S': [[0, 1, 1],
          [1, 1, 0]],
    'Z': [[1, 1, 0],
          [0, 1, 1]],
    'L': [[1, 0, 0],
          [1, 1, 1]],
    'J': [[0, 0, 1],
          [1, 1, 1]]
}

SHAPE_COLORS = {
    'I': CYAN,
    'O': YELLOW,
    'T': PURPLE,
    'S': GREEN,
    'Z': RED,
    'L': ORANGE,
    'J': BLUE
}

class Tetris:
    def __init__(self):
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        pygame.display.set_caption("俄罗斯方块")
        self.clock = pygame.time.Clock()
        
        # Setup fonts with Chinese support
        self.setup_fonts()
        
        self.reset_game()
    
    def setup_fonts(self):
        """Setup fonts with Chinese support"""
        # Try to use system fonts that support Chinese
        font_names = []
        
        # Windows fonts
        font_names.extend([
            'Microsoft YaHei',
            'SimHei',
            'SimSun',
            'KaiTi',
            'FangSong'
        ])
        
        # macOS fonts
        font_names.extend([
            'PingFang SC',
            'STHeiti',
            'Hiragino Sans GB'
        ])
        
        # Linux fonts
        font_names.extend([
            'WenQuanYi Micro Hei',
            'Noto Sans CJK SC'
        ])
        
        # Try each font
        font_loaded = False
        for font_name in font_names:
            try:
                # Test if font supports Chinese
                test_font = pygame.font.SysFont(font_name, 24)
                test_surface = test_font.render("测试", True, WHITE)
                if test_surface.get_width() > 20:  # Chinese character rendered successfully
                    self.font = pygame.font.SysFont(font_name, 32)
                    self.small_font = pygame.font.SysFont(font_name, 24)
                    self.big_font = pygame.font.SysFont(font_name, 48)
                    font_loaded = True
                    break
            except:
                continue
        
        # Fallback to default fonts
        if not font_loaded:
            self.font = pygame.font.Font(None, 32)
            self.small_font = pygame.font.Font(None, 24)
            self.big_font = pygame.font.Font(None, 48)
    
    def reset_game(self):
        """Reset game state"""
        self.board = [[BLACK] * COLS for _ in range(ROWS)]
        self.score = 0
        self.level = 1
        self.lines_cleared = 0
        self.game_over = False
        self.paused = False
        self.fall_time = 0
        self.fall_speed = 500
        
        self.current_piece = self.new_piece()
        self.next_piece = self.new_piece()
        self.hold_piece = None
        self.can_hold = True
        
    def new_piece(self):
        """Create new piece"""
        shape_name = random.choice(list(SHAPES.keys()))
        shape = [row[:] for row in SHAPES[shape_name]]
        color = SHAPE_COLORS[shape_name]
        
        x = COLS // 2 - len(shape[0]) // 2
        y = 0
        
        return {
            'shape': shape,
            'color': color,
            'name': shape_name,
            'x': x,
            'y': y
        }
    
    def rotate_piece(self):
        """Rotate piece clockwise"""
        shape = self.current_piece['shape']
        rotated = list(zip(*shape[::-1]))
        rotated = [list(row) for row in rotated]
        return rotated
    
    def valid_position(self, shape, offset_x, offset_y):
        """Check if position is valid"""
        for y, row in enumerate(shape):
            for x, cell in enumerate(row):
                if cell:
                    board_x = self.current_piece['x'] + x + offset_x
                    board_y = self.current_piece['y'] + y + offset_y
                    
                    if board_x < 0 or board_x >= COLS or board_y >= ROWS:
                        return False
                    
                    if board_y >= 0 and self.board[board_y][board_x] != BLACK:
                        return False
        return True
    
    def lock_piece(self):
        """Lock piece to board"""
        for y, row in enumerate(self.current_piece['shape']):
            for x, cell in enumerate(row):
                if cell:
                    board_x = self.current_piece['x'] + x
                    board_y = self.current_piece['y'] + y
                    if board_y >= 0:
                        self.board[board_y][board_x] = self.current_piece['color']
        
        self.clear_lines()
        
        self.current_piece = self.next_piece
        self.next_piece = self.new_piece()
        self.can_hold = True
        
        if not self.valid_position(self.current_piece['shape'], 0, 0):
            self.game_over = True
    
    def clear_lines(self):
        """Clear completed lines and update score"""
        lines_removed = 0
        y = ROWS - 1
        while y >= 0:
            if all(self.board[y][x] != BLACK for x in range(COLS)):
                del self.board[y]
                self.board.insert(0, [BLACK] * COLS)
                lines_removed += 1
            else:
                y -= 1
        
        if lines_removed > 0:
            self.lines_cleared += lines_removed
            scores = [0, 100, 300, 500, 800]
            self.score += scores[lines_removed] * self.level
            
            self.level = 1 + self.lines_cleared // 10
            self.fall_speed = max(100, 500 - (self.level - 1) * 40)
    
    def move_piece(self, dx, dy):
        """Move current piece"""
        if self.game_over or self.paused:
            return False
        
        if self.valid_position(self.current_piece['shape'], dx, dy):
            self.current_piece['x'] += dx
            self.current_piece['y'] += dy
            return True
        return False
    
    def drop_piece(self):
        """Hard drop piece"""
        if self.game_over or self.paused:
            return
        
        while self.valid_position(self.current_piece['shape'], 0, 1):
            self.current_piece['y'] += 1
        self.lock_piece()
    
    def hold_piece_action(self):
        """Hold current piece"""
        if self.game_over or self.paused or not self.can_hold:
            return
        
        if self.hold_piece is None:
            self.hold_piece = self.current_piece
            self.current_piece = self.next_piece
            self.next_piece = self.new_piece()
        else:
            temp = self.current_piece
            self.current_piece = self.hold_piece
            self.hold_piece = temp
            
            self.current_piece['x'] = COLS // 2 - len(self.current_piece['shape'][0]) // 2
            self.current_piece['y'] = 0
        
        self.can_hold = False
    
    def draw_block(self, x, y, color, size=BLOCK_SIZE):
        """Draw a single block"""
        pygame.draw.rect(self.screen, color, (x, y, size - 1, size - 1))
        pygame.draw.rect(self.screen, (255, 255, 255), (x, y, size - 1, size - 1), 1)
    
    def draw_board(self):
        """Draw game board"""
        # Grid background
        for y in range(ROWS):
            for x in range(COLS):
                pygame.draw.rect(
                    self.screen,
                    (20, 20, 20),
                    (x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE),
                    1
                )
        
        # Fixed pieces
        for y in range(ROWS):
            for x in range(COLS):
                if self.board[y][x] != BLACK:
                    self.draw_block(
                        x * BLOCK_SIZE,
                        y * BLOCK_SIZE,
                        self.board[y][x]
                    )
        
        # Current piece
        if self.current_piece and not self.game_over:
            shape = self.current_piece['shape']
            for y, row in enumerate(shape):
                for x, cell in enumerate(row):
                    if cell:
                        board_x = (self.current_piece['x'] + x) * BLOCK_SIZE
                        board_y = (self.current_piece['y'] + y) * BLOCK_SIZE
                        if self.current_piece['y'] + y >= 0:
                            self.draw_block(board_x, board_y, self.current_piece['color'])
    
    def draw_preview(self, piece, x, y, size=BLOCK_SIZE * 4):
        """Draw piece preview"""
        shape = piece['shape']
        block_size = size // 4
        
        rows = len(shape)
        cols = len(shape[0])
        offset_x = (PREVIEW_SIZE - cols) * block_size // 2
        offset_y = (PREVIEW_SIZE - rows) * block_size // 2
        
        for row, row_data in enumerate(shape):
            for col, cell in enumerate(row_data):
                if cell:
                    pygame.draw.rect(
                        self.screen,
                        piece['color'],
                        (x + offset_x + col * block_size,
                         y + offset_y + row * block_size,
                         block_size - 1,
                         block_size - 1)
                    )
    
    def draw_ui(self):
        """Draw UI elements"""
        # Score
        score_label = self.font.render("分数:", True, WHITE)
        score_text = self.font.render(str(self.score), True, WHITE)
        self.screen.blit(score_label, (SCREEN_WIDTH - 150, 30))
        self.screen.blit(score_text, (SCREEN_WIDTH - 70, 30))
        
        # Level
        level_label = self.font.render("等级:", True, WHITE)
        level_text = self.font.render(str(self.level), True, WHITE)
        self.screen.blit(level_label, (SCREEN_WIDTH - 150, 70))
        self.screen.blit(level_text, (SCREEN_WIDTH - 70, 70))
        
        # Lines
        lines_label = self.font.render("消除:", True, WHITE)
        lines_text = self.font.render(str(self.lines_cleared), True, WHITE)
        self.screen.blit(lines_label, (SCREEN_WIDTH - 150, 110))
        self.screen.blit(lines_text, (SCREEN_WIDTH - 70, 110))
        
        # Next piece
        next_label = self.small_font.render("下一个:", True, WHITE)
        self.screen.blit(next_label, (SCREEN_WIDTH - 150, 160))
        self.draw_preview(self.next_piece, SCREEN_WIDTH - 120, 190)
        
        # Hold piece
        hold_label = self.small_font.render("保留:", True, WHITE)
        self.screen.blit(hold_label, (10, 10))
        if self.hold_piece:
            self.draw_preview(self.hold_piece, 40, 40)
        
        # Game Over
        if self.game_over:
            overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
            overlay.set_alpha(128)
            overlay.fill(BLACK)
            self.screen.blit(overlay, (0, 0))
            
            game_over_text = self.big_font.render("游戏结束!", True, RED)
            text_rect = game_over_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 30))
            self.screen.blit(game_over_text, text_rect)
            
            restart_text = self.small_font.render("按 R 重新开始", True, WHITE)
            restart_rect = restart_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 20))
            self.screen.blit(restart_text, restart_rect)
        
        # Paused
        if self.paused and not self.game_over:
            overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
            overlay.set_alpha(128)
            overlay.fill(BLACK)
            self.screen.blit(overlay, (0, 0))
            
            pause_text = self.big_font.render("暂停中", True, WHITE)
            text_rect = pause_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
            self.screen.blit(pause_text, text_rect)
        
        # Controls
        controls = [
            "← → 移动",
            "↑ 旋转",
            "↓ 加速下落",
            "空格 直接落底",
            "C 保留方块",
            "P 暂停/继续",
            "R 重新开始"
        ]
        y_pos = 490
        for control in controls:
            text = self.small_font.render(control, True, GRAY)
            self.screen.blit(text, (SCREEN_WIDTH - 150, y_pos))
            y_pos += 22
    
    def handle_events(self):
        """Handle input events"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return False
            
            if event.type == pygame.KEYDOWN:
                if self.game_over:
                    if event.key == pygame.K_r:
                        self.reset_game()
                    continue
                
                if event.key == pygame.K_p:
                    self.paused = not self.paused
                    continue
                
                if self.paused:
                    continue
                
                if event.key == pygame.K_LEFT:
                    self.move_piece(-1, 0)
                elif event.key == pygame.K_RIGHT:
                    self.move_piece(1, 0)
                elif event.key == pygame.K_DOWN:
                    self.move_piece(0, 1)
                elif event.key == pygame.K_UP:
                    rotated = self.rotate_piece()
                    if self.valid_position(rotated, 0, 0):
                        self.current_piece['shape'] = rotated
                    elif self.valid_position(rotated, -1, 0):
                        self.current_piece['shape'] = rotated
                        self.current_piece['x'] -= 1
                    elif self.valid_position(rotated, 1, 0):
                        self.current_piece['shape'] = rotated
                        self.current_piece['x'] += 1
                elif event.key == pygame.K_SPACE:
                    self.drop_piece()
                elif event.key == pygame.K_c:
                    self.hold_piece_action()
                elif event.key == pygame.K_r:
                    self.reset_game()
        
        return True
    
    def update(self):
        """Update game state"""
        if self.game_over or self.paused:
            return
        
        self.fall_time += self.clock.get_rawtime()
        if self.fall_time >= self.fall_speed:
            if not self.move_piece(0, 1):
                self.lock_piece()
            self.fall_time = 0
    
    def draw(self):
        """Draw everything"""
        self.screen.fill(BLACK)
        self.draw_board()
        self.draw_ui()
        pygame.display.flip()
    
    def run(self):
        """Main game loop"""
        running = True
        while running:
            running = self.handle_events()
            self.update()
            self.draw()
            self.clock.tick(60)
        
        pygame.quit()
        sys.exit()

if __name__ == "__main__":
    game = Tetris()
    game.run()