import pygame
import random
import math
import sys

# ============================================================
# FROGGY JUMPS
# ============================================================

pygame.init()

WIDTH = 1100
HEIGHT = 700
FPS = 60

screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Froggy Jumps")

clock = pygame.time.Clock()

# ============================================================
# KOLORY
# ============================================================

GREEN = (75, 210, 90)
DARK_GREEN = (35, 130, 55)
LIGHT_GREEN = (140, 245, 130)

YELLOW = (255, 220, 60)
GOLD = (255, 180, 30)

RED = (220, 55, 55)
DARK_RED = (130, 35, 35)

PURPLE = (180, 80, 240)
ORANGE = (255, 130, 40)

BLUE = (70, 170, 240)
CYAN = (70, 220, 240)

WHITE = (245, 245, 245)
BLACK = (20, 20, 25)

GRAY = (100, 105, 115)
DARK_GRAY = (45, 48, 55)

BROWN = (120, 75, 40)
GRASS = (60, 145, 65)

SKY = (110, 190, 230)

# ============================================================
# CZCIONKI
# ============================================================

FONT_BIG = pygame.font.SysFont("arial", 58, bold=True)
FONT_MED = pygame.font.SysFont("arial", 32, bold=True)
FONT = pygame.font.SysFont("arial", 22, bold=True)
FONT_SMALL = pygame.font.SysFont("arial", 17, bold=True)

# ============================================================
# GLOBALNE
# ============================================================

coins = 0
score = 0

particles = []

# ============================================================
# FUNKCJE
# ============================================================


def draw_text(surface, message, font, color, x, y, center=False):
    image = font.render(message, True, color)
    rect = image.get_rect()

    if center:
        rect.center = (x, y)
    else:
        rect.topleft = (x, y)

    surface.blit(image, rect)


def clamp(value, minimum, maximum):
    return max(minimum, min(maximum, value))


def draw_health(surface, x, y, hp, max_hp, width=160):
    pygame.draw.rect(
        surface,
        DARK_GRAY,
        (x, y, width, 20),
        border_radius=6
    )

    ratio = clamp(hp / max_hp, 0, 1)

    if ratio > 0.5:
        color = GREEN
    elif ratio > 0.25:
        color = ORANGE
    else:
        color = RED

    pygame.draw.rect(
        surface,
        color,
        (x, y, int(width * ratio), 20),
        border_radius=6
    )

    pygame.draw.rect(
        surface,
        WHITE,
        (x, y, width, 20),
        2,
        border_radius=6
    )


# ============================================================
# PARTICLE
# ============================================================


class Particle:

    def __init__(self, x, y, color):
        self.x = x
        self.y = y

        angle = random.uniform(0, math.pi * 2)
        speed = random.uniform(1, 5)

        self.vx = math.cos(angle) * speed
        self.vy = math.sin(angle) * speed

        self.color = color
        self.life = random.randint(20, 40)
        self.size = random.randint(2, 5)

    def update(self):
        self.x += self.vx
        self.y += self.vy

        self.vy += 0.08

        self.life -= 1

    def draw(self, surface):
        if self.life <= 0:
            return

        pygame.draw.circle(
            surface,
            self.color,
            (int(self.x), int(self.y)),
            self.size
        )


def create_particles(x, y, color, amount=15):

    for _ in range(amount):
        particles.append(
            Particle(x, y, color)
        )


# ============================================================
# PLATFORM
# ============================================================


class Platform:

    def __init__(self, x, y, width, height):
        self.rect = pygame.Rect(
            x,
            y,
            width,
            height
        )

    def draw(self, surface):

        pygame.draw.rect(
            surface,
            GRASS,
            self.rect,
            border_radius=6
        )

        pygame.draw.rect(
            surface,
            DARK_GREEN,
            self.rect,
            3,
            border_radius=6
        )


# ============================================================
# COIN
# ============================================================


class Coin:

    def __init__(self, x, y):
        self.x = x
        self.y = y

        self.radius = 11
        self.animation = random.random() * 6

        self.collected = False

    def update(self):
        self.animation += 0.12

    def draw(self, surface):

        if self.collected:
            return

        width = max(
            3,
            int(abs(math.sin(self.animation)) * 10)
        )

        pygame.draw.ellipse(
            surface,
            GOLD,
            (
                self.x - width,
                self.y - self.radius,
                width * 2,
                self.radius * 2
            )
        )

        pygame.draw.ellipse(
            surface,
            YELLOW,
            (
                self.x - max(1, width - 3),
                self.y - self.radius + 3,
                max(2, width * 2 - 6),
                self.radius * 2 - 6
            )
        )


# ============================================================
# ENEMY
# ============================================================


