
#include <cstdio>

#include "allegro5/allegro.h"
#include "allegro5/allegro_font.h"
#include "allegro5/allegro_ttf.h"


class AllegroSetup {
private :
   ALLEGRO_DISPLAY* display;
   ALLEGRO_TIMER* timer;
   ALLEGRO_EVENT_QUEUE* event_queue;
   bool ready;
public :
   AllegroSetup(int w , int h , double tick_time) :
      display(0),
      timer(0),
      event_queue(0),
      ready(false)
   {
      if (!al_init()) {printf("Failed to initialize Allegro.\n");return;}
      if (!(display = al_create_display(w,h))) {
         printf("Failed to create %i X %i display.\n" , w , h);
         return;
      }
      if (!(timer = al_create_timer(tick_time))) {
         printf("Failed to create %lg paced timer.\n" , tick_time);
         return;
      }
      if (!al_install_keyboard()) {
         printf("Failed to initialize keyboard.\n");
         return;
      }
      if (!al_install_mouse()) {
         printf("Failed to install mouse.\n");
         return;
      }
      if (!(event_queue = al_create_event_queue())) {
         printf("Failed to create event queue.\n");
         return;
      }
      al_register_event_source(event_queue , al_get_keyboard_event_source());
      al_register_event_source(event_queue , al_get_display_event_source(display));
      al_register_event_source(event_queue , al_get_mouse_event_source());
      al_register_event_source(event_queue , al_get_timer_event_source(timer));
      ready = true;
   }

   ~AllegroSetup() {
      if (event_queue) {al_destroy_event_queue(event_queue);}
      if (display) {al_destroy_display(display);}
   }

   bool Ready() {return ready;}

   inline operator ALLEGRO_DISPLAY* () {return display;}
   inline operator ALLEGRO_EVENT_QUEUE* () {return event_queue;}
   inline operator ALLEGRO_TIMER* () {return timer;}
};


int readkey(ALLEGRO_EVENT_QUEUE* eq) {
   while (1) {
      ALLEGRO_EVENT ev;
      al_wait_for_event(eq , &ev);
      if (ev.type == ALLEGRO_EVENT_KEY_CHAR) {
         return ev.keyboard.keycode;
      }
   }
   return 0;
}



int main(int argc , char** argv) {
   
   //const char* font_name = "consolata.ttf";
   //const char* font_name = "Inconsolata.otf";
   const char* font_name = "data/DejaVuSans.ttf";
   
   if (argc > 1) {
      font_name = argv[1];
   }
   
   
   AllegroSetup allegro(800,600,1.0/60.0);
   if (!allegro.Ready()) {return 1;}
   
   al_init_font_addon();
   al_init_ttf_addon();
   
   double start = 0.0;
   double stop = 0.0;
   double display_time = 0.0;
   
   double total_display_time = 0.0;
   
   int count = 0;
   
   const int NUM = 13;
   const char* strs[NUM] = {
      "abcde",
      "fghij",
      "klmno",
      "pqrst",
      "uvwxyz",
      "01234",
      "56789",
      "!@#$%",
      "^&*()",
      "-=_+",
      "[]{}\\|",
      ",.<>/?",
      ";:'\""
   };

   ALLEGRO_FONT* font = al_load_ttf_font(font_name , -20 , 0);
   if (!font) {
      printf("Font file %s failed to load!\n" , font_name);
      return -1;
   }

   ALLEGRO_COLOR white = al_map_rgb(255,255,255);
   // cache the first time
   for (int i = 0 ; i < NUM ; ++i) {
      al_draw_text(font , white , 10 , 10 + 30*i , 0 , strs[i]);
   }
   
   bool quit = false;
   
   while (!quit) {
      ALLEGRO_EVENT ev;
      while (!al_is_event_queue_empty(allegro)) {
         al_wait_for_event(allegro , &ev);
         if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
            quit = true;
            break;
         }
         else if (ev.type == ALLEGRO_EVENT_KEY_DOWN) {
            if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) {
               quit = true;
               break;
            }
         }
      }
      if (quit) {
         if (!count) {count = 1;}
         break;
      }
      
      al_clear_to_color(al_map_rgb(0,0,0));
      
      // measure drawing time
      start = al_get_time();
      for (int j = 0; j < 1000; j++) {
         for (int i = 0 ; i < NUM ; ++i) {
   //void al_draw_text(const ALLEGRO_FONT *font , ALLEGRO_COLOR color, float x , float y , int flags , char const *text)
            al_draw_text(font , white , 10 , 10 + 30*i , 0 , strs[i]);
         }
         count++;
      }
      stop = al_get_time();
      display_time = stop - start;
      total_display_time += display_time;
      
//void al_draw_textf(const ALLEGRO_FONT *font, ALLEGRO_COLOR color , float x , float y , int flags , const char *format, ...)
      al_draw_textf(font , white , 410 , 100 , 0 , "Average draw time  = %0.4f ms" , 1000.0f*((float)total_display_time / (float)count));
      al_draw_textf(font , white , 410 , 130 , 0 , "Test count = %i tests" , count);
      
      al_flip_display();
   }
      
   al_destroy_font(font);

   printf("Average display time  = %0.4lf ms\n" , 1000.0*(total_display_time / (double)count));
   printf("Test count = %i\n" , count);
   
   return 0;
}
