import pygame
import random

# Инициализация pygame
pygame.init()

# Цвета
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (70, 70, 70)
COLORS = [
    (0, 255, 255),  # I - голубой
    (0, 0, 255),    # J - синий
    (255, 165, 0),  # L - оранжевый
    (255, 255, 0),  # O - желтый
    (0, 255, 0),    # S - зеленый
    (128, 0, 128),  # T - фиолетовый
    (255, 0, 0)     # Z - красный
]

# Настройки игры
BLOCK_SIZE = 30
GRID_WIDTH = 10
GRID_HEIGHT = 20
SCREEN_WIDTH = BLOCK_SIZE * (GRID_WIDTH + 6)
SCREEN_HEIGHT = BLOCK_SIZE * GRID_HEIGHT
GAME_AREA_LEFT = BLOCK_SIZE

# Фигуры тетрамино
SHAPES = [
    [[1, 1, 1, 1]],  # I
    [[1, 0, 0], [1, 1, 1]],  # J
    [[0, 0, 1], [1, 1, 1]],  # L
    [[1, 1], [1, 1]],  # O
    [[0, 1, 1], [1, 1, 0]],  # S
    [[0, 1, 0], [1, 1, 1]],  # T
    [[1, 1, 0], [0, 1, 1]]   # Z
]

# Создание экрана
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Тетрис")

# Часы для управления FPS
clock = pygame.time.Clock()

