import pygame
import sys
import math
import os
import random

pygame.init()

width, height = 800, 670
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Labirints')

os.chdir("C:\\Users\\aleks\\Desktop\\game")
pygame.mixer.music.load('background.mp3')
pygame.mixer.music.play(-1)
cheese_image = pygame.image.load("sprites\cheese\cheese.png").convert_alpha()
BLACK = (0, 0, 0)
BLUE = (0, 0, 255)
cheese_count = 0


maze = [
    "#########################",
    "#.................#.....#",
    "#.##.#.########.#.#.#####",
    "#......#........#.#.....#",
    "#.#.##...##.#####.#####.#",
    "#.#.#######.#.....#...#.#",
    "#.#.......#.#.#####.#.#.#",
    "#.##..###.#.#.#.....#...#",
    "#.....###.#.#.#.#######.#",
    "#.##....#...#...#.#.....#",
    "#.##.##.###.#####.#.#..##",
    "#.....#...#...#...#.#...#",
    "#.#.#.###.###.#.###.#.#.#",
    "#.#.#...........#...#.#.#",
    "#.#.##.###.####.#.###.#.#",
    "#.#.#...##.##...#.#...#.#",
    "#.#.#.#.##....###.#.###.#",
    "#.#.#.#....##.#...#.#...#",
    "#.#.#.#.##..###.###.#.###",
    "#.......................#",
    "#########################"
]

class Button:
    def __init__(self, x, y, width, height, text, action=None):
        self.rect = pygame.Rect(x, y, width, height)
        self.color = (100, 100, 100)
        self.text = text
        self.font = pygame.font.Font(None, 36)
        self.text_surface = self.font.render(self.text, True, (255, 255, 255))
        self.text_rect = self.text_surface.get_rect(center=self.rect.center)
        self.action = action

    def draw(self, surface):
        pygame.draw.rect(surface, self.color, self.rect)
        surface.blit(self.text_surface, self.text_rect)

