import pygame
import sys

#floor_score = 0
#if level_1 complete  floor_score = 1 if level_2 complete floor_score = 2
#if floor_score == 0:
#    show level 1
#elif floor_score == 1:
#    show level 2
#elif floor_score == 2:
#    show level 3
# if floor_score =2  and level_1 complete floor_score stays 2, goes one up in higher level completed



pygame.init()
pygame.mixer.init()

WIDTH, HEIGHT = 1920, 1080
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Goblin & Knight")

CLOCK = pygame.time.Clock()
BLACK = (0, 0, 0)
GRAVITY = 0.9
GROUND_Y = HEIGHT - 60

FPS = 60

BACKGROUND = pygame.image.load("images/back.png")
BACKGROUND = pygame.transform.scale(BACKGROUND, (WIDTH, HEIGHT))
BACK_MAIN = pygame.image.load("images/back_main.jpg")
BACK_MAIN = pygame.transform.scale(BACK_MAIN, (WIDTH, HEIGHT))

BG_MUSIC = None
try:
    BG_MUSIC = pygame.mixer.music
    pygame.mixer.music.load('music/musica.mp3')
    pygame.mixer.music.set_volume(1)
    pygame.mixer.music.play(-1)
except Exception:
    BG_MUSIC = None

FONT = pygame.font.SysFont(None, 32)

score_goblin = 0
score_knight = 0

paused = False



