import pygame
import random
import math

# ---------------- CONFIG ----------------
WIDTH, HEIGHT = 800, 600
FPS = 60

SQUARE_SIZE = 220
SQUARE_X = (WIDTH - SQUARE_SIZE) // 2
SQUARE_Y = (HEIGHT - SQUARE_SIZE) // 2

BALL_RADIUS = 10
PLAYER_POWER = 7
FRICTION = 0.99
STOP_THRESHOLD = 0.1

TOTAL_ENEMIES = 10
GAP_SIZE = 32

#-----------------GAME STATES-----------------
MENU="menu"
PLAYING="playing"
PAUSED="pause"
HOW_TO_PLAY="how to play"
ABOUT="about"
RESUME="resume"#added
AIMING="aiming"
GAME_OVER="game over"

game_state= MENU
#------------------BUTTONS-------------------
start_button= pygame.draw.rect(100,200)
start_button_rect=start_button.get_rect(center=(400,230))

how_to_button= pygame.draw.rect(100,300)
how_to_button_rect=how_to_button.get_rect(center=(400,330))

about_button=pygame.draw.rect(100,300)
about_button_rect=about_button.get_rect(center=(400,430))

pause_button=pygame.draw.rect(100,200)
pause_button_rect=pause_button.get_rect(top_left=(800,0))

resume_button=pygame.draw.rect(100,200)
resume_button_rect=resume_button.get_rect(center=(400,230))

back_button=pygame.draw.rect(100,200)
back_button_rect=back_button.get_rect(topright=(0,0))

restart_button=pygame.draw.rect(100,200)
restart_button_rect=restart_button.get_rect(center=(400,330))

#---------------FUNCTIONS--------------------
def reset_game():
    global game_state


    game_state=PLAYING

# ---------------- BALL CLASS ----------------
class Ball:
    def __init__(self, x, y, color):
        self.x = x
        self.y = y
        self.vx = 0
        self.vy = 0
        self.color = color

    def move(self):
        self.x += self.vx
        self.y += self.vy
        self.vx *= FRICTION
        self.vy *= FRICTION
        if abs(self.vx) < STOP_THRESHOLD:
            self.vx = 0
        if abs(self.vy) < STOP_THRESHOLD:
            self.vy = 0

    def draw(self, screen):
        pygame.draw.circle(screen, self.color,
                           (int(self.x), int(self.y)), BALL_RADIUS)

# ---------------- COLLISION ----------------
def ball_collision(b1, b2):
    dx = b1.x - b2.x
    dy = b1.y - b2.y
    dist = math.hypot(dx, dy)
    if dist == 0 or dist > BALL_RADIUS * 2:
        return
    nx = dx / dist
    ny = dy / dist
    p = (b1.vx - b2.vx) * nx + (b1.vy - b2.vy) * ny
    b1.vx -= p * nx
    b1.vy -= p * ny
    b2.vx += p * nx
    b2.vy += p * ny

