import pygame
import pygame.freetype
import math
import random
import gobjs

class Display:
    def __init__(self, screen, clock):
        self.screen = screen
        self.clock = clock
        self.run = True
        self.delta = 0
        self.font = None
        
    def draw_gobj(self, gobj):
        pygame.draw.circle(
            self.screen,
            gobj.color,
            gobj.pos(),
            gobj.radius)
    def draw_text(self, msg, x, y, color):
        surface, rect = self.font.render(msg, color)
        self.screen.blit(surface, (x-rect.w//2, y-rect.h))
        

def init_display(sw, sh):
    pygame.init()
    screen = pygame.display.set_mode((sw,sh))
    clock = pygame.time.Clock()
    display = Display(screen, clock)
    display.font = pygame.freetype.Font('JuliaMono-Bold.ttf', 18)
    return display

def handle_input(keys, dt, player, win_w, win_h):
    pos = player.pos()
    r = player.radius
    
    if keys[pygame.K_a]:
        player.turn(dt, -1)
    elif keys[pygame.K_d]:
        player.turn(dt, 1)
    if keys[pygame.K_w]:
        player.move(dt)
    elif keys[pygame.K_s]:
        player.move(dt, -1.0)
        
def gather_perecpts(enemy, player):
    return enemy.can_see(player)
        
def game_loop(display):

    win_w, win_h = pygame.display.get_window_size()
    d_rect = (0, 0, win_w, win_h)

    # NOTE: You are welcome to modify some aspects of the following
    # The player and enemy classes do take additional parameters
    # which are currently set to defaults. You are welcome to
    # override them to get a different scenario.
    
    # Possible Player start locations (x, y, heading)
    start_locs = [
        (50,50, math.pi/4),
        (win_w//2, 50, math.pi/2),
        (win_w-50, 50, 3*math.pi/4),
        (50, win_h//2, 0),
        (win_w-50, win_h//2, math.pi),
        (50, win_h-50, -math.pi/4),
        (win_w//2, win_h-50, -math.pi/2),
        (win_w-50, win_h-50, -3*math.pi/4)
        ]
    # Randomly choose one.
    player_start = random.choice(start_locs)
    player = gobjs.Player(player_start[0], player_start[1], heading=player_start[2])

    # Goals. The number passed into the Goal contructor are the x,y coords.
    goals = [
        gobjs.Goal(200, 200),
        gobjs.Goal(win_w-200, 200),
        gobjs.Goal(200, win_h-200),
        gobjs.Goal(win_w-200, win_h-200),
        gobjs.Goal(win_w//2, win_h//2)
        ]

    # The enemies.
    enemy1 = gobjs.EnemyYellow(win_w//2+50, win_h//2, heading=0)
    enemy2 = gobjs.EnemyBlue(win_w//2-50, win_h//2, heading=math.pi)
    enemy3 = gobjs.EnemyRed(win_w//2, win_h//2-50, heading=-math.pi/2)
    enemies = [enemy1, enemy2, enemy3]
    comms = {
        "R": None,
        "B": None,
        "Y": None
        }

    tick = 0
    goal_count = 0
    winner = "Draw"
    msgs = []


    # You probably don't need to modify anything in the main loop
    while display.run:
        dt = display.clock.tick(60) / 1000

        # Check event queue for quit
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                display.run = False

        display.screen.fill("black")

        next_msgs = []
        for msg in msgs:
            if pygame.time.get_ticks() - msg[2] < msg[0][1]:
                display.draw_text(msg[0][0], msg[1].x, msg[1].y-(msg[1].radius+3), msg[1].color)
                next_msgs.append(msg)
        msgs = next_msgs

        for g in goals:
            if not g.is_touched():
                if g.check_collision(player):
                    g.touch()
                    goal_count += 1
                    if goal_count == len(goals):
                        display.run = False
                        winner = "Player"
            g.draw(display.screen)

        # Call Enemy AI and draw
        for e in enemies:
            mt = e.ai(e.update(player), goals, comms)
            e.turn(dt, mt[0])
            e.move(dt, mt[1])
            if mt[2] is not None:
                msgs.append( (mt[2], e, pygame.time.get_ticks()) )
            if e.check_collision(player):
                display.run = False
                winner = "AI"
            if not e.onscreen(d_rect):
                display.run = False
                winner = "Player"
            e.draw(display.screen)

        # Move and draw the player
        keys = pygame.key.get_pressed()
        handle_input(keys, dt, player, win_w, win_h)
        player.draw(display.screen)

        if not player.onscreen(d_rect):
            winner = "AI"
            display.run=False
                
        pygame.display.flip()
        
    print(f"The winner is the {winner}.")
        

def main():
    display = init_display(800, 800)
    game_loop(display)

if __name__ == "__main__":
    main()
