import pygame
import random

WIDTH = 400
HEIGHT = 400

pygame.init()
window = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Clicker')
pygame.font.init()
font = pygame.font.SysFont('Verdana',24)
clock = pygame.time.Clock()

# Game Data
game_data = {"score": 0,                # tracks the player's score
             "stones": 0,               # tracks how many stones we have displayed
             "spawn_chance": 0.05,      # chance of a stone spawning on the screen
             "end_time": 0,             # the time when the game should end. this will be set automatically
             "duration": 10,            # the duration of the game
             "game_over": False,        # whether or not the game is over
             "app_is_running": True}    # whether or not the app is running

# Generic Gem Info
all_stones = ['blue_crystal', 'blue_gem', 'blue_jewel', 
              'green_crystal', 'green_gem', 'green_jewel', 
              'red_crystal', 'red_gem', 'red_jewel', 
              'yellow_crystal', 'yellow_gem', 'yellow_jewel']
images = {"blue_crystal": pygame.image.load("images/blueCrystal.png"),
          "blue_gem": pygame.image.load("images/blueGem.png"),
          "blue_jewel": pygame.image.load("images/blueJewel.png"),
          "green_crystal": pygame.image.load("images/greenCrystal.png"),
          "green_gem": pygame.image.load("images/greenGem.png"),
          "green_jewel": pygame.image.load("images/greenJewel.png"),
          "red_crystal": pygame.image.load("images/redCrystal.png"),
          "red_gem": pygame.image.load("images/redGem.png"),
          "red_jewel": pygame.image.load("images/redJewel.png"),
          "yellow_crystal": pygame.image.load("images/yellowCrystal.png"),
          "yellow_gem": pygame.image.load("images/yellowGem.png"),
          "yellow_jewel": pygame.image.load("images/yellowJewel.png")}
points = {'blue_crystal': 1, # feel free to set these point values for each stone
          'blue_gem': 1, 
          'blue_jewel': 1, 
          'green_crystal': 1, 
          'green_gem': 1, 
          'green_jewel': 1, 
          'red_crystal': 1, 
          'red_gem': 1, 
          'red_jewel': 1, 
          'yellow_crystal': 1,
          'yellow_gem': 1, 
          'yellow_jewel': 1}

# Current Gem Info
objects = []        # list of object names
x_positions = {}    # x positions of the objects
y_positions = {}    # y positions of the objects
types = {}          # types of the object (red_gem, yellow_jewel, etc)

# Helpers
def get_image(object):
    # Takes an object name and returns the image associated with it
    # We do this using the type dictionary
    #   - object: the name of the object that we want to get the image for
    #   - returns: the image of that object
    stone_type = types[object]
    return images[stone_type]

def get_dimensions(object):
    # Takes an object name and returns the dimensions of its image
    #   - object: the name of the object that we want to get the dimensions of
    #   - returns: the dimensions of the given object as a pair (width, height)
    image = get_image(object)
    w = image.get_width()
    h = image.get_height()
    return (w, h)

def seconds_remaining():
    # Calculates the seconds remaining in the game
    # Use game_data["end_time"] to get the end time in milliseconds
    # Use pygame.time.get_ticks() to get the current time in milliseconds
    # return their difference in seconds

    # You have to fill this in.
    pass

def calculate_end_time():
    # Calculates and sets the end time of the game
    # Take the durations of the game (game_data["duration"]) and convert it 
    # to milliseconds
    # Use pygame.time.get_ticks() to get the current time in milliseconds
    # Set the game_data["end_time"] to be the sum of these two

    # You have to fill this in.
    pass

# Game Management
def calculate_points(clicked):
    # Updates the number of points that a player has earned (game_data["score"])
    # using a list of clicked objects and the points dictionary. 
    #   - clicked: a list of stones that were clicked 

    # You have to fill this in.
    pass