class Enemy:

    def __init__(self, x, y, enemy_type="normal"):

        self.x = x
        self.y = y

        self.width = 42
        self.height = 36

        self.enemy_type = enemy_type

        self.direction = random.choice([-1, 1])

        if enemy_type == "fast":
            self.speed = 3.2
            self.hp = 1
            self.color = ORANGE

        elif enemy_type == "strong":
            self.speed = 1.2
            self.hp = 3
            self.color = PURPLE

        else:
            self.speed = 1.6
            self.hp = 2
            self.color = DARK_GREEN

        self.animation = random.random() * 6

    @property
    def rect(self):

        return pygame.Rect(
            int(self.x - self.width / 2),
            int(self.y - self.height),
            self.width,
            self.height
        )

    def update(self, player):

        self.animation += 0.1

        if self.enemy_type == "fast":

            if player.x < self.x:
                self.direction = -1
            else:
                self.direction = 1

        else:

            self.x += self.direction * self.speed

            if self.x < 30:
                self.direction = 1

            if self.x > WIDTH - 30:
                self.direction = -1

    def damage(self):

        self.hp -= 1

        create_particles(
            self.x,
            self.y - 20,
            RED,
            8
        )

    def draw(self, surface):

        bounce = math.sin(self.animation) * 2

        x = int(self.x)
        y = int(self.y + bounce)

        # ciało
        pygame.draw.ellipse(
            surface,
            self.color,
            (x - 21, y - 34, 42, 32)
        )

        # ogon
        pygame.draw.line(
            surface,
            self.color,
            (x - 15, y - 20),
            (x - 35 * self.direction, y - 28),
            8
        )

        # oczy
        pygame.draw.circle(
            surface,
            WHITE,
            (x - 10, y - 35),
            7
        )

        pygame.draw.circle(
            surface,
            WHITE,
            (x + 10, y - 35),
            7
        )

        pygame.draw.circle(
            surface,
            BLACK,
            (x - 10, y - 35),
            3
        )

        pygame.draw.circle(
            surface,
            BLACK,
            (x + 10, y - 35),
            3
        )


# ============================================================
# JĘZYK ŻABY
# ============================================================


class Tongue:

    def __init__(self, x, y, direction):

        self.x = x
        self.y = y
        self.direction = direction

        self.life = 8

    def update(self):

        self.life -= 1

    def draw(self, surface):

        length = 85

        pygame.draw.line(
            surface,
            RED,
            (self.x, self.y),
            (
                self.x + length * self.direction,
                self.y
            ),
            6
        )

        pygame.draw.circle(
            surface,
            RED,
            (
                int(self.x + length * self.direction),
                int(self.y)
            ),
            5
        )


# ============================================================
# FROGGY
# ============================================================


