from settings import *
import pygame as pg
from pytmx.util_pygame import load_pygame
from support import load_all_images, player_is_blocked_by_object, load_frames
import sys
import os
from breakout import Nomekop, MoveQueue, NOMEKOP_ATTACK_MAP, NOMEKOP_DEFENSE_MAP, compute_total_nomekop_hitpoints, find_best_timeline


class Sproot:
    def __init__(self, name, x, y, width, height, images, direction="left"):
        self.name = name
        # attributes defining the rectangle
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        # attributes controlling how the sproot gets drawn on screen
        self.all_images = images # list of all images for this sprite
        self.direction = direction
        direction_index_map = {"left": 0, "right": 4, "down": 8, "up": 12}
        self.current_image = self.all_images[direction_index_map[self.direction]] # set current image


def draw(image, screen, pos_x, pos_y):
    screen.blit(image, (pos_x, pos_y))


def run_game(player_nomekop_list, opp_nomekop_list, player_q, opp_q):

    # initial setup code
    pg.init()
    screen = pg.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
    pg.display.set_caption("Nomékop")
    clock = pg.time.Clock()

    # loading player, yesse, yames, and background images
    player_image_path = os.path.join("..", "graphics", "characters", PLAYER_FILE)
    yesse_image_path = os.path.join("..", "graphics", "characters", YESSE_FILE)
    yames_image_path = os.path.join("..", "graphics", "characters", YAMES_FILE)
    player_images = load_all_images(player_image_path, 4, 4)
    yesse_images = load_all_images(yesse_image_path, 4, 4)
    yames_images = load_all_images(yames_image_path, 4, 4)
    bg_image = pg.image.load(os.path.join("..", "graphics", "backgrounds", "ice.png"))
    player_sproot = Sproot("Player", 100, 400, 100, 128, player_images, direction="right")
    yesse_sproot = Sproot("Yesse", 1100, 300, 100, 128, yesse_images, direction="left")
    yames_sproot = Sproot("Yames", 1100, 500, 100, 128, yames_images, direction="left")
    object_sproots = [player_sproot, yesse_sproot, yames_sproot]
    
    for nomekop in player_nomekop_list:
        nomekop.all_images = load_frames(nomekop.name, flip=True)

    for nomekop in opp_nomekop_list:
        nomekop.all_images = load_frames(nomekop.name, flip=False)

    cleaf, plumette = player_nomekop_list
    jacana, gulfin, atrox = opp_nomekop_list
    cleaf.x, cleaf.y = 400, 400
    plumette.x, plumette.y = 400, 400
    jacana.x, jacana.y = 730, 400
    gulfin.x, gulfin.y = 730, 400
    atrox.x, atrox.y = 730, 400

    cleaf.x, cleaf.y = 400, 300
    plumette.x, plumette.y = 350, 200
    jacana.x, jacana.y = 850, 200
    gulfin.x, gulfin.y = 750, 300
    atrox.x, atrox.y = 850, 400
    attacking_nomekop = None
    target_nomekop = None
    attack_timer = 0
    end = False
    end_timer = 0

    frame = 0
    audio_path = os.path.join("..", "data", "audio", "battle.ogg")
    music = pg.mixer.Sound(audio_path)
    music.play()
    move_num = 0

    font = pg.font.SysFont('Arial', 32)
    move_text = font.render('Move', False, COLORS['fire'])

    while True:
        
        time = clock.tick() / 1000
        # event loop
        for event in pg.event.get():
            if event.type == pg.QUIT:
                 pg.quit()
                 sys.exit()

        # update the frame based on time and animation speed
        frame += time * ANIMATION_SPEED
        frame_index = int(frame % 4)

        # always reset the screen with a blank slate first
        screen.fill("black")
        draw(bg_image, screen, 0, 0)
        for s in object_sproots:
            draw(s.current_image, screen, s.x, s.y)

        # logic for when game is over
        if compute_total_nomekop_hitpoints(opp_nomekop_list) <= 0 and attack_timer <= 0 and not end:
            end_timer = 25
            end = True
            move_text = font.render("You win!", False, COLORS["black"])

        if end:
            end_timer -= time*ANIMATION_SPEED
        if end and end_timer <= 0:
            print("I'm free... but at what cost... we have to find the Professor and finish this!")
            pg.quit()
            sys.exit()
    
        # implement logic for drawing the battle here
        if move_num < 12 and attack_timer <= 0:
            if move_num % 2 == 0:
                attacking_nomekop, move, target_nomekop = player_q.process_next_move()
            else:
                attacking_nomekop, move, target_nomekop = opp_q.process_next_move()
            if attacking_nomekop and target_nomekop:
                if attacking_nomekop == target_nomekop:
                    move_text = font.render(attacking_nomekop.name + " uses " + move + " on itself!", False, COLORS["black"])
                else:
                    move_text = font.render(attacking_nomekop.name + " uses " + move + " on " + target_nomekop.name + "!", False, COLORS["black"])
            if attacking_nomekop and target_nomekop:
                attack_timer = 20
            move_num += 1

        for nomekop in player_nomekop_list + opp_nomekop_list:
            if nomekop.hitpoints > 0 and nomekop != attacking_nomekop and nomekop != target_nomekop:
                draw(nomekop.all_images[frame_index], screen, nomekop.x, nomekop.y)

        if attack_timer > 0 and attacking_nomekop and target_nomekop:

            if attacking_nomekop.name == target_nomekop.name:
                draw(attacking_nomekop.all_images[4+frame_index], screen, attacking_nomekop.x, attacking_nomekop.y)
                draw(attacking_nomekop.all_images[8+frame_index], screen, attacking_nomekop.x, attacking_nomekop.y)
            else:
                draw(attacking_nomekop.all_images[4+frame_index], screen, attacking_nomekop.x, attacking_nomekop.y)
                draw(target_nomekop.all_images[frame_index], screen, target_nomekop.x, target_nomekop.y)
                draw(attacking_nomekop.all_images[8+frame_index], screen, target_nomekop.x, target_nomekop.y)

            attack_timer -= time * ANIMATION_SPEED

            if attack_timer <= 0:
                attacking_nomekop = None
                target_nomekop = None

        else:
            attacking_nomekop, target_nomekop = None, None

        screen.blit(move_text, (400, 600))
            
        pg.display.update()


if __name__ == "__main__":
    cleaf = Nomekop("Cleaf", 6, 4, "plant")
    plumette = Nomekop("Plumette", 2, 4, "plant")
    jacana = Nomekop("Jacana", 4, 3, "fire")
    gulfin = Nomekop("Gulfin", 8, 2, "water")
    atrox = Nomekop("Atrox", 3, 3, "plant")
    player_nomekop_list = [cleaf, plumette]
    opp_nomekop_list = [jacana, gulfin, atrox]

    print()
    print("Finding best sequence")
    best_sequence = find_best_timeline(player_nomekop_list, opp_nomekop_list, 6)
    print()

    player_q = MoveQueue()
    for move in best_sequence:
        player_q.insert_at_end(move[0], move[1])

    opp_q = MoveQueue()
    # triple attack on cleaf
    opp_q.insert_at_end(jacana, cleaf)
    opp_q.insert_at_end(gulfin, cleaf)
    opp_q.insert_at_end(atrox, cleaf)

    # triple attack on plumette
    opp_q.insert_at_end(jacana, plumette)
    opp_q.insert_at_end(gulfin, plumette)
    opp_q.insert_at_end(atrox, plumette)

    run_game(player_nomekop_list, opp_nomekop_list, player_q, opp_q)