import random
import tkinter as tk

# Constants
BOARD_WIDTH = 10
BOARD_HEIGHT = 20
CELL_SIZE = 30
SHAPES = [
    [[1, 1, 1, 1]],
    [[1, 1], [1, 1]],
    [[0, 1, 0], [1, 1, 1]],
    [[1, 0, 0], [1, 1, 1]],
    [[0, 0, 1], [1, 1, 1]],
    [[0, 1, 1], [1, 1, 0]],
    [[1, 1, 0], [0, 1, 1]],
]
COLORS = ["red", "green", "blue", "cyan", "magenta", "yellow", "orange"]


class Tetris:
    def __init__(self, root):
        self.root = root
        self.root.title("Tetris")
        self.canvas = tk.Canvas(
            root, width=BOARD_WIDTH * CELL_SIZE, height=BOARD_HEIGHT * CELL_SIZE
        )
        self.canvas.pack()
        self.board = [[0] * BOARD_WIDTH for _ in range(BOARD_HEIGHT)]
        self.current_shape = None
        self.current_color = None
        self.current_x = 0
        self.current_y = 0
        self.game_over = False
        self.new_shape()
        self.root.bind("<Key>", self.key_press)
        self.update()

    def new_shape(self):
        self.current_shape = random.choice(SHAPES)
        self.current_color = random.choice(COLORS)
        self.current_x = BOARD_WIDTH // 2 - len(self.current_shape[0]) // 2
        self.current_y = 0
        if not self.valid_move(self.current_shape, self.current_x, self.current_y):
            self.game_over = True

    def valid_move(self, shape, x, y):
        for i, row in enumerate(shape):
            for j, cell in enumerate(row):
                if cell and (
                    x + j < 0
                    or x + j >= BOARD_WIDTH
                    or y + i >= BOARD_HEIGHT
                    or self.board[y + i][x + j]
                ):
                    return False
        return True

    def rotate_shape(self):
        rotated_shape = list(zip(*self.current_shape[::-1]))
        if self.valid_move(rotated_shape, self.current_x, self.current_y):
            self.current_shape = rotated_shape

    def move_shape(self, dx, dy):
        if self.valid_move(
            self.current_shape, self.current_x + dx, self.current_y + dy
        ):
            self.current_x += dx
            self.current_y += dy
            return True
        return False

    def drop_shape(self):
        if not self.move_shape(0, 1):
            for i, row in enumerate(self.current_shape):
                for j, cell in enumerate(row):
                    if cell:
                        self.board[self.current_y + i][self.current_x + j] = (
                            self.current_color
                        )
            self.clear_lines()
            self.new_shape()

    def clear_lines(self):
        new_board = [row for row in self.board if any(cell == 0 for cell in row)]
        lines_cleared = BOARD_HEIGHT - len(new_board)
        self.board = [[0] * BOARD_WIDTH for _ in range(lines_cleared)] + new_board

    def draw_board(self):
        self.canvas.delete("all")
        for y, row in enumerate(self.board):
            for x, cell in enumerate(row):
                if cell:
                    self.canvas.create_rectangle(
                        x * CELL_SIZE,
                        y * CELL_SIZE,
                        (x + 1) * CELL_SIZE,
                        (y + 1) * CELL_SIZE,
                        fill=cell,
                    )
        for i, row in enumerate(self.current_shape):
            for j, cell in enumerate(row):
                if cell:
                    self.canvas.create_rectangle(
                        (self.current_x + j) * CELL_SIZE,
                        (self.current_y + i) * CELL_SIZE,
                        (self.current_x + j + 1) * CELL_SIZE,
                        (self.current_y + i + 1) * CELL_SIZE,
                        fill=self.current_color,
                    )

    def update(self):
        if not self.game_over:
            self.drop_shape()
            self.draw_board()
            self.root.after(500, self.update)
        else:
            self.canvas.create_text(
                BOARD_WIDTH * CELL_SIZE // 2,
                BOARD_HEIGHT * CELL_SIZE // 2,
                text="Game Over",
                fill="white",
                font=("Helvetica", 24),
            )

    def key_press(self, event):
        if event.keysym == "Left":
            self.move_shape(-1, 0)
        elif event.keysym == "Right":
            self.move_shape(1, 0)
        elif event.keysym == "Down":
            self.move_shape(0, 1)
        elif event.keysym == "Up":
            self.rotate_shape()
        self.draw_board()


if __name__ == "__main__":
    root = tk.Tk()
    game = Tetris(root)
    root.mainloop()