class Player:
    def __init__(self, x, y, sprites, scale, controls):
        self.start_x = x
        self.start_y = y

        self.x = float(x)
        self.y = float(y)

        self.y_velocity = 0.0
        self.jump_power = 18
        self.jumping = False
        self.facing_right = True
        self.moving = False
        self.speed = 5.5

        self.controls = controls

        self.anim_counter = 0
        self.ANIM_SPEED = 8

        self.stand = pygame.image.load(sprites["stand"]).convert_alpha()
        self.walk_left = pygame.image.load(sprites["walk_left"]).convert_alpha()
        self.walk_right = pygame.image.load(sprites["walk_right"]).convert_alpha()

        # support three-stage jump:
        # - sprites["jump"] can be a list/tuple of 3 paths [start, mid, end]
        # - or provide explicit keys "jump_start", "jump_mid", "jump_end"
        # - otherwise fallback to a single jump image (same for all stages)
        jump_entry = sprites.get("jump")
        if isinstance(jump_entry, (list, tuple)) and len(jump_entry) == 3:
            self.jump_start = pygame.image.load(jump_entry[0]).convert_alpha()
            self.jump_mid = pygame.image.load(jump_entry[1]).convert_alpha()
            self.jump_end = pygame.image.load(jump_entry[2]).convert_alpha()
        elif all(k in sprites for k in ("jump_start", "jump_mid", "jump_end")):
            self.jump_start = pygame.image.load(sprites["jump_start"]).convert_alpha()
            self.jump_mid = pygame.image.load(sprites["jump_mid"]).convert_alpha()
            self.jump_end = pygame.image.load(sprites["jump_end"]).convert_alpha()
        else:
            single_path = jump_entry if isinstance(jump_entry, str) else sprites.get("jump", sprites["stand"])
            single = pygame.image.load(single_path).convert_alpha()
            self.jump_start = self.jump_mid = self.jump_end = single

        self.stand = pygame.transform.scale(self.stand, (int(self.stand.get_width() * scale), int(self.stand.get_height() * scale)))
        self.walk_left = pygame.transform.scale(self.walk_left, (int(self.walk_left.get_width() * scale), int(self.walk_left.get_height() * scale)))
        self.walk_right = pygame.transform.scale(self.walk_right, (int(self.walk_right.get_width() * scale), int(self.walk_right.get_height() * scale)))
        self.jump_start = pygame.transform.scale(self.jump_start, (int(self.jump_start.get_width() * scale), int(self.jump_start.get_height() * scale)))
        self.jump_mid = pygame.transform.scale(self.jump_mid, (int(self.jump_mid.get_width() * scale), int(self.jump_mid.get_height() * scale)))
        self.jump_end = pygame.transform.scale(self.jump_end, (int(self.jump_end.get_width() * scale), int(self.jump_end.get_height() * scale)))

        self.surface = self.stand
        self.rect = self.surface.get_rect(midbottom=(self.x, self.y))

    
    def reset(self):
        self.x = self.start_x
        self.y = self.start_y
        self.y_velocity = 0
        self.jumping = False
        self.moving = False
        self.anim_counter = 0
        self.facing_right = True
        self.rect = self.surface.get_rect(midbottom=(self.x, self.y))

    
    def handle_input(self, keys):
        self.moving = False

        if keys[self.controls["right"]]:
            self.x += self.speed
            self.facing_right = True
            self.moving = True

        if keys[self.controls["left"]]:
            self.x -= self.speed
            self.facing_right = False
            self.moving = True

        if keys[self.controls["jump"]] and not self.jumping:
            self.jumping = True
            self.y_velocity = -self.jump_power

        
        if self.x < 0:
            self.x = 0
        if self.x > WIDTH:
            self.x = WIDTH

    
    def apply_gravity(self):
        self.y_velocity += GRAVITY
        self.y += self.y_velocity

        if self.y >= GROUND_Y:
            self.y = GROUND_Y
            self.y_velocity = 0
            self.jumping = False

    
    def update_animation(self):
        if self.jumping:
            # choose jump stage by vertical velocity:
            # - strong negative: start (ascending)
            # - near zero: mid (apex)
            # - positive: end (descending)
            up_thresh = -self.jump_power * 0.4
            down_thresh = self.jump_power * 0.4
            if self.y_velocity < up_thresh:
                self.surface = self.jump_start
            elif self.y_velocity > down_thresh:
                self.surface = self.jump_end
            else:
                self.surface = self.jump_mid
        elif self.moving:
            self.anim_counter += 1
            frame = (self.anim_counter // self.ANIM_SPEED) % 2
            self.surface = self.walk_left if frame == 0 else self.walk_right
        else:
            self.surface = self.stand

        if not self.facing_right:
            self.surface = pygame.transform.flip(self.surface, True, False)

        self.rect = self.surface.get_rect(midbottom=(int(self.x), int(self.y)))

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




goblin = Player(
    200, GROUND_Y,
    {
        "stand": "images/GoblinWorker/spritePics/stand_gob.png",
        "walk_left": "images/GoblinWorker/spritePics/walkleft.png",
        "walk_right": "images/GoblinWorker/spritePics/walkright.png",
        "jump": "images/GoblinWorker/spritePics/Jump.png"
    },
    3,
    {
        "left": pygame.K_a,
        "right": pygame.K_d,
        "jump": pygame.K_SPACE
    }
)

knight = Player(
    500, GROUND_Y,
    {
        "stand": "images/knight-named/stand.png",
        "walk_left": "images/knight-named/walkleft.png",
        "walk_right": "images/knight-named/walkright.png",
        "jump": [
            "images/knight-named/roll1.png",
            "images/knight-named/roll2.png",
            "images/knight-named/roll3.png"
        ]
    },
    3,
    {
        "left": pygame.K_KP4,
        "right": pygame.K_KP6,
        "jump": pygame.K_KP8
    }
)



door_image = pygame.image.load("images/door.png")
door_rect = door_image.get_rect(center=(800, 700))

button_play = pygame.image.load("images/play_button.png")
button_rect = button_play.get_rect(center=(500, 400))


def restart_level():
    goblin.reset()
    knight.reset()


level = 0
level_start_time = None

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_ESCAPE and level == 1:
                paused = not paused
            if event.key == pygame.K_r:
                restart_level()
                level = 0

    keys = pygame.key.get_pressed()
    mouse_pos = pygame.mouse.get_pos()

    SCREEN.fill((0, 0, 0))

    if level == 0:
        SCREEN.blit(BACK_MAIN, (0, 0))
        SCREEN.blit(button_play, button_rect)

        title_surf = FONT.render('Goblin & Knight', True, (255,255,255))
        SCREEN.blit(title_surf, (WIDTH//2 - title_surf.get_width()//2, 120))

        if button_rect.collidepoint(mouse_pos) and pygame.mouse.get_pressed()[0]:
            restart_level()
            level = 1
            level_start_time = pygame.time.get_ticks()
            if BG_MUSIC:
                try:
                    pygame.mixer.music.play(-1)
                except Exception:
                    pass

    elif level == 1:
        SCREEN.blit(BACKGROUND, (0, 0))
        SCREEN.blit(door_image, door_rect)

        if not paused:
        
            goblin.handle_input(keys)
            goblin.apply_gravity()
            goblin.update_animation()

 
            knight.handle_input(keys)
            knight.apply_gravity()
            knight.update_animation()

        goblin.draw(SCREEN)
        knight.draw(SCREEN)
        elapsed = 0
        if level_start_time:
            elapsed = (pygame.time.get_ticks() - level_start_time) // 1000
        hud_g = FONT.render(f'Goblin: {score_goblin}', True, (255,255,255))
        hud_k = FONT.render(f'Knight: {score_knight}', True, (255,255,255))
        hud_t = FONT.render(f'Time: {elapsed}s', True, (255,255,255))
        SCREEN.blit(hud_g, (20, 20))
        SCREEN.blit(hud_k, (WIDTH - hud_k.get_width() - 20, 20))
        SCREEN.blit(hud_t, (WIDTH//2 - hud_t.get_width()//2, 20))

        if paused:
            p = FONT.render('PAUSED - press ESC to resume', True, (255,255,0))
            SCREEN.blit(p, (WIDTH//2 - p.get_width()//2, HEIGHT//2 - 20))

        if goblin.rect.colliderect(door_rect) and keys[pygame.K_e]:
            score_goblin += 1
            restart_level()
            level = 0
            if BG_MUSIC:
                try:
                    pygame.mixer.music.stop()
                except Exception:
                    pass

        if knight.rect.colliderect(door_rect) and keys[pygame.K_KP5]:
            score_knight += 1
            restart_level()
            level = 0
            if BG_MUSIC:
                try:
                    pygame.mixer.music.stop()
                except Exception:
                    pass

    pygame.display.update()
    CLOCK.tick(FPS)