import sys
from tilemap import *
from sprites import *
from os import path
from tilemap import collide_hit_rect_bis



def draw_player_health(surf,x,y,pct):
    if pct <0:
        pct = 0
    BAR_LENGTH = 100
    BAR_HEIGHT = 20
    fill = pct * BAR_LENGTH
    outline_rect = pg.Rect(x,y,BAR_LENGTH,BAR_HEIGHT)
    fill_rect = pg.Rect(x,y,fill,BAR_HEIGHT)
    if pct > 0.6:
        col = BGREEN
    elif pct > 0.3:
        col = YELLOW
    else:
        col = RED
    pg.draw.rect(surf,col,fill_rect)
    pg.draw.rect(surf,WHITE,outline_rect,2)

class Game:
    def __init__(self):
        pg.init()
        self.screen = pg.display.set_mode((WIDTH, HEIGHT))
        pg.display.set_caption(TITLE)
        self.clock = pg.time.Clock()
        #pg.key.set_repeat(500, 100)
        self.load_data()


    def draw_text(self, text, font_name, size, color, x, y, align="nw"):
        font = pg.font.Font(font_name, size)
        text_surface = font.render(text, True, color)
        text_rect = text_surface.get_rect()
        if align == "nw":
            text_rect.topleft = (x, y)
        if align == "ne":
            text_rect.topright = (x, y)
        if align == "sw":
            text_rect.bottomleft = (x, y)
        if align == "se":
            text_rect.bottomright = (x, y)
        if align == "n":
            text_rect.midtop = (x, y)
        if align == "s":
            text_rect.midbottom = (x, y)
        if align == "e":
            text_rect.midright = (x, y)
        if align == "w":
            text_rect.midleft = (x, y)
        if align == "center":
            text_rect.center = (x, y)
        self.screen.blit(text_surface, text_rect)

    def load_data(self):
        game_folder = path.dirname(__file__)
        img_folder = path.join(game_folder,'img')
        snd_folder = path.join(game_folder,'snd')
        music_folder = path.join(game_folder,'music')
        self.title_font = path.join(img_folder,'ZOMBIE.TTF')
        self.dim_screen = pg.Surface(self.screen.get_size()).convert_alpha()
        self.dim_screen.fill((0,0,0,100))
        self.splat_green = pg.image.load(path.join(img_folder,'splat green.png')).convert_alpha()
        self.splat_red = pg.image.load(path.join(img_folder,'splat red.png')).convert_alpha()
        self.splat_green = pg.transform.scale(self.splat_green,(64,64))
        self.splat_red = pg.transform.scale(self.splat_red,(64,64))

        self.player_img = pg.image.load(path.join(img_folder,PLAYER_IMG)).convert_alpha()
        self.mob_img = pg.image.load(path.join(img_folder, MOB_IMG)).convert_alpha()
        self.gun_flashes = []
        for img in MUZZLE_FLASHES:
            self.gun_flashes.append(pg.image.load(path.join(img_folder,img)).convert_alpha())
        self.item_images = {}
        for item in ITEM_IMAGES:
            self.item_images[item] = pg.transform.scale(pg.image.load(path.join(img_folder,ITEM_IMAGES[item])).convert_alpha(),(30,30))
        pg.mixer.music.load(path.join(music_folder,BG_MUSIC))
        self.effects_sound ={}
        for type in EFFECTS_SOUNDS:
            self.effects_sound[type] = pg.mixer.Sound(path.join(snd_folder,EFFECTS_SOUNDS[type]))
        self.weapons_sounds = {}
        self.weapons_sounds['gun'] = []
        for snd in WEAPON_SOUNDS_GUN:
            s = pg.mixer.Sound(path.join(snd_folder,snd))
            s.set_volume(0.1)
            self.weapons_sounds['gun'].append(s)
        self.zombie_moan_sounds = []
        for snd in ZOMBIE_MOAN_SOUNDS:
            s = pg.mixer.Sound(path.join(snd_folder,snd))
            s.set_volume(0.1)
            self.zombie_moan_sounds.append(s)
        self.player_hit_sounds = []
        for snd in PLAYER_HIT_SOUNDS:
            self.player_hit_sounds.append(pg.mixer.Sound(path.join(snd_folder, snd)))
        self.zombie_hit_sounds = []
        for snd in ZOMBIE_HIT_SOUNDS:
            self.zombie_hit_sounds.append(pg.mixer.Sound(path.join(snd_folder, snd)))

    def new(self):
        # initialize all variables and do all the setup for a new game
        self.all_sprites = pg.sprite.LayeredUpdates()
        self.walls = pg.sprite.Group()
        self.collectable = pg.sprite.Group()
        self.bullets = pg.sprite.Group()
        self.items = pg.sprite.Group()
        game_folder = path.dirname(__file__)
        map_folder = path.join(game_folder,'maps')
        self.map = TiledMap(path.join(map_folder,'testmap.tmx'))
        self.map_img = self.map.make_map()
        self.map_rect = self.map_img.get_rect()
        self.mobs = pg.sprite.Group()
        """for row, tiles in enumerate (self.map.data):
            for col, tile in enumerate(tiles):
                if tile == '1':
                    Wall(self,col,row)
                if tile == 'P':
                    self.player = Player(self, col,row)
                if tile == 'c':
                    Collectable(self,col,row)
                if tile == 'm':
                    Mobs(self,col,row)"""
        for tile_object in self.map.tmxdata.objects:
            obj_center = vec(tile_object.x + tile_object.width /2, tile_object.y + tile_object.height /2)
            if tile_object.name == 'player':
                self.player = Player(self,obj_center.x,obj_center.y)
            if tile_object.name == 'wall':
                Obstacle(self,tile_object.x,tile_object.y,tile_object.width,tile_object.height)
            if tile_object.name == 'zombie':
                Mobs(self,obj_center.x,obj_center.y)
            if tile_object.name in ['health_pack']:
                Item(self,obj_center,tile_object.name)
        self.camera = Camera(self.map.width, self.map.height)
        self.draw_debug = False
        self.paused = False
        self.effects_sound['level_start'].play()

    def run(self):
        self.playing = True
        pg.mixer.music.play(loops=-1)
        while self.playing:
            self.dt = self.clock.tick(FPS) / 1000
            self.events()
            if not self.paused:
                self.update()
            self.draw()

    def quit(self):
        pg.quit()
        sys.exit()

    def update(self):
        self.all_sprites.update()
        self.camera.update(self.player)
        if len(self.mobs) == 0:
            self.playing = False
        hits = pg.sprite.spritecollide(self.player,self.items,False)

        for hit in hits:
            if hit.type == 'health_pack' and self.player.health < PLAYER_HEALTH:
                hit.kill()
                self.effects_sound['health_up'].play()
                self.player.add_health(HEALTH_PACK_AMOUNT)
        hits = pg.sprite.spritecollide(self.player,self.mobs,False,collide_hit_rect_bis)
        for hit in hits:
            if random() < 0.7:
                choice(self.player_hit_sounds).play()
            self.player.health -= MOB_DAMAGE
            hit.vel = vec(0,0)
            if self.player.health <= 0:
                self.playing = False
        if hits:
            self.player.pos += vec(MOB_KNOCKBACK,0).rotate(-hits[0].rot)
        hits = pg.sprite.groupcollide(self.mobs,self.bullets,False,True,collide_hit_rect_bis)
        for hit in hits:
            hit.health -= BULLET_DAMAGE
            hit.vel = vec(0,0)


    def draw_grid(self):
        for x in range(0, WIDTH, TILESIZE):
            pg.draw.line(self.screen, LIGHTGREY, (x, 0), (x, HEIGHT))
        for y in range(0, HEIGHT, TILESIZE):
            pg.draw.line(self.screen, LIGHTGREY, (0, y), (WIDTH, y))

    def draw(self):
        self.screen.blit(self.map_img,self.camera.apply_rect(self.map_rect))
        pg.display.set_caption("{:.2f}".format(self.clock.get_fps()))
        "self.draw_grid()"
        for sprite in self.all_sprites:
            if isinstance(sprite,Mobs):
                sprite.draw_health()
            self.screen.blit(sprite.image, self.camera.apply(sprite))
            if self.draw_debug:
                pg.draw.rect(self.screen,WHITE,self.camera.apply_rect(sprite.hit_rect),1)
        for wall in self.walls:
            if self.draw_debug:
                pg.draw.rect(self.screen,WHITE,self.camera.apply_rect(wall.rect),1)
        draw_player_health(self.screen,10,10,self.player.health / PLAYER_HEALTH)
        self.draw_text('Zombies {}'.format(len(self.mobs)),self.title_font,30,WHITE,WIDTH -10,10,align="ne")
        if self.paused:
            self.draw_text("Paused",self.title_font,185,RED,WIDTH / 2, HEIGHT / 2, "center")
            self.screen.blit(self.dim_screen,(0,0))
        pg.display.flip()

    def events(self):
        # catch all events here
        for event in pg.event.get():
            if event.type == pg.QUIT:
                self.quit()
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_ESCAPE:
                    self.quit()
                if event.key == pg.K_h:
                    self.draw_debug = not self.draw_debug
                if event.key == pg.K_p:
                    self.paused = not self.paused



    def show_start_screen(self):
        pass

    def show_go_screen(self):
        pass

# create the game object
g = Game()
#g.show_start_screen()
while True:
    g.new()
    g.run()
    #g.show_go_screen()