#include <iostream>
#include <stdio.h>

#include <allegro5/allegro.h>
#include <allegro5/allegro_ttf.h>
#include <allegro5/allegro_image.h>
#include <allegro5/allegro_audio.h>
#include <allegro5/allegro_acodec.h>
#include <list>

#include "ball.h"
#include "background.h"
#include "rocket.h"
#include "globals.h"

using std::cout;    using std::cin;
using std::endl;    using std::list;

//GLOBALS
Rocket *P1;
Rocket *P2;
Ball *ball;
Background *pong_table;
list<Game_object *>objects;
list<Game_object *>::iterator iter;
list<Game_object *>::iterator iter2;

bool keys[4] = { false, false, false };
enum KEYS{ UP, DOWN, ENTER };

void Change_state(int &state, int new_state);

int main(int argc, char *argv[])
{
    //SHELL VARIABLES
    bool done = false;
    bool render = false;
    int state = 0;

    int game_time = 0;
    int dt = 0;

    int count_frames = 0;

    //PROJECT VARIABLES
    ball = new Ball();
    pong_table = new Background();
    P1 = new Rocket();
    P2 = new Rocket();
    ALLEGRO_BITMAP *rocket_image = NULL;
    ALLEGRO_BITMAP *ball_image = NULL;
    ALLEGRO_BITMAP *background_image = NULL;
    ALLEGRO_BITMAP *title_image = NULL;
    ALLEGRO_BITMAP *icon = NULL;

    //ALLEGRO VARIABLES
    ALLEGRO_DISPLAY *display;
    ALLEGRO_FONT * font;
    ALLEGRO_EVENT_QUEUE *event_queue;
    ALLEGRO_TIMER *timer;
    ALLEGRO_SAMPLE *ball_sound;
    ALLEGRO_SAMPLE *rocket_sound;

    //ALLEGRO INIT
    if (!al_init())
    cout <<"allegro initialization fail!";

    al_init_font_addon();
    al_init_image_addon();
    al_install_audio();
    al_init_acodec_addon();
    al_install_keyboard();
    al_init_primitives_addon();

    display = al_create_display(width, height);
    al_set_window_title(display, "Super Pong!");

    al_flip_display();

    //PROJECT INIT
    srand(time(NULL));
    al_reserve_samples(4);

    rocket_image = al_load_bitmap( "../source/rockets/rocket01.png" );
    background_image = al_load_bitmap( "../source/backgrounds/background01.png" );
    ball_image = al_load_bitmap( "../source/balls/ball01.png" );
    title_image = al_load_bitmap( "../source/gui/title_screen.png" );
    icon = al_load_bitmap( "../source/icon.tga" );

    al_convert_mask_to_alpha( ball_image, al_map_rgb(255, 0, 255) );
    al_convert_mask_to_alpha( icon, al_map_rgb(255, 0, 255) );

    al_set_display_icon(display, icon);

    rocket_sound = al_load_sample( "../source/sound/beep02.ogg" );
    P1 ->Init(0, rocket_image, rocket_sound);
    P2 ->Init(1, rocket_image, rocket_sound);
    pong_table ->Init(background_image);

    ball_sound = al_load_sample( "../source/sound/beep01.ogg" );
    ball ->Init( ball_sound, ball_image, 100, 100);

    //PUSH OBJECT TO LIST
    objects.push_back(pong_table);
    objects.push_back(ball);
    objects.push_back(P1);
    objects.push_back(P2);

    font = al_create_builtin_font();
    al_set_target_bitmap(al_get_backbuffer(display));

    event_queue = al_create_event_queue();
    al_register_event_source(event_queue, al_get_keyboard_event_source());
    al_register_event_source(event_queue, al_get_display_event_source(display));

    Change_state(state, TITLE);

    //start timer
    timer = al_create_timer(1.0 / 60);
    al_register_event_source(event_queue, al_get_timer_event_source(timer));
    al_start_timer(timer);

    cout << "loading done!" << endl;
    game_time = al_current_time();

    //MAIN LOOP ------------------
    while(!done){
            ALLEGRO_EVENT event;
            al_wait_for_event(event_queue, &event);
            if(event.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
                done = true;

        // KEYS UPDATE
        if(event.type == ALLEGRO_EVENT_KEY_DOWN)
        {
            switch(event.keyboard.keycode)
            {
                case ALLEGRO_KEY_UP:
                    keys[UP] = true;
                    break;
                case ALLEGRO_KEY_DOWN:
                    keys[DOWN] = true;
                    break;
                case ALLEGRO_KEY_ENTER:
                    keys[ENTER] = true;
                    break;
            }
        }
        if(event.type == ALLEGRO_EVENT_KEY_UP)
        {
            switch(event.keyboard.keycode)
            {
                case ALLEGRO_KEY_UP:
                    keys[UP] = false;
                    break;
                case ALLEGRO_KEY_DOWN:
                    keys[DOWN] = false;
                    break;
                case ALLEGRO_KEY_ENTER:
                    keys[ENTER] = false;
                    break;
            }
        }
            //GAME UPDATE
            if(event.type == ALLEGRO_EVENT_TIMER)
            {
                // LOADING RENDER
                if(dt >= 50)
                render = true;
                else
                {
                    al_draw_textf(font, al_map_rgb(255,255,255), width / 2, height / 2, ALLEGRO_ALIGN_CENTER, "LODING...");
                    al_flip_display();
                }

                //fps update ==========
                count_frames ++;
                if(al_current_time() - game_time >= 1)
                {
                    game_time = al_current_time();
                    dt = count_frames;
                    count_frames = 0;
                }
                //======================


                if (state == GAME){
                //update

                for(iter = objects.begin(); iter != objects.end(); ++iter)
                    (*iter)->Update();

                //collisions
                ball ->Collision();
                P1 ->Collision();
                P2 ->Collision();
                }
                if (state == TITLE){
                    if(keys[ENTER])
                        Change_state(state, GAME);
                }
            }

            // RENDER ----------------------------------------------------------------------
            if(render && al_is_event_queue_empty(event_queue))
            {
                render = false;

                // TITLE RENDER
                if(state == TITLE)
                {
                    al_draw_bitmap(title_image, 0, 0, 0);
                    al_draw_textf(font, al_map_rgb(255,255,255), 10, height - 15, 0, "FPS: %i", dt);

                }
                // GAME ELEMENTS RENDER
                else if(state == GAME)
                {
                    if(keys[UP])
                    ball ->Init(ball_sound, ball_image, 100, 100);
                    //project render ------
                    for(iter = objects.begin(); iter != objects.end(); ++iter)
                        (*iter)->Render();

                    al_draw_textf(font, al_map_rgb(255,255,255), 10, height - 15, 0, "FPS: %i", dt);
                    al_draw_textf(font, al_map_rgb(255,255,255), width / 2, 10, ALLEGRO_ALIGN_CENTER, "points: %i", P1 ->Get_score());
                }

                //flip buffer
                al_flip_display();
                al_clear_to_color(al_map_rgb(0,0,40));
            }
    }
    al_destroy_bitmap(icon);
    al_destroy_bitmap(ball_image);
    al_destroy_bitmap(background_image);
    al_destroy_display(display);
    al_destroy_font(font);
    al_destroy_timer(timer);
    al_destroy_event_queue(event_queue);
    al_destroy_sample(ball_sound);
    al_destroy_sample(rocket_sound);
    return 0;
}

void Change_state(int &state, int new_state)
{
    if(state == TITLE)
    {}
    else if(state == GAME)
    {}

    state = new_state;

    if(state == TITLE)
    {}
    else if(state == GAME)
    {}
}
