import pygame
import random
import sys

# Initialize pygame
pygame.init()

# Screen setup
WIDTH, HEIGHT = 600, 500
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Spaceship Shooter")

clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 32)
big_font = pygame.font.SysFont(None, 56)

# Colors
BLACK = (10, 10, 30)
WHITE = (255, 255, 255)
BLUE = (50, 150, 255)
RED = (255, 70, 70)
YELLOW = (255, 230, 50)
GRAY = (150, 150, 150)

# Player settings
PLAYER_SIZE = 40
PLAYER_SPEED = 5

# Bullet settings
BULLET_WIDTH = 6
BULLET_HEIGHT = 15
BULLET_SPEED = 8

# Asteroid settings
ASTEROID_SIZE = 35
ASTEROID_SPEED = 3


def reset_game():
    """Create a fresh game."""
    player = pygame.Rect(
        WIDTH // 2 - PLAYER_SIZE // 2,
        HEIGHT - 60,
        PLAYER_SIZE,
        PLAYER_SIZE
    )

    return {
        "player": player,
        "bullets": [],
        "asteroids": [],
        "score": 0,
        "game_over": False,
        "spawn_timer": 0,
        "asteroid_speed": ASTEROID_SPEED
    }


def draw_text(text, font, color, x, y):
    image = font.render(text, True, color)
    screen.blit(image, (x, y))


def spawn_asteroid(game):
    x = random.randint(0, WIDTH - ASTEROID_SIZE)

    asteroid = pygame.Rect(
        x, -ASTEROID_SIZE, ASTEROID_SIZE, ASTEROID_SIZE
    )

    game["asteroids"].append(asteroid)


# Create stars for the background
stars = [
    (random.randint(0, WIDTH), random.randint(0, HEIGHT))
    for _ in range(60)
]

game = reset_game()

# Main game loop
while True:

    # Handle events
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                if game["game_over"]:
                    game = reset_game()
                else:
                    # Fire a bullet from the spaceship
                    bullet = pygame.Rect(
                        game["player"].centerx - BULLET_WIDTH // 2,
                        game["player"].top,
                        BULLET_WIDTH,
                        BULLET_HEIGHT
                    )
                    game["bullets"].append(bullet)

    # Update game only while playing
    if not game["game_over"]:

        # Move the player
        keys = pygame.key.get_pressed()
        player = game["player"]

        if keys[pygame.K_LEFT]:
            player.x -= PLAYER_SPEED
        if keys[pygame.K_RIGHT]:
            player.x += PLAYER_SPEED

        # Keep player inside the screen
        player.clamp_ip(screen.get_rect())

        # Move bullets upwards
        for bullet in game["bullets"][:]:
            bullet.y -= BULLET_SPEED

            if bullet.bottom < 0:
                game["bullets"].remove(bullet)

        # Spawn new asteroids periodically
        game["spawn_timer"] += 1

        if game["spawn_timer"] >= 35:
            spawn_asteroid(game)
            game["spawn_timer"] = 0

        # Move asteroids downwards
        for asteroid in game["asteroids"][:]:
            asteroid.y += game["asteroid_speed"]

            # Asteroid reaches the bottom
            if asteroid.top > HEIGHT:
                game["asteroids"].remove(asteroid)

            # Asteroid hits the spaceship
            elif asteroid.colliderect(player):
                game["game_over"] = True

        # Bullets destroy asteroids
        for bullet in game["bullets"][:]:
            for asteroid in game["asteroids"][:]:
                if bullet.colliderect(asteroid):
                    game["bullets"].remove(bullet)
                    game["asteroids"].remove(asteroid)
                    game["score"] += 1

                    # Increase difficulty every 5 points
                    if game["score"] % 5 == 0:
                        game["asteroid_speed"] += 1

                    break

    # Draw background
    screen.fill(BLACK)

    for star_x, star_y in stars:
        screen.set_at((star_x, star_y), WHITE)

    # Draw spaceship as a blue triangle
    player = game["player"]

    pygame.draw.polygon(screen, BLUE, [
        (player.centerx, player.top),
        (player.left, player.bottom),
        (player.right, player.bottom)
    ])

    # Draw bullets
    for bullet in game["bullets"]:
        pygame.draw.rect(screen, YELLOW, bullet)

    # Draw asteroids
    for asteroid in game["asteroids"]:
        pygame.draw.circle(
            screen, GRAY, asteroid.center, ASTEROID_SIZE // 2
        )

    # Draw score
    draw_text(f"Score: {game['score']}", font, WHITE, 10, 10)

    # Game Over screen
    if game["game_over"]:
        overlay = pygame.Surface((WIDTH, HEIGHT))
        overlay.set_alpha(180)
        overlay.fill(BLACK)
        screen.blit(overlay, (0, 0))

        title = big_font.render("GAME OVER", True, RED)
        screen.blit(
            title,
            title.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 40))
        )

        message = font.render(
            f"Final score: {game['score']}", True, WHITE
        )
        screen.blit(
            message,
            message.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 5))
        )

        draw_text(
            "Press SPACE to restart",
            font, YELLOW, WIDTH // 2 - 130, HEIGHT // 2 + 45
        )

    pygame.display.flip()
    clock.tick(60)