# ---------------- MAIN GAME ----------------
def main():
    pygame.init()
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    pygame.display.set_caption("2 Player Knock-Out")
    clock = pygame.time.Clock()
    font = pygame.font.Font(None, 32)

    enemies = []
    for _ in range(TOTAL_ENEMIES):
        x = random.randint(SQUARE_X + BALL_RADIUS, SQUARE_X + SQUARE_SIZE - BALL_RADIUS)
        y = random.randint(SQUARE_Y + BALL_RADIUS, SQUARE_Y + SQUARE_SIZE - BALL_RADIUS)
        enemies.append(Ball(x, y, (255, 0, 0)))

    player_ball = Ball(WIDTH // 2, HEIGHT - 40, (0, 0, 255))

    aiming = False
    start_pos = (0, 0)
    current_player = 0
    scores = [0, 0]
    turn_active = False
    game_over = False

    running = True
    while running:
        clock.tick(FPS)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()####changed here
                exit()##here also

        #------KEYBOARD EVENTS---------------
            if event.type == pygame.KEYDOWN:
                if event.key== pygame.K_p:
                    if game_state== PLAYING:
                        game_state=PAUSED
                    elif game_state== PAUSED:
                        game_state= PLAYING#changes here also -------------------

            if event.type == pygame.MOUSEBUTTONDOWN and not aiming and not turn_active and not game_over:
                aiming = True
                start_pos = (player_ball.x, player_ball.y)

            if event.type == pygame.MOUSEBUTTONUP and aiming:
                aiming = False
                mx, my = pygame.mouse.get_pos()
                dx = start_pos[0] - mx
                dy = start_pos[1] - my
                dist = math.hypot(dx, dy)
                if dist > 0:
                    player_ball.vx = (dx / dist) * PLAYER_POWER
                    player_ball.vy = (dy / dist) * PLAYER_POWER
                    turn_active = True
                    
            #-----------MOUSE EVENTS------------
            if event.type==pygame.MOUSEBUTTONDOWN:
                mous_pos=event.pos
                #menu button
                if game_state==MENU:
                   if start_button_rect.pygame.Rect.collidepoint(mous_pos):
                        reset_game()
                   elif game_state==how_to_button_rect.pygame.rect.collidepoint(mous_pos):
                    game_state==HOW_TO_PLAY
                   elif game_state==about_button_rect.pygame.rect.collidepoint(mous_pos):
                       game_state==ABOUT
                       #pause/resume buttons
                if game_state==PLAYING:
                    if pause_button_rect.pygame.rect.collidepoint(mous_pos):
                       game_state==PAUSED
                if game_state==PAUSED:
                    if resume_button_rect.pygame.Rect.collidepoint(mous_pos):
                        game_state==RESUME
                if back_button_rect.collidepoint(mous_pos):
                    if game_state in (HOW_TO_PLAY,PLAYING,ABOUT,PAUSED):
                        game_state==MENU
                if game_state==PAUSED:
                    if restart_button_rect.pygame.Rect.collidepoint(mous_pos):
                        reset_game()
                        game_state==PLAYING

        # ---------------- UPDATE ----------------
        if turn_active:
            player_ball.move()
            for e in enemies:
                e.move()
                ball_collision(player_ball, e)

            # Enemy collisions
            for i in range(len(enemies)):
                for j in range(i + 1, len(enemies)):
                    ball_collision(enemies[i], enemies[j])

            # Wall + gap logic
            for e in enemies:
                # LEFT
                if e.x - BALL_RADIUS <= SQUARE_X:
                    if not (SQUARE_Y + SQUARE_SIZE//2 - GAP_SIZE//2 <= e.y <=
                            SQUARE_Y + SQUARE_SIZE//2 + GAP_SIZE//2):
                        e.x = SQUARE_X + BALL_RADIUS
                        e.vx *= -1
                # RIGHT
                if e.x + BALL_RADIUS >= SQUARE_X + SQUARE_SIZE:
                    if not (SQUARE_Y + SQUARE_SIZE//2 - GAP_SIZE//2 <= e.y <=
                            SQUARE_Y + SQUARE_SIZE//2 + GAP_SIZE//2):
                        e.x = SQUARE_X + SQUARE_SIZE - BALL_RADIUS
                        e.vx *= -1
                # TOP
                if e.y - BALL_RADIUS <= SQUARE_Y:
                    if not (SQUARE_X + SQUARE_SIZE//2 - GAP_SIZE//2 <= e.x <=
                            SQUARE_X + SQUARE_SIZE//2 + GAP_SIZE//2):
                        e.y = SQUARE_Y + BALL_RADIUS
                        e.vy *= -1
                # BOTTOM
                if e.y + BALL_RADIUS >= SQUARE_Y + SQUARE_SIZE:
                    if not (SQUARE_X + SQUARE_SIZE//2 - GAP_SIZE//2 <= e.x <=
                            SQUARE_X + SQUARE_SIZE//2 + GAP_SIZE//2):
                        e.y = SQUARE_Y + SQUARE_SIZE - BALL_RADIUS
                        e.vy *= -1

            # Check escaped balls
            escaped = 0
            for e in enemies[:]:
                if (e.x < SQUARE_X - BALL_RADIUS or
                    e.x > SQUARE_X + SQUARE_SIZE + BALL_RADIUS or
                    e.y < SQUARE_Y - BALL_RADIUS or
                    e.y > SQUARE_Y + SQUARE_SIZE + BALL_RADIUS):
                    enemies.remove(e)
                    escaped += 1

            scores[current_player] += escaped

            # End of turn when player ball stops
            if player_ball.vx == 0 and player_ball.vy == 0:
                player_ball.x = WIDTH // 2
                player_ball.y = HEIGHT - 40
                turn_active = False

                # Switch player ONLY if no ball escaped
                if escaped == 0:
                    current_player = 1 - current_player

        if len(enemies) == 0:
            game_over = True

        # ---------------- DRAW ----------------
        screen.fill((235, 235, 235))
        pygame.draw.rect(screen, (0, 0, 0),
                         (SQUARE_X, SQUARE_Y, SQUARE_SIZE, SQUARE_SIZE), 2)
        
        if game_state==MENU:
            screen.blit(start_button,start_button_rect)
            screen.blit(about_button,about_button_rect)
            screen.blit(how_to_button,how_to_button_rect)
         # Draw gaps
        pygame.draw.rect(screen, (240, 240, 240),
            (SQUARE_X + SQUARE_SIZE//2 - GAP_SIZE//2, SQUARE_Y - 2, GAP_SIZE, 4))
        pygame.draw.rect(screen, (240, 240, 240),
            (SQUARE_X + SQUARE_SIZE//2 - GAP_SIZE//2, SQUARE_Y + SQUARE_SIZE - 2, GAP_SIZE, 4))
        pygame.draw.rect(screen, (240, 240, 240),
            (SQUARE_X - 2, SQUARE_Y + SQUARE_SIZE//2 - GAP_SIZE//2, 4, GAP_SIZE))
        pygame.draw.rect(screen, (240, 240, 240),
            (SQUARE_X + SQUARE_SIZE - 2, SQUARE_Y + SQUARE_SIZE//2 - GAP_SIZE//2, 4, GAP_SIZE))

        for e in enemies:
            e.draw(screen)
        player_ball.draw(screen)

        if aiming:
            mx, my = pygame.mouse.get_pos()
            pygame.draw.line(screen, (0, 0, 255), start_pos, (mx, my), 2)

        screen.blit(font.render(f"Player 1: {scores[0]}", True, (0, 0, 0)), (10, 10))
        screen.blit(font.render(f"Player 2: {scores[1]}", True, (0, 0, 0)), (10, 40))
        screen.blit(font.render(f"Turn: Player {current_player + 1}", True, (0, 0, 150)), (10, 70))

        if game_over:
            winner = "DRAW"
            if scores[0] > scores[1]:
                winner = "PLAYER 1 WINS"
            elif scores[1] > scores[0]:
                winner = "PLAYER 2 WINS"

            screen.blit(font.render(winner, True, (0, 150, 0)),
                        (WIDTH//2 - 90, HEIGHT//2))

        pygame.display.flip()

    pygame.quit()

if __name__ == "__main__":
    main()