class Froggy:

    def __init__(self, x, y):

        self.x = x
        self.y = y

        self.width = 44
        self.height = 48

        self.vx = 0
        self.vy = 0

        self.speed = 5
        self.jump_power = 13

        self.hp = 3
        self.max_hp = 3

        self.on_ground = False

        self.jumps_left = 1

        self.facing = 1

        self.attack_cooldown = 0

        self.dash_cooldown = 0
        self.dash_timer = 0

        self.invincible = 0

        self.animation = 0

    @property
    def rect(self):

        return pygame.Rect(
            int(self.x - self.width / 2),
            int(self.y - self.height),
            self.width,
            self.height
        )

    def jump(self):

        if self.on_ground:

            self.vy = -self.jump_power

            self.on_ground = False

            self.jumps_left = 1

            return

        if self.jumps_left > 0:

            self.vy = -self.jump_power * 0.9

            self.jumps_left -= 1

    def damage(self):

        if self.invincible > 0:
            return False

        self.hp -= 1

        self.invincible = 90

        create_particles(
            self.x,
            self.y - 25,
            RED,
            15
        )

        return self.hp <= 0

    def dash(self):

        if self.dash_cooldown > 0:
            return

        self.x += self.facing * 120

        self.x = clamp(
            self.x,
            25,
            WIDTH - 25
        )

        self.dash_timer = 15
        self.dash_cooldown = 90

        create_particles(
            self.x,
            self.y - 20,
            CYAN,
            15
        )

    def update(self):

        if self.attack_cooldown > 0:
            self.attack_cooldown -= 1

        if self.dash_cooldown > 0:
            self.dash_cooldown -= 1

        if self.dash_timer > 0:
            self.dash_timer -= 1

        if self.invincible > 0:
            self.invincible -= 1

        self.animation += 0.15

    def draw(self, surface):

        # migotanie po obrażeniach
        if self.invincible > 0:

            if (self.invincible // 5) % 2 == 0:
                return

        bounce = math.sin(self.animation) * 2

        x = int(self.x)
        y = int(self.y + bounce)

        # nogi
        pygame.draw.ellipse(
            surface,
            DARK_GREEN,
            (x - 20, y - 12, 18, 12)
        )

        pygame.draw.ellipse(
            surface,
            DARK_GREEN,
            (x + 2, y - 12, 18, 12)
        )

        # ciało
        pygame.draw.ellipse(
            surface,
            GREEN,
            (x - 21, y - 42, 42, 36)
        )

        # oczy
        pygame.draw.circle(
            surface,
            LIGHT_GREEN,
            (x - 13, y - 43),
            10
        )

        pygame.draw.circle(
            surface,
            LIGHT_GREEN,
            (x + 13, y - 43),
            10
        )

        pygame.draw.circle(
            surface,
            BLACK,
            (x - 13, y - 43),
            4
        )

        pygame.draw.circle(
            surface,
            BLACK,
            (x + 13, y - 43),
            4
        )

        # uśmiech
        pygame.draw.arc(
            surface,
            DARK_GREEN,
            (x - 12, y - 36, 24, 15),
            0,
            math.pi,
            2
        )

        # dash
        if self.dash_timer > 0:

            pygame.draw.circle(
                surface,
                CYAN,
                (x, y - 22),
                32,
                3
            )


# ============================================================
# POZIOM
# ============================================================


def create_level():

    platforms = [

        # ziemia
        Platform(
            0,
            650,
            WIDTH,
            50
        ),

        # platformy
        Platform(
            60,
            550,
            180,
            25
        ),

        Platform(
            310,
            475,
            170,
            25
        ),

        Platform(
            540,
            390,
            180,
            25
        ),

        Platform(
            780,
            500,
            160,
            25
        ),

        Platform(
            900,
            350,
            170,
            25
        ),

        Platform(
            420,
            300,
            120,
            25
        ),
    ]

    coins_list = [

        Coin(140, 510),
        Coin(395, 435),
        Coin(630, 350),
        Coin(850, 460),
        Coin(970, 310),
        Coin(480, 260),
    ]

    enemies = [

        Enemy(
            210,
            650,
            "normal"
        ),

        Enemy(
            420,
            475,
            "fast"
        ),

        Enemy(
            630,
            390,
            "strong"
        ),

        Enemy(
            850,
            500,
            "normal"
        ),

        Enemy(
            980,
            350,
            "fast"
        ),
    ]

    return platforms, coins_list, enemies


# ============================================================
# PARKOUR
# ============================================================


def run_game():

    global coins
    global score
    global particles

    player = Froggy(
        80,
        600
    )

    platforms, coin_list, enemies = create_level()

    tongue = None

    timer = 0
    level_time = 90

    won = False
    lost = False

    while True:

        dt = clock.tick(FPS) / 1000

        # ====================================================
        # EVENTY
        # ====================================================

        for event in pygame.event.get():

            if event.type == pygame.QUIT:

                pygame.quit()
                sys.exit()

            if event.type == pygame.KEYDOWN:

                # ESC
                if event.key == pygame.K_ESCAPE:
                    return

                # SKOK
                if event.key == pygame.K_UP:
                    if not won and not lost:
                        player.jump()

                # ATTACK
                if event.key == pygame.K_SPACE:

                    if (
                        player.attack_cooldown <= 0
                        and not won
                        and not lost
                    ):

                        tongue = Tongue(
                            player.x,
                            player.y - 25,
                            player.facing
                        )

                        player.attack_cooldown = 20

                        # sprawdzanie przeciwników
                        for enemy in enemies:

                            if enemy.hp <= 0:
                                continue

                            distance_x = enemy.x - player.x
                            distance_y = enemy.y - player.y

                            in_range = (
                                abs(distance_x) < 100
                                and abs(distance_y) < 70
                            )

                            correct_direction = (
                                distance_x * player.facing > -20
                            )

                            if in_range and correct_direction:

                                enemy.damage()

                                if enemy.hp <= 0:
                                    score += 150
                                    create_particles(
                                        enemy.x,
                                        enemy.y - 20,
                                        ORANGE,
                                        20
                                    )

                # DASH
                if event.key == pygame.K_LSHIFT:

                    if not won and not lost:
                        player.dash()

                # ENTER
                if event.key == pygame.K_RETURN:

                    if won or lost:
                        return

        # ====================================================
        # LOGIKA GRY
        # ====================================================

        if not won and not lost:

            keys = pygame.key.get_pressed()

            # ruch
            player.vx = 0

            if keys[pygame.K_LEFT]:

                player.vx = -player.speed
                player.facing = -1

            if keys[pygame.K_RIGHT]:

                player.vx = player.speed
                player.facing = 1

            player.x += player.vx

            # grawitacja
            player.vy += 0.65

            player.y += player.vy

            player.on_ground = False

            # =================================================
            # KOLIZJE Z PLATFORMAMI
            # =================================================

            for platform in platforms:

                if player.rect.colliderect(platform.rect):

                    # tylko gdy spada
                    if player.vy >= 0:

                        if (
                            player.rect.bottom
                            <= platform.rect.bottom + 15
                        ):

                            player.y = platform.rect.top

                            player.vy = 0

                            player.on_ground = True

                            player.jumps_left = 1

            # ograniczenie poziome
            player.x = clamp(
                player.x,
                20,
                WIDTH - 20
            )

            # =================================================
            # SPADNIĘCIE
            # =================================================

            if player.y > HEIGHT + 100:

                lost = True

            # =================================================
            # TIMER
            # =================================================

            timer += dt

            if timer >= level_time:

                lost = True

            # =================================================
            # PLAYER TIMERS
            # =================================================

            player.update()

            # =================================================
            # ENEMIES
            # =================================================

            for enemy in enemies:

                if enemy.hp <= 0:
                    continue

                enemy.update(player)

                if player.rect.colliderect(enemy.rect):

                    if player.damage():

                        lost = True

            # =================================================
            # MONETY
            # =================================================

            for coin in coin_list:

                coin.update()

                if coin.collected:
                    continue

                distance = math.hypot(
                    player.x - coin.x,
                    player.y - coin.y
                )

                if distance < 35:

                    coin.collected = True

                    coins += 1
                    score += 100

                    create_particles(
                        coin.x,
                        coin.y,
                        GOLD,
                        12
                    )

            # =================================================
            # META
            # =================================================

            if (
                player.x >= WIDTH - 55
                and player.y < 450
            ):

                won = True

                score += 1000

        # ====================================================
        # TONGUE
        # ====================================================

        if tongue:

            tongue.update()

            if tongue.life <= 0:

                tongue = None

        # ====================================================
        # PARTICLES
        # ====================================================

        for particle in particles[:]:

            particle.update()

            if particle.life <= 0:

                particles.remove(particle)

        # ====================================================
        # RYSOWANIE
        # ====================================================

        screen.fill(SKY)

        # słońce
        pygame.draw.circle(
            screen,
            (255, 235, 120),
            (950, 90),
            50
        )

        # chmury
        clouds = [
            (150, 100),
            (500, 130),
            (800, 80)
        ]

        for cx, cy in clouds:

            pygame.draw.circle(
                screen,
                WHITE,
                (cx, cy),
                25
            )

            pygame.draw.circle(
                screen,
                WHITE,
                (cx + 25, cy + 5),
                30
            )

            pygame.draw.circle(
                screen,
                WHITE,
                (cx - 25, cy + 5),
                20
            )

        # ====================================================
        # PLATFORMS
        # ====================================================

        for platform in platforms:

            platform.draw(screen)

        # ====================================================
        # META
        # ====================================================

        pygame.draw.rect(
            screen,
            YELLOW,
            (WIDTH - 65, 260, 25, 90)
        )

        draw_text(
            screen,
            "FINISH",
            FONT_SMALL,
            BLACK,
            WIDTH - 100,
            225
        )

        # ====================================================
        # COINS
        # ====================================================

        for coin in coin_list:

            coin.draw(screen)

        # ====================================================
        # ENEMIES
        # ====================================================

        for enemy in enemies:

            if enemy.hp > 0:

                enemy.draw(screen)

        # ====================================================
        # TONGUE
        # ====================================================

        if tongue:

            tongue.draw(screen)

        # ====================================================
        # PLAYER
        # ====================================================

        player.draw(screen)

        # ====================================================
        # PARTICLES
        # ====================================================

        for particle in particles:

            particle.draw(screen)

        # ====================================================
        # HUD
        # ====================================================

        pygame.draw.rect(
            screen,
            (20, 30, 35),
            (0, 0, WIDTH, 75)
        )

        draw_text(
            screen,
            "FROGGY JUMPS",
            FONT,
            WHITE,
            20,
            15
        )

        draw_health(
            screen,
            230,
            18,
            player.hp,
            player.max_hp,
            150
        )

        draw_text(
            screen,
            f"COINS: {coins}",
            FONT,
            GOLD,
            400,
            15
        )

        remaining = max(
            0,
            int(level_time - timer)
        )

        timer_color = (
            YELLOW
            if remaining > 20
            else RED
        )

        draw_text(
            screen,
            f"TIME: {remaining}",
            FONT,
            timer_color,
            560,
            15
        )

        draw_text(
            screen,
            "← → MOVE",
            FONT_SMALL,
            WHITE,
            700,
            10
        )

        draw_text(
            screen,
            "↑ JUMP",
            FONT_SMALL,
            WHITE,
            700,
            35
        )

        draw_text(
            screen,
            "SPACE ATTACK",
            FONT_SMALL,
            RED,
            800,
            10
        )

        draw_text(
            screen,
            "SHIFT DASH",
            FONT_SMALL,
            CYAN,
            800,
            35
        )

        # ====================================================
        # WIN / LOSE
        # ====================================================

        if won or lost:

            pygame.draw.rect(
                screen,
                (15, 20, 25),
                (250, 210, 600, 250),
                border_radius=20
            )

            if won:

                draw_text(
                    screen,
                    "LEVEL COMPLETE!",
                    FONT_BIG,
                    GREEN,
                    WIDTH // 2,
                    275,
                    True
                )

                draw_text(
                    screen,
                    "+1000 SCORE",
                    FONT,
                    GOLD,
                    WIDTH // 2,
                    340,
                    True
                )

            else:

                draw_text(
                    screen,
                    "FROGGY LOST!",
                    FONT_BIG,
                    RED,
                    WIDTH // 2,
                    275,
                    True
                )

                draw_text(
                    screen,
                    "TRY AGAIN!",
                    FONT,
                    WHITE,
                    WIDTH // 2,
                    340,
                    True
                )

            draw_text(
                screen,
                "PRESS ENTER TO RETURN",
                FONT,
                WHITE,
                WIDTH // 2,
                400,
                True
            )

        pygame.display.flip()


# ============================================================
# MENU
# ============================================================


def main():

    global particles

    while True:

        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_RETURN:
                    run_game()

                if event.key == pygame.K_1:
                    run_game()

        # ====================================================
        # MENU
        # ====================================================

        screen.fill((20, 35, 45))

        # dekoracje
        for i in range(20):

            x = (i * 83) % WIDTH
            y = 80 + (i * 47) % 500

            pygame.draw.circle(
                screen,
                (35, 70, 75),
                (x, y),
                3
            )

        # tytuł
        draw_text(
            screen,
            "FROGGY",
            FONT_BIG,
            GREEN,
            WIDTH // 2,
            120,
            True
        )

        draw_text(
            screen,
            "JUMPS",
            FONT_MED,
            LIGHT_GREEN,
            WIDTH // 2,
            170,
            True
        )

        # żabka
        frog = Froggy(
            WIDTH // 2,
            260
        )

        frog.animation = pygame.time.get_ticks() / 300

        frog.draw(screen)

        # przycisk
        button = pygame.Rect(
            330,
            350,
            440,
            90
        )

        mouse = pygame.mouse.get_pos()

        hover = button.collidepoint(mouse)

        button_color = (
            (55, 100, 70)
            if hover
            else (35, 65, 50)
        )

        pygame.draw.rect(
            screen,
            button_color,
            button,
            border_radius=15
        )

        pygame.draw.rect(
            screen,
            GREEN,
            button,
            3,
            border_radius=15
        )

        draw_text(
            screen,
            "START GAME",
            FONT_MED,
            WHITE,
            button.centerx,
            button.centery,
            True
        )

        # instrukcje
        draw_text(
            screen,
            "1 / ENTER = START",
            FONT,
            WHITE,
            WIDTH // 2,
            490,
            True
        )

        draw_text(
            screen,
            "← → MOVE     ↑ JUMP     SPACE ATTACK",
            FONT_SMALL,
            GRAY,
            WIDTH // 2,
            535,
            True
        )

        draw_text(
            screen,
            "SHIFT = DASH",
            FONT_SMALL,
            CYAN,
            WIDTH // 2,
            565,
            True
        )

        draw_text(
            screen,
            f"COINS: {coins}",
            FONT,
            GOLD,
            30,
            30
        )

        # kliknięcie
        if pygame.mouse.get_pressed()[0]:

            if button.collidepoint(mouse):

                run_game()

        pygame.display.flip()

        clock.tick(FPS)


# ============================================================
# START
# ============================================================

if __name__ == "__main__":
    main()


# ============================================================
# FROGGY TANKS - PROSTA WERSJA
# ============================================================

class TankWall:
    def __init__(self, x, y, width, height):
        self.rect = pygame.Rect(x, y, width, height)

    def draw(self, surface):
        pygame.draw.rect(
            surface,
            BROWN,
            self.rect,
            border_radius=6
        )

        pygame.draw.rect(
            surface,
            DARK_GRAY,
            self.rect,
            3,
            border_radius=6
        )


class SimpleBullet:
    def __init__(self, x, y, vx, vy, owner):
        self.x = x
        self.y = y
        self.vx = vx
        self.vy = vy

        self.owner = owner
        self.radius = 6
        self.life = 120

    def update(self):
        self.x += self.vx
        self.y += self.vy
        self.life -= 1

    def draw(self, surface):
        color = YELLOW if self.owner == "player" else RED

        pygame.draw.circle(
            surface,
            color,
            (int(self.x), int(self.y)),
            self.radius
        )

        pygame.draw.circle(
            surface,
            WHITE,
            (int(self.x - 2), int(self.y - 2)),
            2
        )


class SimpleTank:
    def __init__(self, x, y, color, enemy=False):
        self.x = x
        self.y = y

        self.color = color
        self.enemy = enemy

        self.width = 52
        self.height = 42

        self.speed = 3 if not enemy else 1.5

        self.hp = 10
        self.max_hp = 10

        self.angle = 0

        self.reload = 0

        # Tylko dla AI
        self.ai_timer = 0

    @property
    def rect(self):
        return pygame.Rect(
            int(self.x - self.width / 2),
            int(self.y - self.height / 2),
            self.width,
            self.height
        )

    def move(self, dx, dy, walls):
        if dx != 0 or dy != 0:

            length = math.hypot(dx, dy)

            if length > 0:
                dx /= length
                dy /= length

            # Ruch X
            old_x = self.x
            self.x += dx * self.speed

            self.x = clamp(
                self.x,
                50,
                WIDTH - 50
            )

            if self.collides_with_walls(walls):
                self.x = old_x

            # Ruch Y
            old_y = self.y
            self.y += dy * self.speed

            self.y = clamp(
                self.y,
                125,
                HEIGHT - 50
            )

            if self.collides_with_walls(walls):
                self.y = old_y

    def collides_with_walls(self, walls):
        for wall in walls:
            if self.rect.colliderect(wall.rect):
                return True

        return False

    def shoot(self, target_x, target_y, bullets):
        if self.reload > 0:
            return

        dx = target_x - self.x
        dy = target_y - self.y

        distance = max(1, math.hypot(dx, dy))

        self.angle = math.atan2(dy, dx)

        speed = 8

        bullet_x = (
            self.x +
            math.cos(self.angle) * 38
        )

        bullet_y = (
            self.y +
            math.sin(self.angle) * 38
        )

        owner = "enemy" if self.enemy else "player"

        bullets.append(
            SimpleBullet(
                bullet_x,
                bullet_y,
                dx / distance * speed,
                dy / distance * speed,
                owner
            )
        )

        self.reload = 30

    def update(self):
        if self.reload > 0:
            self.reload -= 1

    def draw(self, surface):
        # cień
        pygame.draw.ellipse(
            surface,
            (25, 25, 25),
            (
                int(self.x - 34),
                int(self.y - 18),
                68,
                42
            )
        )

        # gąsienice
        pygame.draw.rect(
            surface,
            DARK_GRAY,
            (
                int(self.x - 32),
                int(self.y - 22),
                64,
                44
            ),
            border_radius=7
        )

        # korpus
        pygame.draw.rect(
            surface,
            self.color,
            (
                int(self.x - 25),
                int(self.y - 17),
                50,
                34
            ),
            border_radius=6
        )

        # wieża
        pygame.draw.circle(
            surface,
            self.color,
            (int(self.x), int(self.y)),
            18
        )

        # lufa
        barrel_length = 42

        end_x = (
            self.x +
            math.cos(self.angle) *
            barrel_length
        )

        end_y = (
            self.y +
            math.sin(self.angle) *
            barrel_length
        )

        pygame.draw.line(
            surface,
            DARK_GRAY,
            (int(self.x), int(self.y)),
            (int(end_x), int(end_y)),
            10
        )

        pygame.draw.line(
            surface,
            BLACK,
            (int(self.x), int(self.y)),
            (int(end_x), int(end_y)),
            5
        )

        # HP
        draw_health(
            surface,
            int(self.x - 30),
            int(self.y - 42),
            self.hp,
            self.max_hp,
            60
        )


def create_simple_tank_level():
    walls = [
        # górne ściany
        TankWall(300, 160, 180, 35),
        TankWall(650, 160, 180, 35),

        # środek
        TankWall(450, 300, 200, 40),

        # lewa strona
        TankWall(150, 300, 45, 180),

        # prawa strona
        TankWall(900, 300, 45, 180),

        # dół
        TankWall(300, 520, 180, 35),
        TankWall(650, 520, 180, 35),

        # małe przeszkody
        TankWall(250, 400, 100, 35),
        TankWall(750, 400, 100, 35),
    ]

    return walls


def run_tanks():
    global coins, total_score, particles

    # --------------------------------------------------------
    # GRACZ
    # --------------------------------------------------------

    player = SimpleTank(
        WIDTH // 2,
        HEIGHT - 100,
        GREEN,
        enemy=False
    )

    # --------------------------------------------------------
    # ŚCIANY
    # --------------------------------------------------------

    walls = create_simple_tank_level()

    # --------------------------------------------------------
    # PRZECIWNICY
    # --------------------------------------------------------

    enemies = [
        SimpleTank(150, 180, RED, True),
        SimpleTank(850, 180, RED, True),
        SimpleTank(150, 550, ORANGE, True),
        SimpleTank(850, 550, PURPLE, True),
    ]

    # --------------------------------------------------------
    # POCISKI
    # --------------------------------------------------------

    bullets = []

    running = True
    won = False
    lost = False

    # ========================================================
    # GŁÓWNA PĘTLA
    # ========================================================

    while running:

        clock.tick(FPS)

        # ----------------------------------------------------
        # EVENTY
        # ----------------------------------------------------

        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_ESCAPE:
                    return

                # ENTER po zakończeniu
                if event.key == pygame.K_RETURN:

                    if won or lost:
                        return

        # ----------------------------------------------------
        # MYSZKA
        # ----------------------------------------------------

        mouse_x, mouse_y = pygame.mouse.get_pos()

        # ----------------------------------------------------
        # GRACZ
        # ----------------------------------------------------

        if not won and not lost:

            # ---------------- RUCH ----------------

            dx = 0
            dy = 0

            keys = pygame.key.get_pressed()

            if keys[pygame.K_w]:
                dy -= 1

            if keys[pygame.K_s]:
                dy += 1

            if keys[pygame.K_a]:
                dx -= 1

            if keys[pygame.K_d]:
                dx += 1

            player.move(
                dx,
                dy,
                walls
            )

            # ---------------- CELOWANIE ----------------

            player.angle = math.atan2(
                mouse_y - player.y,
                mouse_x - player.x
            )

            # ---------------- STRZELANIE ----------------

            if pygame.mouse.get_pressed()[0]:

                player.shoot(
                    mouse_x,
                    mouse_y,
                    bullets
                )

            player.update()

            # ------------------------------------------------
            # AI PRZECIWNIKÓW
            # ------------------------------------------------

            for enemy in enemies:

                if enemy.hp <= 0:
                    continue

                dx = player.x - enemy.x
                dy = player.y - enemy.y

                distance = max(
                    1,
                    math.hypot(dx, dy)
                )

                # celowanie
                enemy.angle = math.atan2(
                    dy,
                    dx
                )

                # ---------------- RUCH ----------------

                if distance > 280:

                    enemy.move(
                        dx / distance,
                        dy / distance,
                        walls
                    )

                # ---------------- STRZAŁ ----------------

                if distance < 600:

                    enemy.shoot(
                        player.x,
                        player.y,
                        bullets
                    )

                enemy.update()

            # ------------------------------------------------
            # POCISKI
            # ------------------------------------------------

            for bullet in bullets[:]:

                bullet.update()

                remove_bullet = False

                # --------------------------------------------
                # CZY POCISK WYSZEDŁ POZA ARENĘ?
                # --------------------------------------------

                if (
                    bullet.life <= 0 or
                    bullet.x < 20 or
                    bullet.x > WIDTH - 20 or
                    bullet.y < 100 or
                    bullet.y > HEIGHT
                ):
                    remove_bullet = True

                # --------------------------------------------
                # KOLIZJA ZE ŚCIANĄ
                # --------------------------------------------

                if not remove_bullet:

                    for wall in walls:

                        if wall.rect.collidepoint(
                            int(bullet.x),
                            int(bullet.y)
                        ):

                            explosion(
                                bullet.x,
                                bullet.y,
                                ORANGE,
                                8
                            )

                            remove_bullet = True
                            break

                # --------------------------------------------
                # POCISK GRACZA
                # --------------------------------------------

                if (
                    not remove_bullet and
                    bullet.owner == "player"
                ):

                    for enemy in enemies:

                        if enemy.hp <= 0:
                            continue

                        if math.hypot(
                            bullet.x - enemy.x,
                            bullet.y - enemy.y
                        ) < 30:

                            enemy.hp -= 2

                            explosion(
                                bullet.x,
                                bullet.y,
                                YELLOW,
                                12
                            )

                            remove_bullet = True

                            if enemy.hp <= 0:

                                explosion(
                                    enemy.x,
                                    enemy.y,
                                    ORANGE,
                                    30
                                )

                                coins += 1
                                total_score += 100

                            break

                # --------------------------------------------
                # POCISK PRZECIWNIKA
                # --------------------------------------------

                if (
                    not remove_bullet and
                    bullet.owner == "enemy"
                ):

                    if math.hypot(
                        bullet.x - player.x,
                        bullet.y - player.y
                    ) < 32:

                        player.hp -= 1

                        explosion(
                            bullet.x,
                            bullet.y,
                            RED,
                            15
                        )

                        remove_bullet = True

                        if player.hp <= 0:
                            lost = True

                # --------------------------------------------
                # USUNIĘCIE POCISKU
                # --------------------------------------------

                if remove_bullet:

                    if bullet in bullets:
                        bullets.remove(bullet)

            # ------------------------------------------------
            # WYGRANA
            # ------------------------------------------------

            alive_enemies = [
                enemy
                for enemy in enemies
                if enemy.hp > 0
            ]

            if len(alive_enemies) == 0:

                won = True

                total_score += 500

            # ------------------------------------------------
            # PRZEGRANA
            # ------------------------------------------------

            if player.hp <= 0:

                lost = True

        # ====================================================
        # PARTICLE
        # ====================================================

        for particle in particles[:]:

            particle.update()

            if particle.life <= 0:
                particles.remove(particle)

        # ====================================================
        # RYSOWANIE
        # ====================================================

        screen.fill(
            (55, 75, 65)
        )

        # ----------------------------------------------------
        # ARENA
        # ----------------------------------------------------

        pygame.draw.rect(
            screen,
            (70, 90, 70),
            (
                20,
                100,
                WIDTH - 40,
                HEIGHT - 120
            )
        )

        # ----------------------------------------------------
        # SIATKA
        # ----------------------------------------------------

        for x in range(
            25,
            WIDTH - 25,
            50
        ):

            pygame.draw.line(
                screen,
                (65, 84, 65),
                (x, 105),
                (x, HEIGHT - 25)
            )

        for y in range(
            105,
            HEIGHT - 25,
            50
        ):

            pygame.draw.line(
                screen,
                (65, 84, 65),
                (25, y),
                (WIDTH - 25, y)
            )

        # ----------------------------------------------------
        # ŚCIANY
        # ----------------------------------------------------

        for wall in walls:
            wall.draw(screen)

        # ----------------------------------------------------
        # POCISKI
        # ----------------------------------------------------

        for bullet in bullets:
            bullet.draw(screen)

        # ----------------------------------------------------
        # PRZECIWNICY
        # ----------------------------------------------------

        for enemy in enemies:

            if enemy.hp > 0:
                enemy.draw(screen)

        # ----------------------------------------------------
        # GRACZ
        # ----------------------------------------------------

        player.draw(screen)

        # ----------------------------------------------------
        # PARTICLES
        # ----------------------------------------------------

        for particle in particles:
            particle.draw(screen)

        # ====================================================
        # HUD
        # ====================================================

        pygame.draw.rect(
            screen,
            (20, 25, 30),
            (0, 0, WIDTH, 80)
        )

        text(
            screen,
            "FROGGY TANKS",
            FONT,
            WHITE,
            20,
            15
        )

        draw_health(
            screen,
            220,
            20,
            player.hp,
            player.max_hp,
            170
        )

        text(
            screen,
            f"HP: {player.hp}/{player.max_hp}",
            FONT_SMALL,
            WHITE,
            400,
            22
        )

        text(
            screen,
            f"COINS: {coins}",
            FONT,
            GOLD,
            510,
            17
        )

        alive_count = sum(
            1
            for enemy in enemies
            if enemy.hp > 0
        )

        text(
            screen,
            f"ENEMIES: {alive_count}",
            FONT,
            RED,
            670,
            17
        )

        text(
            screen,
            "WASD: MOVE",
            FONT_SMALL,
            WHITE,
            20,
            HEIGHT - 30
        )

        text(
            screen,
            "MOUSE: AIM",
            FONT_SMALL,
            WHITE,
            150,
            HEIGHT - 30
        )

        text(
            screen,
            "LMB: SHOOT",
            FONT_SMALL,
            YELLOW,
            280,
            HEIGHT - 30
        )

        text(
            screen,
            "ESC: MENU",
            FONT_SMALL,
            WHITE,
            420,
            HEIGHT - 30
        )

        # ====================================================
        # KONIEC GRY
        # ====================================================

        if won or lost:

            pygame.draw.rect(
                screen,
                (15, 20, 25),
                (250, 220, 600, 220),
                border_radius=20
            )

            if won:

                text(
                    screen,
                    "ARENA CLEARED!",
                    FONT_BIG,
                    GREEN,
                    WIDTH // 2,
                    280,
                    True
                )

                text(
                    screen,
                    "+500 SCORE",
                    FONT,
                    GOLD,
                    WIDTH // 2,
                    340,
                    True
                )

            else:

                text(
                    screen,
                    "TANK DESTROYED!",
                    FONT_BIG,
                    RED,
                    WIDTH // 2,
                    280,
                    True
                )

            text(
                screen,
                "ENTER = MENU",
                FONT,
                WHITE,
                WIDTH // 2,
                395,
                True
            )

        # ----------------------------------------------------
        # UPDATE EKRANU
        # ----------------------------------------------------

        pygame.display.flip()
