# Arup Guha and Erick Verlangieli
# 5/30/2022
# Written for SI@UCF converting Dot Game to multiple screens.

import random
import math
import time
import dotconsts
import dotfunctions
import pygame, sys
from pygame.locals import *

def draw(text, font, color, surface, x, y):
    # Draw text on a new Surface. Title, antialias and color are used.
    text = font.render(text, 1, color)

    # Returns a new rectangle covering the entire surface.
    # This rectangle will always start at (0, 0) with a width and height the same size as the image.
    textrect = text.get_rect()

    # Sets location of text.
    textrect.topleft = (x, y)

    # Draw one image onto another. Source and destination are passed. Source is textobj and it will be written onto textrect,
    surface.blit(text, textrect)

def options():
    running = True

    # If you click escape, it will default to lime as the dot color.
    color = dotconsts.LIME

    # Create a Font object from the system fonts. I chose size 100.
    font = pygame.font.SysFont(None, 100)

    # Create an object to help track time
    clock = pygame.time.time()

    # Created buttons. X, Y, Width, Height.
    button_1 = pygame.Rect(350, 150, 300, 80)
    button_2 = pygame.Rect(350, 300, 300, 80)
    button_3 = pygame.Rect(350, 450, 300, 80)

    # Creates a screen with width and height.
    screen = pygame.display.set_mode((dotconsts.SCREEN_W, dotconsts.SCREEN_H))

    while running:

        # Fill surface with a solid color, I chose black.
        screen.fill((0, 0, 0))

        dotfunctions.draw('Color Options', font, (255, 255, 255), screen, 250, 20)

        # Draws the buttons
        pygame.draw.rect(screen, (255, 0, 0), button_1)
        pygame.draw.rect(screen, (0, 255, 0), button_2)
        pygame.draw.rect(screen, (0, 0, 255), button_3)

        # Creates and draws text on buttons.
        dotfunctions.draw('Red', font, (255, 255, 255), screen, 430, 160)
        dotfunctions.draw('Green', font, (255, 255, 255), screen, 400, 310)
        dotfunctions.draw('Blue', font, (255, 255, 255), screen, 420, 460)

        for event in pygame.event.get():

            # If you close the game.
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

            # If you press down a key.
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    running = False

            # If you click on screen.
            if event.type == MOUSEBUTTONDOWN:
                # 1 - left click, 2 - middle click, 3 - right click, 4 - scroll up, 5 - scroll down
                if event.button == 1:

                    # Get mouse position x and y.
                    mx, my = pygame.mouse.get_pos()

                    # If mouse location is inside this rectangle.
                    if button_1.collidepoint((mx, my)):
                        color = dotconsts.RED
                        running = False

                    # If mouse location is inside this rectangle.
                    if button_2.collidepoint((mx, my)):
                        color = dotconsts.GREEN
                        running = False

                    # If mouse location is inside this rectangle.
                    if button_3.collidepoint((mx, my)):
                        color = dotconsts.BLUE
                        running = False

        # Update portions of the screen for software displays
        pygame.display.update()

        # Update the clock in milliseconds. Should be called once per frame.
        clock.tick(60)

    return color


