"""
    Allegro Python port game example
    Author: Jeroen De Busser
"""

from allegro import *
from random import randint
import os


class Pallet:
    def __init__(self, x, y, h, w, speed, keyup, keydown, color):
        self.x, self.y, self.h, self.w, self.speed, self.keyup, self.keydown, self.color = x, y, h, w, speed, keyup, keydown, color
        self.moving = 0

    def handle_event(self, ev):
        if ev.type == ALLEGRO_EVENT_KEY_DOWN:
            if ev.keyboard.keycode == self.keyup:
                self.moving = -1
            elif ev.keyboard.keycode == self.keydown:
                self.moving = 1
        elif ev.type == ALLEGRO_EVENT_KEY_UP:
            if (ev.keyboard.keycode == self.keyup and self.moving == -1) or (ev.keyboard.keycode == self.keydown and self.moving == 1):
                self.moving = 0
    
    def update(self):
        self.y += self.moving * self.speed
        if self.y < 0:
            self.y = 0
        elif self.y > al_get_display_height(al_get_current_display()) - self.h:
            self.y = al_get_display_height(al_get_current_display()) - self.h
    
    def draw(self):
        # Fill
        al_draw_filled_rounded_rectangle(self.x, self.y, self.x + self.w, self.y + self.h, 6, 6, self.color)
        # Highlight
        al_draw_filled_rounded_rectangle(self.x+2, self.y+2, self.x + self.w/2, self.y + self.h-5, 4, 4, al_map_rgba_f(0.2,0.2,0.2,0.2))


class Ball:
    def __init__(self, x, y, speed, size, pallets, color):
        self.x, self.y, self.speed, self.size, self.pallets, self.color = x, y, speed, size, pallets, color
        self.xdir = randint(0,1)
        self.ydir = randint(0,1)

    def update(self):
        new_x = self.x + (self.xdir - int(self.xdir == 0)) * self.speed
        new_y = self.y + (int(self.ydir == 0) - self.ydir) * self.speed
        p = self.pallets[self.xdir] #The pallet this ball is flying to
        if ((new_x <= p.x + p.w and self.xdir == 0) or (new_x + self.size >= p.x and self.xdir == 1)) and new_y + self.size >= p.y and new_y <= p.y + p.h:
            #We hit the pallet
            self.xdir = (self.xdir + 1) % 2
            new_x = self.x #Reset the x value
            self.speed += 0.1 #Increase the difficulty
        if new_y < 0 or new_y + self.size > al_get_display_height(al_get_current_display()):
            #We hit a wall
            self.ydir = (self.ydir + 1) % 2
            new_y = self.y #Reset the y value
        self.x = new_x
        self.y = new_y

    def draw(self):
        #Fill
        al_draw_filled_circle(self.x + self.size/2, self.y + self.size/2, self.size/2, self.color)
        #Highlight
        al_draw_filled_circle(self.x + self.size/4, self.y + self.size/4, self.size/6, al_map_rgb_f(0.8,0.9,0.8))


def main():
    #Initialisation
    al_install_system(ALLEGRO_VERSION_INT, None)
    
    w, h = 800, 600
    #Make lines draw smoother
    al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST)
    al_set_new_display_option(ALLEGRO_SAMPLES, 4, ALLEGRO_SUGGEST)
    display = al_create_display(w, h)
    
    al_init_primitives_addon()
    al_install_keyboard()
    al_init_image_addon()
    al_init_font_addon()

    font = al_load_font("fixed_font.tga",0,0)

    finished = False
    need_redraw = True
    FPS = 60
    pallet_w, pallet_h, pallet_speed = 20, 80, 5
    ball_size, ball_speed = 30, 4
    left_player = Pallet(0,h/2-pallet_h/2,pallet_h,pallet_w,pallet_speed,ALLEGRO_KEY_W,ALLEGRO_KEY_S,al_map_rgb_f(1.0,0.0,0.0))
    right_player = Pallet(w-pallet_w,h/2-pallet_h/2, pallet_h, pallet_w, pallet_speed, ALLEGRO_KEY_UP,ALLEGRO_KEY_DOWN,al_map_rgb_f(0.0,0.0,1.0))
    ball = Ball(w/2,h/2,ball_speed,ball_size,[left_player,right_player],al_map_rgb_f(0,1.0,0))

    timer = al_create_timer(1.0/FPS)

    queue = al_create_event_queue()
    al_register_event_source(queue, al_get_timer_event_source(timer))
    al_register_event_source(queue, al_get_keyboard_event_source())
    al_register_event_source(queue, al_get_display_event_source(display))

    al_start_timer(timer)

    while True:
        ev = ALLEGRO_EVENT()

        if need_redraw and al_is_event_queue_empty(queue):
            al_clear_to_color(al_map_rgb_f(0,0,0))
            left_player.draw()
            right_player.draw()
            ball.draw()
            if not finished:
                al_draw_text(font, al_map_rgb_f(1,1,1), w/2, 10, ALLEGRO_ALIGN_CENTRE, "Player 1: use W and S to move, Player 2: use the up and down arrow keys.")
            else:
                al_draw_text(font, al_map_rgb_f(1,1,1), w/2, 10, ALLEGRO_ALIGN_CENTRE, "Press R to reset, ESC to exit.")
            al_flip_display()
            redraw = False
        
        al_wait_for_event(queue,byref(ev))

        if ev.type == ALLEGRO_EVENT_TIMER:
            left_player.update()
            right_player.update()
            ball.update()
            if ball.x + ball.size < 0 or ball.x > w:
                finished = True
                al_stop_timer(timer)
            redraw = True
        elif (ev.type == ALLEGRO_EVENT_KEY_DOWN and ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) or ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE:
            break
        elif ev.type == ALLEGRO_EVENT_KEY_DOWN and ev.keyboard.keycode == ALLEGRO_KEY_R:
            ball.x = w/2
            ball.y = h/2
            ball.speed = ball_speed
            al_start_timer(timer)
            finished = False
        else:
            left_player.handle_event(ev)
            right_player.handle_event(ev)

    al_uninstall_system()


if __name__ == '__main__':
    #Only start the game when this file is executed directly.
    al_main(main)