class Tetris:
    def __init__(self):
        self.grid = [[0 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
        self.current_piece = self.new_piece()
        self.game_over = False
        self.score = 0
        self.level = 1
        self.fall_speed = 0.5  # секунды между падением на 1 клетку
        self.fall_time = 0
        
    def new_piece(self):
        # Выбираем случайную фигуру
        shape = random.choice(SHAPES)
        color = COLORS[SHAPES.index(shape)]
        
        # Начальная позиция (по центру сверху)
        x = GRID_WIDTH // 2 - len(shape[0]) // 2
        y = 0
        
        return {"shape": shape, "color": color, "x": x, "y": y}
    
    def valid_move(self, piece, x_offset=0, y_offset=0):
        for y, row in enumerate(piece["shape"]):
            for x, cell in enumerate(row):
                if cell:
                    new_x = piece["x"] + x + x_offset
                    new_y = piece["y"] + y + y_offset
                    
                    if (new_x < 0 or new_x >= GRID_WIDTH or 
                        new_y >= GRID_HEIGHT or 
                        (new_y >= 0 and self.grid[new_y][new_x])):
                        return False
        return True
    
    def rotate_piece(self):
        # Получаем текущую фигуру
        piece = self.current_piece
        # Транспонируем матрицу фигуры (поворот на 90 градусов)
        rotated = [[piece["shape"][y][x] for y in range(len(piece["shape"])-1, -1, -1)] 
                  for x in range(len(piece["shape"][0]))]
        
        old_shape = piece["shape"]
        piece["shape"] = rotated
        
        # Если после поворота фигура выходит за границы или пересекается с другими блоками,
        # отменяем поворот
        if not self.valid_move(piece):
            piece["shape"] = old_shape
    
    def lock_piece(self):
        piece = self.current_piece
        for y, row in enumerate(piece["shape"]):
            for x, cell in enumerate(row):
                if cell:
                    # Проверяем, не выходит ли фигура за верхнюю границу (игра окончена)
                    if piece["y"] + y < 0:
                        self.game_over = True
                    else:
                        self.grid[piece["y"] + y][piece["x"] + x] = piece["color"]
        
        # Проверяем заполненные линии
        self.clear_lines()
        # Создаем новую фигуру
        self.current_piece = self.new_piece()
        
        # Если новая фигура сразу не может разместиться, игра окончена
        if not self.valid_move(self.current_piece):
            self.game_over = True
    
    def clear_lines(self):
        lines_cleared = 0
        for y in range(GRID_HEIGHT):
            if all(self.grid[y]):
                lines_cleared += 1
                # Удаляем линию и сдвигаем все вышележащие линии вниз
                for y2 in range(y, 0, -1):
                    self.grid[y2] = self.grid[y2-1][:]
                self.grid[0] = [0 for _ in range(GRID_WIDTH)]
        
        # Обновляем счет
        if lines_cleared == 1:
            self.score += 100 * self.level
        elif lines_cleared == 2:
            self.score += 300 * self.level
        elif lines_cleared == 3:
            self.score += 500 * self.level
        elif lines_cleared == 4:
            self.score += 800 * self.level
        
        # Обновляем уровень (каждые 10 линий)
        self.level = 1 + self.score // 1000
        # Увеличиваем скорость (максимум 0.05 секунды между падениями)
        self.fall_speed = max(0.05, 0.5 - (self.level - 1) * 0.05)
    
    def update(self, delta_time):
        if self.game_over:
            return
        
        self.fall_time += delta_time
        
        # Автоматическое падение фигуры
        if self.fall_time >= self.fall_speed:
            self.fall_time = 0
            if self.valid_move(self.current_piece, 0, 1):
                self.current_piece["y"] += 1
            else:
                self.lock_piece()
    
    def draw(self):
        # Очищаем экран
        screen.fill(BLACK)
        
        # Рисуем игровую область
        pygame.draw.rect(screen, WHITE, (GAME_AREA_LEFT, 0, BLOCK_SIZE * GRID_WIDTH, SCREEN_HEIGHT), 1)
        
        # Рисуем сетку
        for x in range(GRID_WIDTH):
            for y in range(GRID_HEIGHT):
                pygame.draw.rect(screen, GRAY, 
                               (GAME_AREA_LEFT + x * BLOCK_SIZE, y * BLOCK_SIZE, 
                                BLOCK_SIZE, BLOCK_SIZE), 1)
        
        # Рисуем статичные блоки
        for y in range(GRID_HEIGHT):
            for x in range(GRID_WIDTH):
                if self.grid[y][x]:
                    pygame.draw.rect(screen, self.grid[y][x], 
                                   (GAME_AREA_LEFT + x * BLOCK_SIZE, y * BLOCK_SIZE, 
                                    BLOCK_SIZE, BLOCK_SIZE))
                    pygame.draw.rect(screen, WHITE, 
                                   (GAME_AREA_LEFT + x * BLOCK_SIZE, y * BLOCK_SIZE, 
                                    BLOCK_SIZE, BLOCK_SIZE), 1)
        
        # Рисуем текущую фигуру
        if not self.game_over:
            piece = self.current_piece
            for y, row in enumerate(piece["shape"]):
                for x, cell in enumerate(row):
                    if cell:
                        pygame.draw.rect(screen, piece["color"], 
                                       (GAME_AREA_LEFT + (piece["x"] + x) * BLOCK_SIZE, 
                                        (piece["y"] + y) * BLOCK_SIZE, 
                                        BLOCK_SIZE, BLOCK_SIZE))
                        pygame.draw.rect(screen, WHITE, 
                                       (GAME_AREA_LEFT + (piece["x"] + x) * BLOCK_SIZE, 
                                        (piece["y"] + y) * BLOCK_SIZE, 
                                        BLOCK_SIZE, BLOCK_SIZE), 1)
        
        # Рисуем информацию (счет, уровень)
        font = pygame.font.SysFont(None, 36)
        score_text = font.render(f"Счет: {self.score}", True, WHITE)
        level_text = font.render(f"Уровень: {self.level}", True, WHITE)
        screen.blit(score_text, (GAME_AREA_LEFT + GRID_WIDTH * BLOCK_SIZE + 10, 30))
        screen.blit(level_text, (GAME_AREA_LEFT + GRID_WIDTH * BLOCK_SIZE + 10, 70))
        
        # Если игра окончена, выводим сообщение
        if self.game_over:
            game_over_font = pygame.font.SysFont(None, 48)
            game_over_text = game_over_font.render("Игра Окончена!", True, (255, 0, 0))
            screen.blit(game_over_text, (GAME_AREA_LEFT + GRID_WIDTH * BLOCK_SIZE // 2 - 100, 
                                       SCREEN_HEIGHT // 2 - 24))

# Создаем экземпляр игры
game = Tetris()

# Основной игровой цикл
running = True
last_time = pygame.time.get_ticks()

while running:
    # Управление FPS
    current_time = pygame.time.get_ticks()
    delta_time = (current_time - last_time) / 1000.0  # Конвертируем в секунды
    last_time = current_time
    
    # Обработка событий
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        
        if not game.game_over:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    if game.valid_move(game.current_piece, -1, 0):
                        game.current_piece["x"] -= 1
                elif event.key == pygame.K_RIGHT:
                    if game.valid_move(game.current_piece, 1, 0):
                        game.current_piece["x"] += 1
                elif event.key == pygame.K_DOWN:
                    if game.valid_move(game.current_piece, 0, 1):
                        game.current_piece["y"] += 1
                elif event.key == pygame.K_UP:
                    game.rotate_piece()
                elif event.key == pygame.K_SPACE:
                    # Мгновенное падение
                    while game.valid_move(game.current_piece, 0, 1):
                        game.current_piece["y"] += 1
                    game.lock_piece()
    
    # Обновление игры
    game.update(delta_time)
    
    # Отрисовка
    game.draw()
    pygame.display.flip()
    
    # Ограничиваем FPS
    clock.tick(60)

pygame.quit()