import pygame
import random
import os

pygame.init()

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

def load_img(name):
    return pygame.image.load(os.path.join(BASE_DIR, name)).convert_alpha()


# =============================
# 화면 설정
# =============================
screen_width = 1200
screen_height = 673
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Frog Jump Game")

clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 36)
big_font = pygame.font.SysFont(None, 72)

# =============================
# 배경
# =============================
background = load_img("background_mygame.png")
prologue_background = load_img("background_mygame_Prologue.png")
start_background = load_img("background_mygame_start.PNG")
# =============================
# 개구리 이미지
# =============================
frog_normal = load_img("frog_normal.png")
frog_jump = load_img("frog_jump.png")
frog_prepare = load_img("frog_prepare_jump.png")
frog_left = load_img("frog_left.png")
frog_right = load_img("frog_right.png")
character_img = frog_normal
rect = frog_normal.get_rect()

GROUND_Y = (screen_height - 170) - rect.height
MAX_JUMP_HEIGHT = 300

rect.x = screen_width // 2
rect.y = GROUND_Y

# =============================
# 이동 & 점프
# =============================
move_speed = 5
air_control = 0.6
gravity = 1.2
jump_speed = 14

jump_height = 0
velocity_y = 0
target_y = GROUND_Y

charging = False
jumping = False
falling = False

# =============================
# 파리
# =============================
fly_origin = load_img("fly.png")

class Fly:
    def __init__(self):
        self.size = random.randint(30, 70)
        self.image = pygame.transform.scale(fly_origin, (self.size, self.size))
        self.rect = self.image.get_rect()
        self.rect.x = random.randint(0, screen_width - self.size)
        self.rect.y = random.randint(GROUND_Y - 250, GROUND_Y - 50)
        self.big = self.size == 70

flies = [Fly() for _ in range(5)]

# =============================
# 점수 / 시간
# =============================
score = 0
GAME_TIME = 60
start_ticks = pygame.time.get_ticks()

# =============================
# 랭킹
# =============================
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
RANK_FILE = os.path.join(BASE_DIR, "ranking.txt")


def load_ranking():
    if not os.path.exists(RANK_FILE):
        return []
    with open(RANK_FILE, "r") as f:
        return [int(line.strip()) for line in f.readlines()]

def save_score(new_score):
    ranks = load_ranking()
    ranks.append(new_score)
    ranks = sorted(ranks, reverse=True)[:5]
    with open(RANK_FILE, "w") as f:
        for r in ranks:
            f.write(str(r) + "\n")
    return ranks

ranking = []

# =============================
# 점프 게이지
# =============================
def draw_jump_gauge():
    gauge_w = 120
    gauge_h = 14
    x = screen_width // 2 - gauge_w // 2
    y = screen_height - 35

    ratio = jump_height / MAX_JUMP_HEIGHT
    color = (0, 200, 0) if ratio < 0.6 else (230, 180, 0) if ratio < 0.85 else (230, 50, 50)

    pygame.draw.rect(screen, (40, 40, 40), (x, y, gauge_w, gauge_h))
    pygame.draw.rect(screen, color, (x, y, int(gauge_w * ratio), gauge_h))

# =============================
# 게임 상태
# =============================
STATE_PROLOGUE = "prologue"
STATE_START = "start"
STATE_GAME = "game"

game_state = STATE_PROLOGUE

# =============================
# 프롤로그 페이드 설정
# =============================
fade_alpha = 255
fade_speed = 3
fade_done_time = None

# =============================
# 메인 루프
# =============================
running = True
game_over = False
restart_pending = False

