import pygame
import random
import math

# Initialize pygame and create a screen object
pygame.init()
screen = pygame.display.set_mode((1000, 800))

# Define grid size
GRID_WIDTH = 21
GRID_HEIGHT = 17

# Define initial floor position
FLOOR_START_ROW = GRID_HEIGHT - 2
FLOOR_END_ROW = GRID_HEIGHT - 1

pygame.display.set_caption('100% no luck')

# Load the images for the background, the player, and the boss
# Ensure that these images are present in your project directory
try:
  background = pygame.image.load('level_1_background.jpeg')
  player_image = pygame.image.load('player1_back.png')
  boss_image = pygame.image.load('level_1_boss.jpg')
  invisibility_cloak_image = pygame.image.load('invisibility_cloak.png')
  grappling_hook_image = pygame.image.load('grappling_hook.png')
  katana_image = pygame.image.load('katana.png')
  freezing_ray_image = pygame.image.load('freezing_ray.png')
  speed_pill_image = pygame.image.load('speed_pill.jpeg')
  bouncy_shoes_image = pygame.image.load('bouncy_shoes.png')
  key_image = pygame.image.load('key.png')
  tsunami_maker_image = pygame.image.load('tsunami_maker.png')
  laser_beam_image = pygame.image.load('laser_beam.png')
  go_kart_image = pygame.image.load('go_kart.jpeg')
  revival_kit_image = pygame.image.load('revival_kit.jpeg')
except pygame.error as e:
  print("Cannot load images:", e)
  raise SystemExit

# Define the colors for the text
WHITE = (255, 255, 255)

# Define the font for the text
font = pygame.font.SysFont('Arial', 32)

# Define the text for the intro and the tools
intro_text = "Welcome to 100% no luck, a game where you have to use smart logic and some luck to beat the dungeon. You will spawn with 3 tools out of a possible 15 tools randomized. Each tool has a different effect and can help you or hinder you depending on the situation. You have to think carefully about how to use your tools and when to use them. The dungeon has many obstacles and enemies that you have to overcome. The goal is to reach the end of the dungeon and defeat the boss. Good luck!"

tools_text = ["Invisibility cloak: Makes you invisible for 10 seconds. Useful for sneaking past enemies or traps.",
"Grappling hook: Allows you to swing across gaps or pull objects towards you.",
"Katana: A sharp sword that can cut through anything. Useful for fighting enemies or breaking barriers.",
"Freeze ray: A device that can freeze anything in its path. Useful for stopping enemies or creating platforms.",
"Bouncy shoes: Shoes that make you jump higher and farther. Useful for reaching high places or avoiding obstacles.",
"Key: A key that can unlock any door or chest. Useful for accessing hidden areas or treasures.",
"Go kart: A vehicle that can move fast and run over anything. Useful for escaping enemies or crossing large distances.",
"Tsunami maker: A device that can create a huge wave of water. Useful for washing away enemies or filling gaps.",
"Laser beam: A device that can shoot a powerful laser. Useful for destroying enemies or barriers.",
"Speed pill: A pill that can make you move faster for 10 seconds. Useful for dodging enemies or traps.",
"Revival kit: A kit that can revive you once if you die. Useful for surviving fatal situations."]

