#imports
import pygame

#initialize pygame
pygame.init()

# Class for the player character to tidy up code
class Player():
    def __init__(self, x, y, width, height):
        self.x = x
        self.y = y
        self.width = width  # screen parameters
        self.height = height  # screen parameters
        self.velocity = 12  # speed of objects in level
        self.jumping = False  # check if jumping
        self.jumpcount = 10
        self.walk_count = 0
        self.left = False  # check if player is moving left
        self.right = False  # check if player is moving right
        self.hitbox = (self.x + 12, self.y, 25, 68)#make player hitbox

    # Draw player (make it visible)
    def draw(self, screen):
        if self.left:  # Only update animation if moving left
            screen.blit(walk_left[self.walk_count // 3], (self.x, self.y))  # Blit the appropriate image from walk_left list
            self.walk_count = (self.walk_count + 1) % (len(walk_left) * 3)  # Update walk_count, looping it back when needed
        elif self.right:  # Only update animation if moving right
            screen.blit(walk_right[self.walk_count // 3], (self.x, self.y))  # Blit the appropriate image from walk_right list
            self.walk_count = (self.walk_count + 1) % (len(walk_right) * 3)  # Update walk_count, looping it back when needed
        else:  # If no keys pressed, show idle animation
            if direction == -1:
                screen.blit(idle_img_left, (self.x, self.y))
            else:
                screen.blit(idle_img, (self.x, self.y))
        self.hitbox = (self.x + 12, self.y, 25, 68)#moving hitbox with player
        pygame.draw.rect(screen, (255, 0, 0), self.hitbox,2)
        
#class to make projectiles
class projectile():
    def __init__(self, x, y, radius, colour, facing):
        self.x = x
        self.y = y
        self.radius = radius
        self.colour = colour
        self.facing = facing
        self.vel = 18 #speed of projectile

    def draw(self,screen):
        pygame.draw.circle(screen, self.colour, (self.x, self.y), self.radius)

#class for enemy
class Enemy():
    def __init__(self, x, y, width, height, end):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.end = end
        self.path = [self.x, self.end]
        self.walk_count = 0
        self.velocity = 8
        self.hitbox = (self.x + 8, self.y, 37, 70)#make enemy hitbox
    
    def draw(self,screen):
        self.move()
        if self.walk_count + 1 >= 9:
            self.walk_count = 0

        if self.velocity > 0:
            screen.blit(enemy_walk_right[self.walk_count //3], (self.x, self.y))
            self.walk_count += 1
        else:
            screen.blit(enemy_walk_left[self.walk_count //3], (self.x, self.y))
            self.walk_count += 1

        self.hitbox = (self.x + 8, self.y, 37, 70)#moving hitbox with enemy
        pygame.draw.rect(screen, (255, 0, 0), self.hitbox,2)

    def move(self):
        if self.velocity > 0:
            if self.x + self.velocity < self.path[1]:
                self.x += self.velocity
            else:
                self.velocity = self.velocity * -1
                self.walk_count = 0
        else:
            if self.x - self.velocity > self.path[0]:
                self.x += self.velocity
            else:
                self.velocity = self.velocity * -1
                self.walk_count = 0

    def hit(self):
        print('hit')

#List for bullets
bullets = []

# Set name of game window
pygame.display.set_caption('Platformer')

#vairables
player = Player(300, 410, 50, 69)
enemy = Enemy(100, 410, 50, 69, 450)
run = True
FPS = 20
clock = pygame.time.Clock()
screen_width = 1000
screen_height = 1000
screen = pygame.display.set_mode((screen_width, screen_height))
direction = 1
tile_size = 50

# Load images
idle_img = pygame.image.load('img/main_idle.png')
idle_img_left = pygame.transform.flip(idle_img, True, False)  # Flipping the image horizontally
enemy_idle1= pygame.image.load('img/enemy_idle.png') #facing right
enemy_idle2 = pygame.transform.flip(enemy_idle1, True, False) #facing left
enemy_run1 = pygame.image.load('img/enemy_run1.png')
enemy_run2 = pygame.image.load('img/enemy_run2.png')
run1_img = pygame.image.load('img/main_run1.png')
run2_img = pygame.image.load('img/main_run2.png')
bg1_img = pygame.image.load('img/bg_1.png')

#create a list of images for enemy walking animation in the right direction
enemy_walk_right = [enemy_run1, enemy_idle1, enemy_run2]
#flip images left
enemy_walk_left = [pygame.transform.flip(img, True, False) for img in enemy_walk_right]


# Create a list of images for walking animation in the right direction
walk_right = [run1_img, idle_img, run2_img]
# Flip the images horizontally to create a list of images for walking animation in the left direction
walk_left = [pygame.transform.flip(img, True, False) for img in walk_right]


# View grid of level makeup
#def draw_grid():
    #for line in range(0, 20):
        #pygame.draw.line(screen, (255, 255, 255), (0, line * tile_size), (screen_width, line * tile_size))
        #pygame.draw.line(screen, (255, 255, 255), (line * tile_size, 0), (line * tile_size, screen_height))

# Create world/levels
class World():
    def __init__(self, data):
        self.tile_list = []

        # World images
        groundx_img = pygame.image.load('img/platform_x.png')

        # World logic/world info
        row_count = 0
        for row in data:
            col_count = 0
            for tile in row:
                if tile == 1:
                    img = pygame.transform.scale(groundx_img, (tile_size, tile_size))
                    img_rect = img.get_rect()
                    img_rect.x = col_count * tile_size
                    img_rect.y = row_count * tile_size
                    tile = (img, img_rect)
                    self.tile_list.append(tile)
                col_count += 1
            row_count += 1

    def draw(self):
        for tile in self.tile_list:
            screen.blit(tile[0], tile[1])

# Make world data for level 1
level_1 = [
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
]

world1 = World(level_1)

# Game window function
def update_game_window():
    screen.blit(bg1_img, (0, 0))  # Display background
    world1.draw()  # draw world
    enemy.draw(screen)
    #draw_grid()
    player.draw(screen)  # draw player
    for bullet in bullets:
        bullet.draw(screen)#draw bullets
    pygame.display.update()  # Update display


# Main game loop
shoot = 0 #create a bullet cooldown

while run:

    if shoot > 0: #impliment shoot cooldowna
        shoot += 1
    if shoot > 3:
        shoot = 0

    for event in pygame.event.get():
        # Check if game has been closed
        if event.type == pygame.QUIT:
            run = False

    for bullet in bullets:
        if bullet.y - bullet.radius < enemy.hitbox[1] + enemy.hitbox[3] and bullet.y + bullet.radius > enemy.hitbox[1]: #check for collision
            if bullet.x + bullet.radius > enemy.hitbox[0] and bullet.x - bullet.radius < enemy.hitbox[0]+enemy.hitbox[2]: #check for collision
                enemy.hit()
                bullets.pop(bullets.index(bullet))#remove bullet after collision

        if bullet.x < 1000 and bullet.x > 0: #check if bullet is on screen
            bullet.x += bullet.vel * bullet.facing #adjusting the velocity based on direction of player
        else: #remove bullets that leave the screen
            bullets.pop(bullets.index(bullet))

    keys = pygame.key.get_pressed()  # Get the current state of keys

    #Fire bullet
    if keys[pygame.K_f] and shoot == 0:
        if player.left or direction == -1: #checking direction to be fired
            facing = -1
        else: #checking direction to be fired
            facing = 1
        if len(bullets) < 10: 
            bullets.append(projectile(player.x + player.width // 2, round(player.y + player.height // 2), 6, (0, 0, 0), facing))

        shoot = 1

    # Character movement
    if keys[pygame.K_a] and player.x > player.velocity:  # Move left within screen boundaries
        player.left = True
        player.right = False
        player.x -= player.velocity
        direction = -1
    elif keys[pygame.K_d] and player.x < screen_width - player.width - player.velocity:  # Move right within screen boundaries
        player.left = False
        player.right = True
        player.x += player.velocity
        direction = 1
    else:
        player.left = False
        player.right = False

    if not player.jumping:  # Allow actions when not jumping
        if keys[pygame.K_SPACE]:  # Check if space key is pressed
            player.jumping = True  # Start jumping
    else:
        if player.jumpcount >= -10:  # Control jump height and direction
            neg = 1
            if player.jumpcount < 0:
                neg = -1
            player.y -= (player.jumpcount ** 2) * 0.5 * neg  # Apply jump physics
            player.jumpcount -= 1
        else:
            player.jumping = False
            player.jumpcount = 10

    update_game_window()  # Update game window with animations

    clock.tick(FPS)  # Limit frames per second

pygame.quit()