def main_game(color):

    # Creates a screen with width and height.
    DISPLAYSURF = pygame.display.set_mode((dotconsts.SCREEN_W, dotconsts.SCREEN_H))

    # Create a custom caption that will be displayed on the top of your window of your game.
    pygame.display.set_caption("Dot Game!")

    clock = pygame.time.Clock()

    # Enemy dots will be stored here.
    dots = []

    # My initial position.
    me = [dotconsts.SCREEN_W // 2, dotconsts.SCREEN_H // 2, 0, 0, 20, color]

    curT = time.time()

    score = 0
    dropped = 0
    step = 0
    alive = True
    # Main game loop starts here.
    while True:

        for event in pygame.event.get():

            # X out at the top right.
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

            # Just looking for key presses to change the dot movement.
            if event.type == KEYDOWN:

                # Using the arrow keys for their natural meaning.
                if event.key == K_DOWN:
                    me[dotconsts.DY] += dotconsts.DELTA_ME
                elif event.key == K_UP:
                    me[dotconsts.DY] -= dotconsts.DELTA_ME
                elif event.key == K_RIGHT:
                    me[dotconsts.DX] += dotconsts.DELTA_ME
                elif event.key == K_LEFT:
                    me[dotconsts.DX] -= dotconsts.DELTA_ME

        # I add dots once every 20 frames.
        if step % 20 == 0:
            dots.append(dotfunctions.getRandDot())

        # Move stuff
        dotfunctions.move(dots)
        dotfunctions.moveItem(me)

        # See if I am eating a dot!
        for item in dots:
            if dotfunctions.hit(me, item):

                # I die :(
                if not dotfunctions.isBigger(me, item):
                    alive = False

                # I grow - my new area is your area plus mine!
                else:
                    dotfunctions.eat(me, item)
                    dots.remove(item)

        # So my list doesn't grow endlessly!
        dotfunctions.removeUseless(dots)

        DISPLAYSURF.fill(dotconsts.WHITE)

        # Draw all the dots.
        for item in dots:
            pygame.draw.circle(DISPLAYSURF, item[dotconsts.CLR], (item[dotconsts.X], item[dotconsts.Y]),
                               item[dotconsts.R], 0)

        # Draw me.
        pygame.draw.circle(DISPLAYSURF, me[dotconsts.CLR], (me[dotconsts.X], me[dotconsts.Y]), me[dotconsts.R], 0)

        pygame.display.update()

        # Conditions that end the game - you hit a bigger dot or got ran off the screen!
        if not alive:
            return me[dotconsts.R]
            
        elif dotfunctions.offScreen(me):
            return me[dotconsts.R]


        clock.tick(10)
        step += 1



# This function removes all items that will never be visible again,
# and returns how many were removed.
def removeUseless(items):
    for item in items:
        if item[dotconsts.Y] > dotconsts.SCREEN_H or item[dotconsts.Y] < 0:
            items.remove(item)
        if item[dotconsts.X] > dotconsts.SCREEN_W or item[dotconsts.X] < 0:
            items.remove(item)

# Returns true iff mypos is within the picture specified by f.
def hit(enemy, me):
    distsq = (enemy[dotconsts.X]-me[dotconsts.X])**2 + (enemy[dotconsts.Y]-me[dotconsts.Y])**2
    return (enemy[dotconsts.R]+me[dotconsts.R])**2 > distsq

# This function changes item's velocity by (addvelX, addvelY).
def changeVel(item,addvelX,addvelY):
    item[dotconsts.DX] += addvelX
    item[dotconsts.DY] += addvelY

# This function moves item for one frame based on its DX, DY    
def moveItem(item):
    item[dotconsts.X] += item[dotconsts.DX]
    item[dotconsts.Y] += item[dotconsts.DY]
        
# This function handles moving each item listed in items.
def move(items):
    for item in items:
        moveItem(item)

# This function removes all items that will never be visible again,
# and returns how many were removed.
def removeUseless(items):
    for item in items:
        if item[dotconsts.Y] > dotconsts.SCREEN_H or item[dotconsts.Y] < 0:
            items.remove(item)
        if item[dotconsts.X] > dotconsts.SCREEN_W or item[dotconsts.X] < 0:
            items.remove(item)

# Returns true iff the dot me is bigger than other
def isBigger(me,other):
    return me[dotconsts.R] > other[dotconsts.R]

# Updates me for the act of "eating" other.
def eat(me,other):
    me[dotconsts.R] = int((me[dotconsts.R]**2 + other[dotconsts.R]**2)**.5)    

# Returns true iff me is off the screen.
# Edited on 6/3/2022 so if ANY portion of the circle is off the screen, not just the center.
def offScreen(me):
    return me[dotconsts.X] - me[dotconsts.R] < 0 or me[dotconsts.X] + me[dotconsts.R] > dotconsts.SCREEN_W or me[dotconsts.Y] - me[dotconsts.R] < 0 or me[dotconsts.Y] + me[dotconsts.R] > dotconsts.SCREEN_H

# Returns true iff mypos is within the picture specified by f.
def hit(enemy, me):
    distsq = (enemy[dotconsts.X]-me[dotconsts.X])**2 + (enemy[dotconsts.Y]-me[dotconsts.Y])**2
    return (enemy[dotconsts.R]+me[dotconsts.R])**2 > distsq

# Returns a newly created dot.
def getRandDot():
    x = random.randint(1, dotconsts.SCREEN_W)
    y = random.randint(1, dotconsts.SCREEN_H)
    r = random.randint(5,50)
    which = random.randint(0,3)
    mydx = random.randint(-dotconsts.DELTA+1, dotconsts.DELTA-1)
    mydy = random.randint(-dotconsts.DELTA+1, dotconsts.DELTA-1)
    return [x,y,mydx,mydy,r,dotconsts.PINK]