def draw_start_screen(screen):
    screen.fill(BLUE)
    title_font = pygame.font.Font(None, 72)
    title_text = title_font.render("Labirints", True, (255, 255, 255))
    title_rect = title_text.get_rect(center=(width // 2, height // 2 - 50))
    screen.blit(title_text, title_rect)

    play_button = Button(width // 2 - 100, height - 100, 200, 50, "Play")
    play_button.draw(screen)
    pygame.display.flip()
    
def reset_game():
    global player, enemy, cheese_count
    player = Player(32, 32)
    enemy = Enemy(700, 610, player)
    player.reset_cheese_count()
    player.cheeses = []
    cheese_count = 0

def handle_game_over():
    screen.fill(BLUE)
    title_font = pygame.font.Font(None, 72)
    title_text = title_font.render("Game Over", True, (255, 255, 255))
    title_rect = title_text.get_rect(center=(width // 2, height // 2 - 50))
    screen.blit(title_text, title_rect)

    replay_button = Button(width // 2 - 100, height // 2 + 50, 200, 50, "Replay", action=main_game_loop)
    replay_button.draw(screen)
    pygame.display.flip()
    replay_waiting = True
    while replay_waiting:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                mouse_pos = pygame.mouse.get_pos()
                if replay_button.rect.collidepoint(mouse_pos):
                    replay_waiting = False
                    reset_game()
    return False

def draw_victory_screen():
    screen.fill(BLUE)
    title_font = pygame.font.Font(None, 72)
    title_text = title_font.render("Victory!", True, (255, 255, 255))
    title_rect = title_text.get_rect(center=(width // 2, height // 2 - 50))
    screen.blit(title_text, title_rect)

    replay_button = Button(width // 2 - 100, height // 2 + 50, 200, 50, "Replay", action=main_game_loop)
    replay_button.draw(screen)
    pygame.display.flip()

def handle_victory():
    replay_button = Button(width // 2 - 100, height // 2 + 50, 200, 50, "Replay", action=main_game_loop)
    replay_waiting = True
    while replay_waiting:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                mouse_pos = pygame.mouse.get_pos()
                if replay_button.rect.collidepoint(mouse_pos):
                    replay_waiting = False
                    return True
    return False

class Cheese(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = pygame.transform.scale(cheese_image, (30, 30))
        self.rect = self.image.get_rect()
        self.rect.topleft = (x, y)

class Player(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        # Загрузка изображений персонажа и изменение их размера
        self.images = {
            "up": [pygame.transform.scale(pygame.image.load('sprites/rodent/up.png').convert_alpha(), (25, 25)),
                   pygame.transform.scale(pygame.image.load('sprites/rodent/up1.png').convert_alpha(), (25, 25))],
            "down": [pygame.transform.scale(pygame.image.load('sprites/rodent/down.png').convert_alpha(), (25, 25)),
                     pygame.transform.scale(pygame.image.load('sprites/rodent/down1.png').convert_alpha(), (25, 25))],
            "left": [pygame.transform.scale(pygame.image.load('sprites/rodent/left.png').convert_alpha(), (25, 25)),
                     pygame.transform.scale(pygame.image.load('sprites/rodent/left1.png').convert_alpha(), (25, 25))],
            "right": [pygame.transform.scale(pygame.image.load('sprites/rodent/right.png').convert_alpha(), (25, 25)),
                      pygame.transform.scale(pygame.image.load('sprites/rodent/right1.png').convert_alpha(), (25, 25))]
        }

    
        self.direction = "down"  # Initial direction
        self.image_index = 0  # Index of the current image in the animation
        self.image = self.images[self.direction][self.image_index]
        self.rect = self.image.get_rect()
        self.rect.topleft = (x, y)
        self.speed = 10
        self.cheeses = []
        self.cheese_count = 0
    def reset_cheese_count(self):
        self.cheese_count = 0  # Reset cheese count to zero


    def move(self, dx, dy, walls):
        old_rect = self.rect.copy()  # Копируем текущее положение игрока
        self.rect.x += dx
        self.rect.y += dy

    # Проверка столкновений по горизонтали
        for wall in walls:
            if self.rect.colliderect(wall):
                if dx > 0:
                    self.rect.right = wall.left
                elif dx < 0:
                    self.rect.left = wall.right

    # Проверка столкновений по вертикали
        for wall in walls:
            if self.rect.colliderect(wall):
                if dy > 0:
                    self.rect.bottom = wall.top
                elif dy < 0:
                    self.rect.top = wall.bottom

    # Если после обновления положения игрока есть столкновение с другими стенами,
    # возвращаем его на предыдущее положение
        if self.rect.collidelist(walls) != -1:
            self.rect = old_rect





    def update_image(self, dx, dy):
        if dx > 0:
            self.direction = "right"
        elif dx < 0:
            self.direction = "left"
        elif dy > 0:
            self.direction = "down"
        elif dy < 0:
            self.direction = "up"

        # Update the image index for animation
        self.image_index = (self.image_index + 1) % len(self.images[self.direction])
        self.image = self.images[self.direction][self.image_index]

    def draw(self, surface):
        surface.blit(self.image, self.rect)

    def generate_random_cheese(self, walls, num_cheese=1):  # По умолчанию создаем 3 кусочка сыра
        for _ in range(num_cheese):
            while True:
                x = random.randint(0, width - 30)
                y = random.randint(0, height - 30)
                rect = pygame.Rect(x, y, 30, 30)
                if not any(wall.colliderect(rect) for wall in walls):
                    self.cheeses.append(Cheese(x, y))
                    break

    def check_cheese_collision(self, cheeses):
        for cheese in cheeses[:]:
            if self.rect.colliderect(cheese.rect):
                cheeses.remove(cheese)



def draw_maze(maze):
    walls = []
    for y, row in enumerate(maze):
        for x, char in enumerate(row):
            if char == '#':
                pygame.draw.rect(screen, BLACK, (x * 32, y * 32, 32, 32))
                walls.append(pygame.Rect(x * 32, y * 32, 32, 32))
    return walls
class Enemy(pygame.sprite.Sprite):
    def __init__(self, x, y, player):
        super().__init__()
        self.images = {
            "up": [pygame.transform.scale(pygame.image.load('sprites/cat/up.png').convert_alpha(), (25, 25)),
                   pygame.transform.scale(pygame.image.load('sprites/cat/up3.png').convert_alpha(), (25, 25))],
            "down": [pygame.transform.scale(pygame.image.load('sprites/cat/down.png').convert_alpha(), (25, 25)),
                     pygame.transform.scale(pygame.image.load('sprites/cat/down3.png').convert_alpha(), (25, 25))],
            "left": [pygame.transform.scale(pygame.image.load('sprites/cat/left.png').convert_alpha(), (25, 25)),
                     pygame.transform.scale(pygame.image.load('sprites/cat/left3.png').convert_alpha(), (25, 25))],
            "right": [pygame.transform.scale(pygame.image.load('sprites/cat/right.png').convert_alpha(), (25, 25)),
                      pygame.transform.scale(pygame.image.load('sprites/cat/right3.png').convert_alpha(), (25, 25))]
        }
        self.direction = "down"  # Initial direction
        self.image_index = 0  # Index of the current image in the animation
        self.image = self.images[self.direction][self.image_index]
        self.rect = pygame.Rect(x, y, 30, 30)
        self.rect.topleft = (x, y)
        self.speed = 5
        self.player = player
        

    def check_collision_ahead(self, walls):
        # Проверяем столкновение в точке впереди противника
        future_rect = self.rect.move(self.speed, 0) if self.direction == "right" else \
                      self.rect.move(-self.speed, 0) if self.direction == "left" else \
                      self.rect.move(0, self.speed) if self.direction == "down" else \
                      self.rect.move(0, -self.speed)  # "up"
        for wall in walls:
            if wall.colliderect(future_rect):
                return True
        return False


    def update(self, walls):
        dx, dy = 0, 0

        keys = pygame.key.get_pressed()
        
        # Обработка нажатий клавиш для управления врагом
        if keys[pygame.K_a]:
            dx = -self.speed
            self.direction = "left"
        elif keys[pygame.K_d]:
            dx = self.speed
            self.direction = "right"
        elif keys[pygame.K_w]:
            dy = -self.speed
            self.direction = "up"
        elif keys[pygame.K_s]:
            dy = self.speed
            self.direction = "down"
        
        new_rect = self.rect.move(dx, dy)
        if not self.check_collision(new_rect, walls):
            self.rect = new_rect

        # Если двигается только по одной оси, то разрешаем движение
        if dx != 0 and dy == 0:
            new_rect = self.rect.move(dx, 0)
            if not self.check_collision(new_rect, walls):
                self.rect = new_rect
        elif dy != 0 and dx == 0:
            new_rect = self.rect.move(0, dy)
            if not self.check_collision(new_rect, walls):
                self.rect = new_rect

        # Update animation
        self.image_index = (self.image_index + 1) % len(self.images[self.direction])
        self.image = self.images[self.direction][self.image_index]

    def check_collision(self, new_rect, walls):
    # Проверяем столкновение только с несколькими точками на пути противника
        for i in range(0, new_rect.width, self.speed):
            x = new_rect.left + i if self.speed > 0 else new_rect.right - i
            for j in range(0, new_rect.height, self.speed):
                y = new_rect.top + j if self.speed > 0 else new_rect.bottom - j
                if self.is_wall(x, y, walls):
                    return True
        return False


    def is_wall(self, x, y, walls):
        # Проверяем, находится ли точка (x, y) внутри стены
        for wall in walls:
            if wall.collidepoint(x, y):
                return True
        return False



    def draw(self, surface):
        surface.blit(self.image, self.rect)

player = Player(32, 32)
enemy = Enemy(700, 610, player)
def draw_text(surface, text, pos, font, color):
    text_surface = font.render(text, True, color)
    text_rect = text_surface.get_rect()
    text_rect.topleft = pos
    surface.blit(text_surface, text_rect)

def generate_random_cheese(player, walls):
    player.generate_random_cheese(walls)
def main_game_loop():
    global cheese_count
    cheese_count = 0
    red_square_timer = 0

    clock = pygame.time.Clock()
    cheese_count = 0  # Initialize cheese count
    font = pygame.font.Font(None, 36)  # Font for displaying text
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
        current_time = pygame.time.get_ticks()
        dt = clock.tick(30) / 1000.0  # Преобразуем миллисекунды в секунды
        replay_button = Button(width // 2 - 100, height // 2 + 50, 200, 50, "Replay", action=main_game_loop)
        if player.rect.colliderect(enemy.rect):
            if handle_game_over():
                reset_game()
        
        
        red_square_timer += dt

        if red_square_timer >= 5:
            red_square_timer -= 5
            generate_random_cheese(player, walls)
        


        player.check_cheese_collision(player.cheeses)

        keys = pygame.key.get_pressed()
        dx, dy = 0, 0

# Check horizontal movement
        if keys[pygame.K_LEFT]:
            dx = -player.speed
        elif keys[pygame.K_RIGHT]:
            dx = player.speed

# Check vertical movement
        if keys[pygame.K_UP]:
            dy = -player.speed
        elif keys[pygame.K_DOWN]:
            dy = player.speed

# Ensure that the player can only move in one direction at a time
        if dx != 0 and dy != 0:
    # Diagonal movement detected, prioritize one direction
            if keys[pygame.K_LEFT]:
                dy = 0  # Prevent vertical movement
            elif keys[pygame.K_RIGHT]:
                dy = 0  # Prevent vertical movement
            elif keys[pygame.K_UP]:
                dx = 0  # Prevent horizontal movement
            elif keys[pygame.K_DOWN]:
                dx = 0  # Prevent horizontal movement
    
    
        walls = draw_maze(maze)
        collision = player.move(dx, dy, walls)
        player.update_image(dx, dy)
        enemy.update(walls)

        screen.fill(BLUE)
        draw_maze(maze)
        player.draw(screen)    
        enemy.draw(screen)

        for cheese in player.cheeses:
            screen.blit(cheese.image, cheese.rect)
        
        cheeses_to_remove = []

        for cheese in player.cheeses:
            if player.rect.colliderect(cheese.rect):
                cheese_count += 1  # Increment cheese count
                player.cheeses.remove(cheese)
        for cheese in cheeses_to_remove:
            player.cheeses.remove(cheese)
        
        draw_text(screen, f"Cheese: {cheese_count}", (10, 10), font, (255, 255, 255))

        if cheese_count >= 5:
            draw_victory_screen()
            if handle_victory():
                reset_game()
            continue
    
        pygame.display.flip()
        clock.tick(10)  # Reduce animation speed for better visibility
def main():
    play_button = Button(width // 2 - 100, height - 100, 200, 50, "Play")
    draw_start_screen(screen)
    waiting = True
    while waiting:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                mouse_pos = pygame.mouse.get_pos()
                if play_button.rect.collidepoint(mouse_pos):
                    waiting = False
                    main_game_loop()

if __name__ == "__main__":
    main()