import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'lib'))
import pygame
import random

pygame.init()

BOARD_SIZE = 8
CELL_SIZE = 60
PADDING = 10
TOP_BAR_HEIGHT = 60
WINDOW_WIDTH = BOARD_SIZE * CELL_SIZE + PADDING * 2
WINDOW_HEIGHT = BOARD_SIZE * CELL_SIZE + PADDING * 2 + TOP_BAR_HEIGHT

COLORS = [
    (255, 100, 100),
    (100, 255, 100),
    (100, 100, 255),
    (255, 255, 100),
    (255, 100, 255),
    (100, 255, 255),
    (255, 180, 100),
]

BG_COLOR = (30, 30, 30)
SELECTED_COLOR = (255, 255, 255)
LINE_COLOR = (50, 50, 50)
TEXT_COLOR = (255, 255, 255)

font = pygame.font.Font(None, 36)

class Match3Game:
    def __init__(self):
        self.screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
        pygame.display.set_caption("消消乐")
        self.board = []
        self.score = 0
        self.selected = None
        self.matching = []
        self.falling = []
        self.new_tiles = []
        self.state = "playing"
        self.init_board()

    def init_board(self):
        self.board = []
        for row in range(BOARD_SIZE):
            row_tiles = []
            for col in range(BOARD_SIZE):
                color = random.choice(COLORS)
                while self.would_match(row, col, color, row_tiles):
                    color = random.choice(COLORS)
                row_tiles.append(color)
            self.board.append(row_tiles)

    def would_match(self, row, col, color, row_tiles):
        if col >= 2:
            if row_tiles[col-1] == color and row_tiles[col-2] == color:
                return True
        if row >= 2:
            if self.board[row-1][col] == color and self.board[row-2][col] == color:
                return True
        return False

    def draw(self):
        self.screen.fill(BG_COLOR)
        score_text = font.render(f"分数: {self.score}", True, TEXT_COLOR)
        self.screen.blit(score_text, (PADDING, 15))

        start_y = TOP_BAR_HEIGHT + PADDING
        for row in range(BOARD_SIZE):
            for col in range(BOARD_SIZE):
                x = PADDING + col * CELL_SIZE
                y = start_y + row * CELL_SIZE
                color = self.board[row][col]
                pygame.draw.rect(self.screen, color, (x, y, CELL_SIZE - 2, CELL_SIZE - 2))
                
                if self.selected == (row, col):
                    pygame.draw.rect(self.screen, SELECTED_COLOR, (x, y, CELL_SIZE - 2, CELL_SIZE - 2), 3)
                
                if (row, col) in self.matching:
                    pygame.draw.circle(self.screen, (255, 255, 255), (x + CELL_SIZE//2, y + CELL_SIZE//2), CELL_SIZE//3)
        
        pygame.display.flip()

    def handle_click(self, pos):
        if self.state != "playing":
            return
        
        x, y = pos
        start_y = TOP_BAR_HEIGHT + PADDING
        
        if y < start_y or y >= start_y + BOARD_SIZE * CELL_SIZE:
            return
        if x < PADDING or x >= PADDING + BOARD_SIZE * CELL_SIZE:
            return
        
        col = (x - PADDING) // CELL_SIZE
        row = (y - start_y) // CELL_SIZE
        
        if self.selected is None:
            self.selected = (row, col)
        else:
            if self.selected == (row, col):
                self.selected = None
            else:
                self.try_swap(self.selected, (row, col))

    def try_swap(self, pos1, pos2):
        r1, c1 = pos1
        r2, c2 = pos2
        
        if abs(r1 - r2) + abs(c1 - c2) != 1:
            self.selected = (r2, c2)
            return
        
        self.swap(pos1, pos2)
        
        matches = self.find_matches()
        if matches:
            self.selected = None
            self.process_matches(matches)
        else:
            self.swap(pos1, pos2)
            self.selected = None

    def swap(self, pos1, pos2):
        r1, c1 = pos1
        r2, c2 = pos2
        self.board[r1][c1], self.board[r2][c2] = self.board[r2][c2], self.board[r1][c1]

    def find_matches(self):
        matches = set()
        
        for row in range(BOARD_SIZE):
            for col in range(BOARD_SIZE - 2):
                color = self.board[row][col]
                if self.board[row][col+1] == color and self.board[row][col+2] == color:
                    matches.add((row, col))
                    matches.add((row, col+1))
                    matches.add((row, col+2))
                    k = col + 3
                    while k < BOARD_SIZE and self.board[row][k] == color:
                        matches.add((row, k))
                        k += 1
        
        for col in range(BOARD_SIZE):
            for row in range(BOARD_SIZE - 2):
                color = self.board[row][col]
                if self.board[row+1][col] == color and self.board[row+2][col] == color:
                    matches.add((row, col))
                    matches.add((row+1, col))
                    matches.add((row+2, col))
                    k = row + 3
                    while k < BOARD_SIZE and self.board[k][col] == color:
                        matches.add((k, col))
                        k += 1
        
        return matches

    def process_matches(self, matches):
        self.matching = matches
        self.draw()
        pygame.time.wait(300)
        
        for row, col in matches:
            self.board[row][col] = None
        
        self.score += len(matches) * 10
        self.matching = []
        
        self.drop_tiles()

    def drop_tiles(self):
        moved = False
        for col in range(BOARD_SIZE):
            empty_row = BOARD_SIZE - 1
            for row in range(BOARD_SIZE - 1, -1, -1):
                if self.board[row][col] is not None:
                    if row != empty_row:
                        self.board[empty_row][col] = self.board[row][col]
                        self.board[row][col] = None
                        moved = True
                    empty_row -= 1
            
            for row in range(empty_row, -1, -1):
                self.board[row][col] = random.choice(COLORS)
                moved = True
        
        if moved:
            self.draw()
            pygame.time.wait(200)
            
            new_matches = self.find_matches()
            if new_matches:
                self.process_matches(new_matches)

    def run(self):
        clock = pygame.time.Clock()
        running = True
        
        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                elif event.type == pygame.MOUSEBUTTONDOWN:
                    self.handle_click(event.pos)
            
            self.draw()
            clock.tick(60)
        
        pygame.quit()
        sys.exit()

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