def show_intro():
  intro_text = "Welcome to 100% no luck, a game where you have to use smart logic and some luck to beat the dungeon. You will spawn with 3 tools out of a possible 15 tools randomized. Each tool has a different effect and can help you or hinder you depending on the situation. You have to think carefully about how to use your tools and when to use them. The dungeon has many obstacles and enemies that you have to overcome. The goal is to reach the end of the dungeon and defeat the boss. Good luck!"

  # Wrap the intro text
  intro_lines = []
  max_width = 950 # Adjust as needed
  words = intro_text.split()
  current_line = words[0]
  for word in words[1:]:
    if font.size(current_line + ' ' + word)[0] < max_width:
      current_line += ' ' + word
    else:
      intro_lines.append(current_line)
      current_line = word
  intro_lines.append(current_line)

  current_line = 0
  intro_complete = False
  start_time = pygame.time.get_ticks()

  while not intro_complete:
    for event in pygame.event.get():
      if event.type == pygame.QUIT:
        pygame.quit()
        sys.exit()

    screen.fill((0, 0, 0))
    intro_surface = font.render(intro_lines[current_line], True, WHITE)
    intro_rect = intro_surface.get_rect(center=(screen.get_width() // 2, screen.get_height() // 2))
    screen.blit(intro_surface, intro_rect)

    if pygame.time.get_ticks() - start_time > 2980:
      current_line += 1
      start_time = pygame.time.get_ticks()

    if current_line == len(intro_lines):
      intro_complete = True

    pygame.display.flip()
    pygame.time.Clock().tick(60)

  screen.fill((0, 0, 0))
  pygame.display.flip()

  tools_title_surface = font.render("Selected Tools:", True, WHITE)
  tools_title_rect = tools_title_surface.get_rect(center=(screen.get_width() // 2, 100))
  screen.blit(tools_title_surface, tools_title_rect)
  pygame.display.flip()

  pygame.time.delay(1000)

  selected_tools = random.sample(tools_text, 3)
   
  # Wrap the tool descriptions
  wrapped_tools = []
  for tool_desc in selected_tools:
    tool_lines = []
    current_line = tool_desc.split()[0]
    for word in tool_desc.split()[1:]:
      if font.size(current_line + ' ' + word)[0] < max_width:
        current_line += ' ' + word
      else:
        tool_lines.append(current_line)
        current_line = word
    tool_lines.append(current_line)
    wrapped_tools.append(tool_lines)

  selected_tools_surface = [font.render(line, True, WHITE) for tool_lines in wrapped_tools for line in tool_lines]

  for i, tool_surface in enumerate(selected_tools_surface):
    tool_rect = tool_surface.get_rect(center=(screen.get_width() // 2, 200 + i * 50))
    screen.blit(tool_surface, tool_rect)
    pygame.display.flip()

    start_time = pygame.time.get_ticks()
    while pygame.time.get_ticks() - start_time < 2000:
      for event in pygame.event.get():
        if event.type == pygame.QUIT:
          pygame.quit()
          sys.exit()

  screen.fill((0, 0, 0))
  pygame.display.flip()

# Define the logic for each tool as a function
def invisibility_cloak():
  # Set a global variable to indicate that the player is invisible
  global invisible
  invisible = True
  # Set a timer to make the player visible again after 10 seconds
  pygame.time.set_timer(pygame.USEREVENT, 10000)

def grappling_hook():
  # Get the mouse position and the player position
  mouse_x, mouse_y = pygame.mouse.get_pos()
  player_x, player_y = player_rect.center
  # Calculate the distance and the angle between the mouse and the player
  distance = ((mouse_x - player_x) ** 2 + (mouse_y - player_y) ** 2) ** 0.5
  angle = math.atan2(mouse_y - player_y, mouse_x - player_x)
  # Draw a line from the player to the mouse
  pygame.draw.line(screen, BLACK, (player_x, player_y), (mouse_x, mouse_y), 5)
  # Check if the mouse is over a gap or an object
  if mouse_x > 600 and mouse_x < 700 and mouse_y > 300 and mouse_y < 400:
    # If the mouse is over a gap, move the player towards the mouse
    player_rect.centerx += math.cos(angle) * 10
    player_rect.centery += math.sin(angle) * 10
  elif mouse_x > 700 and mouse_x < 800 and mouse_y > 200 and mouse_y < 300:
    # If the mouse is over an object, move the object towards the player
    object_rect.centerx -= math.cos(angle) * 10
    object_rect.centery -= math.sin(angle) * 10

def katana():
  # Get the mouse position and the player position
  mouse_x, mouse_y = pygame.mouse.get_pos()
  player_x, player_y = player_rect.center
  # Calculate the angle between the mouse and the player
  angle = math.atan2(mouse_y - player_y, mouse_x - player_x)
  # Draw a line from the player to the mouse
  pygame.draw.line(screen, RED, (player_x, player_y), (mouse_x, mouse_y), 5)
  # Check if the line intersects with an enemy or a barrier
  if pygame.sprite.spritecollideany(line, enemies) or pygame.sprite.spritecollideany(line, barriers):
    # If the line intersects with an enemy or a barrier, destroy it
    pygame.sprite.spritecollide(line, enemies, True)
    pygame.sprite.spritecollide(line, barriers, True)
   
def bouncy_shoes():
  # Set a global variable to indicate that the player has bouncy shoes
  global bouncy
  bouncy = True
  # Increase the player's jump velocity
  player_jump_vel = 20

def key():
  # Get the mouse position and the player position
  mouse_x, mouse_y = pygame.mouse.get_pos()
  player_x, player_y = player_rect.center
  # Calculate the distance between the mouse and the player
  distance = ((mouse_x - player_x) ** 2 + (mouse_y - player_y) ** 2) ** 0.5
  # Check if the mouse is over a door or a chest
  if pygame.sprite.spritecollideany(mouse, doors) or pygame.sprite.spritecollideany(mouse, chests):
    # If the mouse is over a door or a chest, unlock it and open it
    pygame.sprite.spritecollide(mouse, doors, True)
    pygame.sprite.spritecollide(mouse, chests, True)
    # If the chest contains a tool, add it to the player's inventory
    if chest.tool:
      inventory.append(chest.tool)

def go_kart():
  # Set a global variable to indicate that the player is in a go kart
  global go_kart
  go_kart = True
  # Increase the player's speed and size
  player_speed = 15
  player_rect.inflate_ip(50, 50)
  # Load the image for the go kart
  go_kart = pygame.image.load('go_kart.png')
  # Draw the go kart over the player
  screen.blit(go_kart, player_rect)
  # Check if the player collides with an enemy or a barrier
  if pygame.sprite.spritecollideany(player, enemies) or pygame.sprite.spritecollideany(player, barriers):
    # If the player collides with an enemy or a barrier, run over it and destroy it
    pygame.sprite.spritecollide(player, enemies, True)
    pygame.sprite.spritecollide(player, barriers, True)

def freeze_ray():
  # Get the mouse position and the player position
  mouse_x, mouse_y = pygame.mouse.get_pos()
  player_x, player_y = player_rect.center
  # Calculate the angle between the mouse and the player
  angle = math.atan2(mouse_y - player_y, mouse_x - player_x)
  # Draw a line from the player to the mouse
  pygame.draw.line(screen, BLUE, (player_x, player_y), (mouse_x, mouse_y), 5)
  # Check if the line intersects with an enemy or a platform
  if pygame.sprite.spritecollideany(line, enemies) or pygame.sprite.spritecollideany(line, platforms):
    # If the line intersects with an enemy or a platform, freeze it
    pygame.sprite.spritecollide(line, enemies, False, freeze)
    pygame.sprite.spritecollide(line, platforms, False, freeze)

def freeze(sprite):
  # Change the sprite's image to a frozen version
  sprite.image = pygame.image.load(sprite.name + '_frozen.png')
  # Set the sprite's frozen attribute to True
  sprite.frozen = True

def tsunami_maker():
  # Set a global variable to indicate that the player has used the tsunami maker
  global tsunami
  tsunami = True
  # Load the image for the wave
  wave = pygame.image.load('wave.png')
  # Create a rect for the wave
  wave_rect = wave.get_rect()
  # Set the wave's initial position at the left edge of the screen
  wave_rect.left = 0
  # Set the wave's speed
  wave_speed = 10
  # Draw the wave on the screen
  screen.blit(wave, wave_rect)
  # Move the wave to the right
  wave_rect.x += wave_speed
  # Check if the wave collides with an enemy or a gap
  if pygame.sprite.spritecollideany(wave, enemies) or pygame.sprite.spritecollideany(wave, gaps):
    # If the wave collides with an enemy or a gap, wash it away
    pygame.sprite.spritecollide(wave, enemies, True)
    pygame.sprite.spritecollide(wave, gaps, True, fill)

def fill(sprite):
  # Change the sprite's image to a water version
  sprite.image = pygame.image.load(sprite.name + '_water.png')
  # Set the sprite's filled attribute to True
  sprite.filled = True

def laser_beam():
  # Get the mouse position and the player position
  mouse_x, mouse_y = pygame.mouse.get_pos()
  player_x, player_y = player_rect.center
  # Calculate the angle between the mouse and the player
  angle = math.atan2(mouse_y - player_y, mouse_x - player_x)
  # Draw a line from the player to the mouse
  pygame.draw.line(screen, YELLOW, (player_x, player_y), (mouse_x, mouse_y), 5)
  # Check if the line intersects with an enemy or a barrier
  if pygame.sprite.spritecollideany(line, enemies) or pygame.sprite.spritecollideany(line, barriers):
    # If the line intersects with an enemy or a barrier, destroy it
    pygame.sprite.spritecollide(line, enemies, True)
    pygame.sprite.spritecollide(line, barriers, True)

def speed_pill():
  # Set a global variable to indicate that the player has used the speed pill
  global speed
  speed = True
  # Set a timer to make the player normal again after 10 seconds
  pygame.time.set_timer(pygame.USEREVENT + 1, 10000)
  # Increase the player's speed
  player_speed = 10

def revival_kit():
  # Set a global variable to indicate that the player has a revival kit
  global revival
  revival = True
  # Check if the player's health is zero
  if player_health == 0:
    # If the player's health is zero, revive the player
    player_health = 100
    # Set the revival variable to False
    revival = False

def draw_doors():
  # Define the door's color
  DOOR_COLOR = (139, 69, 19) # Saddle brown color

  # Calculate the cell size based on the screen dimensions
  cell_width = screen.get_width() // GRID_WIDTH
  cell_height = screen.get_height() // GRID_HEIGHT

  # Draw door 1
  door1_start_row = GRID_HEIGHT - 10
  door1_end_row = GRID_HEIGHT - 13
  door1_start_col = 10
  door1_end_col = 11

  for row in range(door1_start_row, door1_end_row - 1, -1):
    for col in range(door1_start_col, door1_end_col + 1):
      rect = pygame.Rect(col * cell_width, row * cell_height, cell_width, cell_height)
      pygame.draw.rect(screen, DOOR_COLOR, rect)

  # Draw door 2
  door2_start_row = GRID_HEIGHT - 3
  door2_end_row = GRID_HEIGHT - 4
  door2_start_col = 16
  door2_end_col = 17

  for row in range(door2_start_row, door2_end_row - 1, -1):
    for col in range(door2_start_col, door2_end_col + 1):
      rect = pygame.Rect(col * cell_width, row * cell_height, cell_width, cell_height)
      pygame.draw.rect(screen, DOOR_COLOR, rect)

def draw_floor():
  # Define the floor's color
  FLOOR_COLOR = (128, 64, 0) # Brown color
  STAIRS_COLOR = (128, 128, 128) # Gray color

  # Calculate the cell size based on the screen dimensions
  cell_width = screen.get_width() // GRID_WIDTH
  cell_height = screen.get_height() // GRID_HEIGHT

  # Draw the floor cells
  for col in range(GRID_WIDTH):
    for row in range(FLOOR_START_ROW, FLOOR_END_ROW + 1):
      rect = pygame.Rect(col * cell_width, row * cell_height, cell_width, cell_height)
      pygame.draw.rect(screen, FLOOR_COLOR, rect)

  # Draw the stairs
  stairs_start_row = GRID_HEIGHT - 3
  stairs_end_row = GRID_HEIGHT - 9
  stairs_start_col = 9
  stairs_end_col = 12

  for row in range(stairs_start_row, stairs_end_row - 1, -1):
    for col in range(stairs_start_col, stairs_end_col + 1):
      rect = pygame.Rect(col * cell_width, row * cell_height, cell_width, cell_height)
      pygame.draw.rect(screen, STAIRS_COLOR, rect)

enemies = pygame.sprite.Group()
barriers = pygame.sprite.Group()
platforms = pygame.sprite.Group()
doors = pygame.sprite.Group()
chests = pygame.sprite.Group()
gaps = pygame.sprite.Group()
tools = pygame.sprite.Group()

# Create some sprites and groups for the player
player_sprite = pygame.sprite.Sprite()
player_sprite.image = player_image
player_sprite.rect = player_sprite.image.get_rect()
player_sprite.rect.center = (100, 300)

# Create sprite groups
enemies = pygame.sprite.Group()
tools = pygame.sprite.Group() # Assuming tools are also Sprites

# Gravity constant
GRAVITY = 0.5

# Player properties
player_x = 100
player_y = 300
player_speed = 5
player_jump_vel = 10
player_vert_vel = 0 # Initial vertical velocity
player_health = 100
inventory = []

# Main game loop control
running = True
clock = pygame.time.Clock()

show_intro()

while running:
  # 1. Handle events
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      running = False
     
     

  # 2. Update game state
  keys = pygame.key.get_pressed()
  if keys[pygame.K_SPACE]:
    player_vert_vel = -player_jump_vel # Jump velocity
  if keys[pygame.K_LEFT]:
    player_sprite.rect.x -= player_speed
  if keys[pygame.K_RIGHT]:
    player_sprite.rect.x += player_speed
  if keys[pygame.K_UP]: # Add this line
    player_sprite.rect.y -= player_speed  
   

  # Apply gravity
  player_vert_vel += GRAVITY
  player_sprite.rect.y += player_vert_vel

  # Prevent the player from moving off screen
  player_sprite.rect.clamp_ip(screen.get_rect())

  # 3. Draw everything
  screen.blit(background, (0, 0))
  draw_floor()
  draw_doors()
  tools.draw(screen)
  enemies.draw(screen)
  screen.blit(player_sprite.image, player_sprite.rect) # Draw player

  # After drawing everything, update/flip the display
  pygame.display.flip()

  # 4. Cap the frame rate
  clock.tick(60) the Up key is not working the player is supposed to move left right foward backwards and jump