while running:
    clock.tick(60)

    elapsed = (pygame.time.get_ticks() - start_ticks) // 1000
    remaining_time = max(0, GAME_TIME - elapsed)

 # -------------------------
 # 이벤트
 # -------------------------
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        if game_state == STATE_START:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RETURN:
                    game_state = STATE_GAME
                    start_ticks = pygame.time.get_ticks()

        if game_state == STATE_GAME and not game_over:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE and not jumping:
                    charging = True
                    jump_height = 0
                    character_img = frog_prepare

            if event.type == pygame.KEYUP:
                if event.key == pygame.K_SPACE and charging:
                    charging = False
                    jumping = True
                    falling = False
                    target_y = GROUND_Y - jump_height
                    velocity_y = -jump_speed
                    character_img = frog_jump

        if game_over and event.type == pygame.KEYDOWN:
            if event.key == pygame.K_r:
                restart_pending = True

    # -------------------------
    # 게임 진행
    # -------------------------
    if not game_over:
        keys = pygame.key.get_pressed()
        move = move_speed if not jumping else move_speed * air_control

        if keys[pygame.K_LEFT]:
            rect.x -= move
            if not jumping and not charging:
                character_img = frog_left
        elif keys[pygame.K_RIGHT]:
            rect.x += move
            if not jumping and not charging:
                character_img = frog_right
        elif not jumping and not charging:
            character_img = frog_normal

        rect.x = max(0, min(rect.x, screen_width - rect.width))

        if charging:
            ratio = jump_height / MAX_JUMP_HEIGHT
            jump_height += max(3, int(14 * (1 - ratio)) + 1)
            jump_height = min(jump_height, MAX_JUMP_HEIGHT)

        if jumping:
            rect.y += velocity_y

            if not falling and rect.y <= target_y:
                rect.y = target_y
                falling = True

            if falling:
                velocity_y += gravity

            if rect.y >= GROUND_Y:
                rect.y = GROUND_Y
                jumping = False
                falling = False
                velocity_y = 0
                character_img = frog_normal

        for fly in flies[:]:
            if rect.colliderect(fly.rect):
                score += 2 if fly.big else 1
                flies.remove(fly)
                flies.append(Fly())

        if remaining_time == 0 and not game_over:
            game_over = True
            ranking = save_score(score)

    # -------------------------
    # 그리기
    # -------------------------

    # 1️⃣ 프롤로그 화면
    if game_state == STATE_PROLOGUE:
        screen.blit(prologue_background, (0, 0))

        fade_surface = pygame.Surface((screen_width, screen_height))
        fade_surface.fill((0, 0, 0))
        fade_surface.set_alpha(fade_alpha)
        screen.blit(fade_surface, (0, 0))

        fade_alpha -= fade_speed
        if fade_alpha <= 0:
            fade_alpha = 0
            if fade_done_time is None:
                fade_done_time = pygame.time.get_ticks()
            if pygame.time.get_ticks() - fade_done_time >= 1000:
                game_state = STATE_START

        # 2️⃣ 게임 시작 화면
    elif game_state == STATE_START:
        screen.blit(start_background, (0, 0))       
        
        # 3️⃣ 실제 게임 화면
    else:
        screen.blit(background, (0, 0))

        for fly in flies:
            screen.blit(fly.image, fly.rect)

        screen.blit(character_img, rect)

        if charging:
            draw_jump_gauge()

        timer_color = (255, 80, 80) if remaining_time <= 10 and pygame.time.get_ticks() // 300 % 2 == 0 else (255, 255, 255)
        screen.blit(font.render(f"Time : {remaining_time}", True, timer_color), (screen_width - 150, 20))
        screen.blit(font.render(f"Score : {score}", True, (255, 255, 255)), (20, 20))


    # -------------------------
    # 게임 오버
    # -------------------------
    if game_over:
        overlay = pygame.Surface((screen_width, screen_height))
        overlay.set_alpha(180)
        overlay.fill((0, 0, 0))
        screen.blit(overlay, (0, 0))

        # 타이틀
        screen.blit(
            big_font.render("TIME OVER", True, (255, 80, 80)),
            (screen_width // 2 - 180, 80)
        )

        # 랭킹 제목
        screen.blit(
            font.render("RANKING", True, (255, 255, 255)),
            (screen_width // 2 - 50, 140)
        )

        # 랭킹 리스트 출력 (Top 5)
        rank_start_y = 180
        line_gap = 35

        for idx, s in enumerate(ranking):
            rank = idx + 1

            # 현재 플레이 점수 강조 (순위와 무관)
            color = (255, 200, 0) if s == score else (255, 255, 255)

            rank_text = f"{rank} : {s}"

            screen.blit(
                font.render(rank_text, True, color),
                (screen_width // 2 - 70, rank_start_y)
            )

            rank_start_y += line_gap

        # 재시작 안내
        screen.blit(
            font.render("R : Retry", True, (200, 200, 200)),
            (screen_width // 2 - 45, rank_start_y + 5 * 35 + 20)
        )

    # -------------------------
    # 🔥 프레임 종료 후 재시작 처리
    # -------------------------
    if restart_pending:
        score = 0
        flies = [Fly() for _ in range(5)]
        rect.x = screen_width // 2
        rect.y = GROUND_Y
        start_ticks = pygame.time.get_ticks()

        charging = False
        jumping = False
        falling = False
        velocity_y = 0
        jump_height = 0
        character_img = frog_normal

        ranking = []
        game_over = False
        restart_pending = False

    pygame.display.update()

pygame.quit()