def check_game_over():
    # Checks whether or not the game is over. 
    # If the number of seconds remaining is less than or equal to 0, then the
    # game is over. Otherwise, it is not.

    # You have to fill this in.
    pass

def reset():
    # Resets the game data (game_data["score"] and game_data["stones"])

    # You have to fill this in.
    pass

# Draw functions
def draw_background():
    # Draws the background
    window.fill((0, 0, 0))

def draw_objects():
    # Draws all objects 
    for object in objects:
        x = x_positions[object]
        y = y_positions[object]
        image = get_image(object)
        window.blit(image, (x, y))

def draw_timer():
    # Draws the timer
    seconds = seconds_remaining()
    text = f"Time: {seconds}"
    message = font.render(text, True, (255, 255, 255))
    window.blit(message, (0,0))

def draw_score():
    # Draws the score
    score = game_data["score"]
    text = f"Score: {score}"
    message = font.render(text, True, (255, 255, 255))
    window.blit(message, (0,30))

def redraw():
    # Redraws the window
    draw_background()
    draw_objects()
    draw_timer()
    draw_score()
    pygame.display.update()

def draw_times_up():
    # Draws the time's up message
    message = font.render("Time's up!", True, (255, 255, 255))
    window.blit(message, (0, 0))

def draw_end_screen():
    # Draws the end screen
    draw_background()
    draw_times_up()
    draw_score()
    pygame.display.update()

# Stone Management
def was_object_clicked(mx, my, object):    
    # Determines if the given object was clicked
    #   - mx: the x position the mouse clicked
    #   - my: the y position the mouse clicked
    #   - object: the name of the object that we want to test

    # To do this, you will need the (x, y) of the object and the (w, h) of 
    # its image (see get_dimensions()). From there, you need to make sure that
    # the x <= mx <= x + w AND y <= my <= y + h. 

    # You have to fill this in.
    pass

def handle_click(mx, my):
    # Determines what to update when a click is done.
    #   - mx: the x position the mouse clicked
    #   - my: the y position the mouse clicked

    # This function does several things:
    #   1. Define a clicked list
    #   2. Loop through every object and do the following
    #       a. check if it was clicked (see was_object_clicked())
    #       b. if it was clicked, add it to the clicked list
    #   3. Update the points using the clicked list (see calculate_points())
    #   4. Remove the clicked stones from the list (see remove_objects())

    # You have to fill this in.
    pass

def remove_objects(clicked):
    # Removes the clicked objects from the list and the dictionaries
    #   - clicked: the names of the objects that were clicked

    # To write this function, loop through all of the clicked objects and do
    # the following:
    #   1. remove the current object from the objects list (.remove())
    #   2. remove the current object from the dictionaries (.pop())
    #      the relevant dictionaries are: x_positions, y_positions, and types

    # You have to fill this in.
    pass

def spawn_stones():
    # We will fill this in together
    pass

def clear_stones():
    # Clears all stones
    objects.clear()
    x_positions.clear()
    y_positions.clear()
    types.clear()

def run_game():
    # Runs the game
    calculate_end_time()
    while game_data["app_is_running"] == True and game_data["game_over"] == False:
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q:
                    game_data["app_is_running"] = False
            if event.type == pygame.MOUSEBUTTONDOWN:
                (mx, my) = pygame.mouse.get_pos()
                handle_click(mx, my)

        spawn_stones()
        redraw()
        check_game_over()
        clock.tick(30)

def game_over():
    # Runs the game over screen
    while game_data["app_is_running"] == True and game_data["game_over"] == True:
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q:
                    game_data["app_is_running"] = False
                elif event.key == pygame.K_r:
                    game_data["game_over"] = False

        draw_end_screen()
        clock.tick(10)

def run_app():
    # Runs the whole app and manages switching between screens
    while game_data["app_is_running"] == True:
        run_game()
        clear_stones()
        game_over()
        reset()
    
    pygame.quit()

run_app()
