import pygame, sys
from pygame.locals import *
import random
 
# pygame.init()

pygame.display.init()
pygame.font.init()

w = pygame.display.Info().current_w
h = pygame.display.Info().current_h
screen_scale_factor = w / 1920
screen_scale_factor_h = h / 1080

MOUSE_BUTTON_RIGHT = 3
HEART_POS_X = 1700 * screen_scale_factor
HEART_POS_Y = 700 * screen_scale_factor

SCREEN_WIDTH = 400 
FPS = 60
FramePerSec = pygame.time.Clock()
game_level = 1
enemy_list = []
 
BLUE  = (0, 0, 255)
RED   = (255, 0, 0)
GREEN = (0, 255, 0)
YELLOW = (255, 255, 0)

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

TEXT_COLOR = (0, 0, 0)

MENU_PADDING = 10 * screen_scale_factor

money = 15000

DISPLAYSURF = pygame.display.set_mode((screen_scale_factor * 1920, screen_scale_factor * 1080))
DISPLAYSURF.fill(WHITE)
pygame.display.set_caption("Game")

pygame.font.init()
my_font = pygame.font.SysFont("Arial", 30, bold=True, italic=False)
you_died_font = pygame.font.SysFont("Arial", 300, bold=True, italic=False)


exit_text_surface = my_font.render("Exit", False, TEXT_COLOR)
exit_text_x = screen_scale_factor * 1800
exit_text_y = screen_scale_factor *16
exit_rect = exit_text_surface.get_rect(topleft=(exit_text_x, exit_text_y))

you_died = you_died_font.render('YOU DIED', False, (255, 0, 0))

text_surface = my_font.render("money: " + str(money), False, TEXT_COLOR)
text_surface_x = screen_scale_factor * 16
text_surface_y = screen_scale_factor * 16

level_text_surface = my_font.render("Level: " + str(game_level), False, TEXT_COLOR)
level_text_surface_x = screen_scale_factor * 16
level_text_surface_y = screen_scale_factor * 48

snowman_list = []
cakeman_list = []
snowball_list = []
reindeer_list = []
laser_beam_list = []

class CakeMan(pygame.sprite.Sprite):
    def __init__ (self, x, y):
        super().__init__()
        self.image = pygame.image.load("kagemand/kagemand1.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.image = pygame.transform.smoothscale(self.image, (self.rect.w * screen_scale_factor, self.rect.h * screen_scale_factor) )
        self.rect.center = (x, y)
        self.animation_step = 0

    def draw(self, surface):
        surface.blit(self.image, self.rect)

class Reindeer(pygame.sprite.Sprite):
    def __init__ (self, x, y):
        super().__init__()
        self.image = pygame.image.load("reindeer/r1.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.image = pygame.transform.smoothscale(self.image, (self.rect.w * screen_scale_factor, self.rect.h * screen_scale_factor) )
        self.rect.center = (x, y)
        self.speed = 180
        self.shoot_laser_beam = self.speed
        self.animation_step = 0

    def draw(self, surface):
        surface.blit(self.image, self.rect)
        self.shoot_laser_beam = self.shoot_laser_beam - 1
        if self.shoot_laser_beam == -1:
            return
        elif self.shoot_laser_beam == 0:
            # Throw snowball. 
            # print("Laser beam: x: " + str(self.rect.center[0]) + "y:" + str(self.rect.center[1]))
            laser_beam_list.append(Laser_Beam(self.rect.center[0] + (self.rect.width / 4), self.rect.center[1] - (self.rect.height / 7)))
            # rest sownball counter 
            self.shoot_laser_beam = self.speed

class Snowman(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__() 
        self.image = pygame.image.load("snowmand.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.image = pygame.transform.smoothscale(self.image, (self.rect.w * screen_scale_factor, self.rect.h * screen_scale_factor) )
        self.rect.center = (x, y)
        self.speed = 180
        self.throw_snowball_counter = self.speed

    def draw(self, surface):
        surface.blit(self.image, self.rect)
        self.throw_snowball_counter = self.throw_snowball_counter - 1
        if self.throw_snowball_counter == -1:
            return
        elif self.throw_snowball_counter == 0:
            # Throw snowball. 
            # print("Snowball: x: " + str(self.rect.center[0]) + "y:" + str(self.rect.center[1]))
            snowball_list.append(Snowball(self.rect.center[0], self.rect.center[1]))
            # rest sownball counter 
            self.throw_snowball_counter = self.speed

class Enemy(pygame.sprite.Sprite):
      def __init__(self, x, y, heart, health):
        super().__init__()
        self.image = pygame.image.load("elf.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)

        self.image = pygame.transform.smoothscale(self.image, (self.rect.w * screen_scale_factor, self.rect.h * screen_scale_factor) )
        
        self.health_bar_color = GREEN
        self.health_bar_width = 0
        self.path = 0
        self.max_health = health
        self.health = self.max_health
        self.alive = 1
        self.heart = heart
        self.speed = 2 *screen_scale_factor
        self.calculate_life_bar()
 
      def damage(self, amount):
        self.health = self.health - amount
        if(self.health <= 0):
            self.alive = 0
            add_money(1000)
            return

        self.calculate_life_bar()


      def calculate_life_bar(self):
        #Beregn størrelsen på liv baren:
        life_ratio = self.health / self.max_health
        
        if life_ratio >= 0.75:
            self.health_bar_color = GREEN
        elif life_ratio < 0.75 and life_ratio >= 0.25:
            self.health_bar_color = YELLOW
        else:
            self.health_bar_color = RED

        self.health_bar_width = self.rect.w * (self.health / self.max_health)



      def move(self, player):
        if (self.path == 0):
            if (self.rect.right < 300 *screen_scale_factor):
                self.rect.move_ip(self.speed,0)
            else:
                self.path = 1
        if (self.path == 1):
            if(self.rect.bottom < 890 *screen_scale_factor):
                self.rect.move_ip(0,self.speed)
            else:
                self.path = 2
        if(self.path == 2):
            if(self.rect.right < 1128 *screen_scale_factor):
                self.rect.move_ip(self.speed,0)
            else:
                self.path = 3
        if (self.path == 3):
            if(self.rect.top > 516*screen_scale_factor):
                self.rect.move_ip(0,-self.speed)
            else:
                self.path = 4
        if (self.path == 4):
            if(self.rect.left > 847*screen_scale_factor):
                self.rect.move_ip(-self.speed,0)
            else:
                self.path = 5
        if (self.path == 5):
            if(self.rect.top > 246*screen_scale_factor):
                self.rect.move_ip(0,-self.speed)
            else:
                self.path = 6
        if (self.path == 6):
            if (self.rect.right < 1248*screen_scale_factor):
                self.rect.move_ip(self.speed,0)
            else:
                self.path = 7
        if (self.path == 7):
            if (self.rect.bottom < 570*screen_scale_factor):
                self.rect.move_ip(0,self.speed)
            else:
                self.path = 8
        if (self.path == 8):
            if (self.rect.right < 1548*screen_scale_factor):
                self.rect.move_ip(self.speed,0)
            else:
                self.path = 'end'
        if (self.path == 'end'):
            self.alive = 0
            self.heart.lives -= 20

      def draw(self, surface):
        surface.blit(self.image, self.rect) 

        pygame.draw.rect(DISPLAYSURF,self.health_bar_color,(self.rect.x, (self.rect.y + self.rect.h + 8), self.health_bar_width  * screen_scale_factor , 5 * screen_scale_factor ))

class Snowball(pygame.sprite.Sprite):
      def __init__(self, x, y):
        super().__init__() 
        self.image = pygame.image.load("snowball.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.rect.center=(x, y) 
 
      def move(self, player):
        self.rect.move_ip(4,0)
        #if (self.rect.right > 600):
        #    self.rect.top = 0
        #    self.rect.center = (0, 400)

        # if self.rect.colliderect(player.rect):
        #         print("HIT")

      def draw(self, surface):
        surface.blit(self.image, self.rect)  

class Laser_Beam(pygame.sprite.Sprite):
      def __init__(self, x, y):
        super().__init__() 
        self.image = pygame.image.load("reindeer/laser_beam.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.rect.center=(x, y) 
 
      def move(self, enemy_list):
        self.rect.move_ip(4,0)
        for enemy in enemy_list:
            if self.rect.colliderect(enemy.rect):
                enemy.damage(1)
        #if (self.rect.right > 600):
        #    self.rect.top = 0
        #    self.rect.center = (0, 400)

        # if self.rect.colliderect(player.rect):
        #         print("HIT")

      def draw(self, surface):
        surface.blit(self.image, self.rect)  

 
class MenuSnowman(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__() 
        self.image = pygame.image.load("snowmand.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.rect.center = (screen_scale_factor * 580, screen_scale_factor * 80)
        self.image = pygame.transform.smoothscale(self.image, (self.rect.w * screen_scale_factor, self.rect.h * screen_scale_factor) )
        self.price = 2500
        self.text = my_font.render(str(self.price) , False, TEXT_COLOR)
        self.selected = 0

    def draw(self, surface):
        if self.selected == 1:
            pygame.draw.rect(DISPLAYSURF,BLUE,(menu_snowman.rect.x - MENU_PADDING , menu_snowman.rect.y - MENU_PADDING, (menu_snowman.rect.w + 2 * MENU_PADDING) * screen_scale_factor , (menu_snowman.rect.h + 2 * MENU_PADDING)* screen_scale_factor ))
        surface.blit(self.image, self.rect)
        surface.blit(self.text,(self.rect.x, self.rect.y + (100 * screen_scale_factor)))
    
    def get_pos(self):
        return self.rect.pos

class MenuCakeman(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__() 
        self.image = pygame.image.load("kagemand/kagemand1.png").convert_alpha()
        self.rect = self.image.get_rect()
        #self.rect.scale_by(screen_scale_factor) 
        self.rect.center = (screen_scale_factor * 720, screen_scale_factor * 80)
        self.image = pygame.transform.smoothscale(self.image, (self.rect.w * screen_scale_factor, self.rect.h * screen_scale_factor) )
        self.price = 5000
        self.text = my_font.render(str(self.price) , False, TEXT_COLOR)
        self.selected = 0

    def draw(self, surface):
        if self.selected == 1:
            pygame.draw.rect(DISPLAYSURF,BLUE,(menu_cakeman.rect.x - MENU_PADDING, menu_cakeman.rect.y - MENU_PADDING, (menu_cakeman.rect.w + 2 * MENU_PADDING) *screen_scale_factor, (menu_cakeman.rect.h + 2 * MENU_PADDING) * screen_scale_factor ))
        surface.blit(self.image, self.rect)
        surface.blit(self.text,(self.rect.x ,self.rect.y + (100 * screen_scale_factor) ))
    
    def get_pos(self):
        return self.rect.pos

class MenuReindeer(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__() 
        self.image = pygame.image.load("reindeer/r1.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.rect.center = (screen_scale_factor * 850, screen_scale_factor * 80)
        self.image = pygame.transform.smoothscale(self.image, (self.rect.w * screen_scale_factor, self.rect.h * screen_scale_factor) )
        self.price = 7500
        self.text = my_font.render(str(self.price) , False, TEXT_COLOR)
        self.selected = 0

    def draw(self, surface):
        if self.selected == 1:
            pygame.draw.rect(DISPLAYSURF,BLUE,(self.rect.x - MENU_PADDING , self.rect.y - MENU_PADDING, (self.rect.w + 2 * MENU_PADDING) * screen_scale_factor , (self.rect.h + 2 * MENU_PADDING)* screen_scale_factor ))
        surface.blit(self.image, self.rect)
        surface.blit(self.text,(self.rect.x + (20* screen_scale_factor), self.rect.y + (100 * screen_scale_factor)))
    
    def get_pos(self):
        return self.rect.pos


scaleFactor = 2 * screen_scale_factor
class Heart(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image0 = pygame.image.load('0_hjerte.png').convert_alpha()

        self.image20 = pygame.image.load('20_hjerte.png').convert_alpha()
        self.image20 = pygame.transform.scale(self.image20, (74 * scaleFactor, 79 * scaleFactor))

        self.image40 = pygame.image.load('40_hjerte.png').convert_alpha()
        self.image40 = pygame.transform.scale(self.image40, (74 * scaleFactor, 79 * scaleFactor))

        self.image60 = pygame.image.load('60_hjerte.png').convert_alpha()
        self.image60 = pygame.transform.scale(self.image60, (74 * scaleFactor, 79 * scaleFactor))

        self.image80 = pygame.image.load('80_hjerte.png').convert_alpha()
        self.image80 = pygame.transform.scale(self.image80, (74 * scaleFactor, 79 * scaleFactor))

        self.image100 = pygame.image.load('100_hjerte.png').convert_alpha()
        self.image100 = pygame.transform.scale(self.image100, (74 * scaleFactor, 79 * scaleFactor))

        self.lives = 100

    def draw(self, surface):
        if self.lives == 100:
            surface.blit(self.image100, (HEART_POS_X, HEART_POS_Y))
        elif self.lives == 80:
            surface.blit(self.image80, (HEART_POS_X, HEART_POS_Y))
        elif self.lives == 60:
            surface.blit(self.image60, (HEART_POS_X, HEART_POS_Y))
        elif self.lives == 40:
            surface.blit(self.image40, (HEART_POS_X, HEART_POS_Y))
        elif self.lives == 20:
            surface.blit(self.image20, (HEART_POS_X, HEART_POS_Y))
        elif self.lives == 0:
            surface.blit(self.image0, (HEART_POS_X, HEART_POS_Y))


def try_to_buy(new_tower, price):
    global money
    global text_surface
    
    if not valid_space(new_tower):
        return False
    
    if money >= price:
        money = money - price
        text_surface = my_font.render("money: " + str(money), False, TEXT_COLOR)
        
        return True

    return False

def add_money(price):
    global money
    global text_surface
    money = money + price
    text_surface = my_font.render("money: " + str(money), False, TEXT_COLOR)


def check_round_end():
    global enemy_list
    for i in range(len(enemy_list)):
        if (enemy_list[i].alive == 1):
            return False

    print("Level ended")
    return True

def level_up():
    global game_level
    global level_text_surface
    game_level = game_level + 1
    level_text_surface = my_font.render("Level: " + str(game_level), False, TEXT_COLOR)

    start_new_level(10, game_level * 100)


heart = Heart()

def start_new_level(count, health):
    global screen_scale_factor
    global enemy_list
    global heart
    enemy_list = []
    enemy_pos_x = 60 * screen_scale_factor
    enemy_pos_y = 350* screen_scale_factor
    for i in range(count):
        enemy_list.append(Enemy(-enemy_pos_x * i, enemy_pos_y, heart, health))


def valid_space(new_tower):
    global snowman_list
    global cakeman_list
    global reindeer_list

    combined_tower_list = snowman_list + cakeman_list + reindeer_list
    for old_tower in combined_tower_list:
        print("new: ")
        print(new_tower.rect)
        print("old: ")
        print(old_tower.rect)

        if new_tower.rect.colliderect(old_tower.rect):
            return False

    return True




menu_snowman  = MenuSnowman()
menu_cakeman  = MenuCakeman()
menu_reindeer = MenuReindeer()
# cakeman = CakeMan(300, 400)



enemy_pos_x = 60 * screen_scale_factor
enemy_pos_y = 350* screen_scale_factor

start_new_level(5, 100)


kagemand_animation_step = 0
kagemand_animation = []
kagemand_animation_temp = [
    pygame.image.load("kagemand/kagemand1.png").convert_alpha(), 
    pygame.image.load("kagemand/kagemand2.png").convert_alpha(), 
    pygame.image.load("kagemand/kagemand3.png").convert_alpha(), 
    pygame.image.load("kagemand/kagemand4.png").convert_alpha(), 
    pygame.image.load("kagemand/kagemand5.png").convert_alpha(),
    pygame.image.load("kagemand/kagemand6.png").convert_alpha(),
    pygame.image.load("kagemand/kagemand7.png").convert_alpha(),
    pygame.image.load("kagemand/kagemand8.png").convert_alpha()]


for animation_image in kagemand_animation_temp:
    img_rect = animation_image.get_rect()
    animation_image_new = pygame.transform.smoothscale(animation_image, (img_rect.w * screen_scale_factor, img_rect.h * screen_scale_factor) )
    kagemand_animation.append(animation_image_new)


mouse_down = 0

bg = pygame.image.load("background.png").convert_alpha()
bg = pygame.transform.smoothscale(bg, DISPLAYSURF.get_size())

mouse_snowman = Snowman(0, 0)
mouse_snowman.speed = -1
mouse_cakeman = CakeMan(0, 0)
mouse_reindeer = Reindeer(0, 0)

frame_count = 0

# heart_health = pygame.image.load("heart.png")

while True:     
    for event in pygame.event.get():              
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
    
    pressed_keys = pygame.key.get_pressed()
    if pressed_keys[K_ESCAPE]:
      sys.exit()

    DISPLAYSURF.blit(bg, (0, 0))
    if heart.lives <= 0:
        DISPLAYSURF.blit(you_died, (400, 400))
        pygame.display.update()
        FramePerSec.tick(10)
        frame_count = (frame_count + 1) % 16
        continue

    heart.draw(DISPLAYSURF)

    DISPLAYSURF.blit(exit_text_surface, (exit_text_x, exit_text_y))
    # cakeman.draw(DISPLAYSURF)
    #menu_snowman.update()
    for snowman in snowman_list:
        snowman.draw(DISPLAYSURF)

    for reindeer in reindeer_list:
        reindeer.draw(DISPLAYSURF)
    
    for cakeman in cakeman_list:
        # cakeman.draw(DISPLAYSURF)

        kagemand_image = kagemand_animation[cakeman.animation_step]
        kagemand_rect = kagemand_image.get_rect()
        kagemand_rect.center = cakeman.rect.center
        DISPLAYSURF.blit(kagemand_image, kagemand_rect)
    
        if frame_count == 0:
            cakeman.animation_step = (cakeman.animation_step + 1) % len(kagemand_animation)

            if cakeman.animation_step == 7:
                rect = cakeman.rect
                for enemy in enemy_list:
                    if enemy.alive:
                        if enemy.rect.colliderect(rect):
                            enemy.damage(100)
             

    for enemy in enemy_list:
        if enemy.alive:
            enemy.move(menu_snowman)
            enemy.draw(DISPLAYSURF)
            
            # for cakeman in cakeman_list:
            #     if cakeman.animation_step == 7:
            #      rect = cakeman.rect
            #      # print(rect)
            #      
            #      if enemy.rect.colliderect(rect):
            #          enemy.damage(100)
            #          add_money(1000)

    if event.type == MOUSEBUTTONDOWN:

        if event.button == MOUSE_BUTTON_RIGHT:
            menu_snowman.selected = 0
            menu_cakeman.selected = 0
            menu_reindeer.selected = 0
        else:
            if mouse_down == 0:
                mouse_down = 1
                mouse_pos = event.pos
                # print(mouse_pos)
                
                
                # print("exit rect: " + str(exit_rect))
                if exit_rect.collidepoint(mouse_pos):
                    exit()

                #
                # Menu snowman
                #
                if menu_snowman.selected == 1:

                    if try_to_buy(mouse_snowman, menu_snowman.price):
                        snowman_list.append(Snowman(mouse_pos[0], mouse_pos[1]))
                        # print(len(snowman_list))
                    
                    menu_snowman.selected = 0
                
                
                if menu_snowman.rect.collidepoint(mouse_pos):
                    # print("Clickmenusnowman")
                    if money >= menu_snowman.price:
                        menu_snowman.selected = 1

                #
                # menu cakeman
                #

                if menu_cakeman.selected == 1:

                    if try_to_buy(mouse_cakeman, menu_cakeman.price):
                        mouse_pos = pygame.mouse.get_pos()
                        cakeman_list.append(CakeMan(mouse_pos[0], mouse_pos[1]))
                        # print(len(snowman_list))
                    
                    menu_cakeman.selected = 0
                
                #
                # Menu Reindeer
                #
                if menu_reindeer.selected == 1:

                    if try_to_buy(mouse_reindeer, menu_reindeer.price):
                        mouse_pos = pygame.mouse.get_pos()
                        reindeer_list.append(Reindeer(mouse_pos[0], mouse_pos[1]))
                        # print(len(snowman_list))
                    
                    menu_reindeer.selected = 0


                if menu_cakeman.rect.collidepoint(mouse_pos):
                    if money >= menu_cakeman.price:
                        menu_cakeman.selected = 1


                if menu_reindeer.rect.collidepoint(mouse_pos):
                    if money >= menu_reindeer.price:
                        menu_reindeer.selected = 1


    elif event.type == MOUSEBUTTONUP:
        mouse_down = 0


    if (frame_count % 4) == 0:
        kagemand_animation_step = (kagemand_animation_step + 1) % 8
    
    for snowball in snowball_list:    
        snowball.move(menu_snowman)
        snowball.draw(DISPLAYSURF)

    for laser_beam in laser_beam_list:    
        laser_beam.move(enemy_list)
        laser_beam.draw(DISPLAYSURF)
        
    
    if menu_snowman.selected == 1:
        if event.type == pygame.MOUSEMOTION:
            mouse_pos = pygame.mouse.get_pos()
            mouse_snowman.rect.center = (mouse_pos[0], mouse_pos[1])
            mouse_snowman.draw(DISPLAYSURF)
    elif menu_cakeman.selected == 1:
        if event.type == pygame.MOUSEMOTION:
            mouse_pos = pygame.mouse.get_pos()
            mouse_cakeman.rect.center = (mouse_pos[0], mouse_pos[1])
            mouse_cakeman.draw(DISPLAYSURF)
    elif menu_reindeer.selected == 1:
        if event.type == pygame.MOUSEMOTION:
            mouse_pos = pygame.mouse.get_pos()
            mouse_reindeer.rect.center = (mouse_pos[0], mouse_pos[1])
            mouse_reindeer.draw(DISPLAYSURF)


    #DISPLAYSURF.fill(WHITE)
    menu_snowman.draw(DISPLAYSURF)
    menu_cakeman.draw(DISPLAYSURF)
    menu_reindeer.draw(DISPLAYSURF)
    
    
    DISPLAYSURF.blit(text_surface, (text_surface_x, text_surface_y))
    DISPLAYSURF.blit(level_text_surface, (level_text_surface_x, level_text_surface_y))

    frame_count = (frame_count + 1) % 16

    if (check_round_end()):
        level_up()

    pygame.display.update()
    FramePerSec.tick(FPS)