/*
*****************************************
* This is Snake 256!                    *
* Author: Tony Wasserka                 *
* Version: 0.0.3                        *
* License: GPL                          *
* See Readme.txt                        *
* Enjoy this!                           *
*****************************************
*/

#include "snake.h"

BITMAP *screenbmp;

ALFONT_FONT *myfont[8];

double dtime;
float fps;
int fps_count;

float max_score = 0;

#ifdef ALLEGRO_WINDOWS
LONGLONG start_t, end_t;
double frequency;
#else
timeval start_t, end_t;
#endif

int scrshot_count = 0;

void UpdateFPS()
{
 fps = 1 / dtime;
}

void Reset()
{
 for(int a = 0;a < 8;a++)
  snake[a] = Snake(a);

 target.x = (rand() % SCREEN_W);
 target.y = (rand() % (SCREEN_H - Config::num_snakes * 15 - 5));
 target.r = 0;

 alfont_set_font_size(myfont[FONT_GETREADY], Config::screenw * 16 / 800);
 alfont_set_font_size(myfont[FONT_3], Config::screenw * 32 / 800);
 alfont_set_font_size(myfont[FONT_2], Config::screenw * 64 / 800);
 alfont_set_font_size(myfont[FONT_1], Config::screenw * 128 / 800);
 alfont_set_font_size(myfont[FONT_GO], Config::screenw * 256 / 800);
}

void Screenshot()
{
 char buf[256], buf2[32];

 for(int a = 0;;a++)
 {
  if(scrshot_count >= 1000) sprintf(buf2, "screenshot%d.bmp", scrshot_count);
  else if(scrshot_count >= 100) sprintf(buf2, "screenshot0%d.bmp", scrshot_count);
  else if(scrshot_count >= 10) sprintf(buf2, "screenshot00%d.bmp", scrshot_count);
  else sprintf(buf2, "screenshot000%d.bmp", scrshot_count);

  if(exists(buf2))
   scrshot_count++;
  else break;
 }
 get_executable_name(buf, sizeof(buf));
 replace_filename(buf, buf, buf2, sizeof(buf));
 save_bitmap(buf, screenbmp, NULL);

 while(key[KEY_F12]);
#ifdef ALLEGRO_WINDOWS
 QueryPerformanceCounter((LARGE_INTEGER*)(&start_t));
#else
 gettimeofday(&start_t, NULL);
#endif
}

int main()
{
 srand(time(NULL));
 allegro_init();
 alfont_init();

 GetConfig();

 install_keyboard();
 install_mouse();
 install_timer();
 set_color_depth(Config::bpp);

 if(set_gfx_mode(Config::card, Config::screenw, Config::screenh, 0, 0) != 0)
 {
  set_color_depth(32);
  if(set_gfx_mode(GFX_AUTODETECT, 800, 600, 0, 0) != 0)
  {
   set_color_depth(24);
   if(set_gfx_mode(GFX_AUTODETECT, 800, 600, 0, 0) != 0)
   {
    set_color_depth(16);
    if(set_gfx_mode(GFX_AUTODETECT, 800, 600, 0, 0) != 0)
    {
     set_color_depth(15);
     if(set_gfx_mode(GFX_AUTODETECT, 800, 600, 0, 0) != 0)
     {
      allegro_message("Couldn't set the graphics mode. The game will exit now.");
      exit(0);
     }
    }
   }
  }
  Config::screenw = 320;
  Config::screenh = 200;
  Config::bpp = get_color_depth();
 }
 install_int_ex(UpdateFPS, SECS_TO_TIMER(1));

 screenbmp = create_bitmap(SCREEN_W, SCREEN_H);
 clear_bitmap(screenbmp);

 {
  char buf[256];

  get_executable_name(buf, sizeof(buf));
  replace_filename(buf, buf, "suigener.ttf", sizeof(buf));

  for(int a = 0;a < 8;a++)
   myfont[a] = alfont_load_font(buf);
 }

 alfont_set_font_size(myfont[FONT_NORMAL], 16);
 alfont_set_font_size(myfont[FONT_SUBTITLE], 14);
 alfont_set_font_size(myfont[FONT_SNAKE256], 32);

#ifdef ALLEGRO_WINDOWS
 {
  LONGLONG freq;
  QueryPerformanceFrequency((LARGE_INTEGER*)(&freq));
  frequency = (double)freq;
 }
#endif

 Reset();
 Intro();

 dtime = 0.025;

 while(1)
  switch(DoMenu())
  {
   case MENU_SINGLEPLAYER: break;
   case MENU_MULTIPLAYER:
   {
    float count = 0;

    Reset();

    while(count < 6)
    {
     if(dtime)
#ifdef ALLEGRO_WINDOWS
      QueryPerformanceCounter((LARGE_INTEGER*)(&start_t));
#else
      gettimeofday(&start_t, NULL);
#endif
     for(int a = 0;a < Config::num_snakes;a++)
     {
      snake[a].Draw(screenbmp, dtime);
      alfont_textprintf_centre_ex(screenbmp, myfont[FONT_NORMAL], (int)snake[a].x[0], (int)snake[a].y[0] - 10, makecol((int)(255 * (6 - count) / 6.),
                                                                                                 (int)(255 * (6 - count) / 6),
                                                                                                 (int)(255 * (6 - count) / 6.)), -1, "Player %d",
                                                                                                                                     a + 1);
     }
     switch((int)count)
     {
      case 0: alfont_textout_centre_ex(screenbmp, myfont[FONT_GETREADY], "Get ready...", SCREEN_W / 2, SCREEN_H / 2 - Config::screenw / 100, makecol((int)(255 * (1 - count)), (int)(255 * (1 - count)),
                                                                                               (int)(255 * (1 - count))), -1); break;
      case 2: alfont_textout_centre_ex(screenbmp, myfont[FONT_3], "3...", SCREEN_W / 2, SCREEN_H / 2 - Config::screenw / 50, makecol((int)(255 * (3 - count)), (int)(255 * (3 - count)),
                                                                                       (int)(255 * (3 - count))), -1); break;
      case 3: alfont_textout_centre_ex(screenbmp, myfont[FONT_2], "2...", SCREEN_W / 2, SCREEN_H / 2 - Config::screenw / 25, makecol((int)(255 * (4 - count)), (int)(255 * (4 - count)),
                                                                                       (int)(255 * (4 - count))), -1); break;
      case 4: alfont_textout_centre_ex(screenbmp, myfont[FONT_1], "1...", SCREEN_W / 2, SCREEN_H / 2 - Config::screenw * 2 / 25, makecol((int)(255 * (5 - count)), (int)(255 * (5 - count)),
                                                                                       (int)(255 * (5 - count))), -1); break;
      case 5: if((int)(count * 5) % 2) alfont_textout_centre_ex(screenbmp, myfont[FONT_GO], "GO!!!", SCREEN_W / 2, SCREEN_H / 2 - Config::screenw * 4 / 25, makecol(255, 255, 255), -1); break;
     }
     rectfill(screenbmp, 0, SCREEN_H - Config::num_snakes * 15 - 5, SCREEN_W, SCREEN_H, makecol(128,128,128));

     for(int a = 0;a < Config::num_snakes;a++)
      if(!snake[a].state)
       snake[a].DrawScore(screenbmp, dtime * 120);

     if(Config::show_fps) alfont_textprintf_right_ex(screenbmp, myfont[FONT_NORMAL], SCREEN_W - 10, 10,
                                             makecol(255, 255, 255), -1,
                                             "FPS: %.2f", fps);

     if(key[KEY_F12]) Screenshot();

     switch(Config::bpp)
     {
      case 32: switch_antialias(32); break;
      case 16: switch_antialias(16); break;
      case 15: switch_antialias(15); break;
      default: blit(screenbmp, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
     }

     clear_bitmap(screenbmp);
#ifdef ALLEGRO_WINDOWS
     QueryPerformanceCounter((LARGE_INTEGER*)(&end_t));
     dtime = (float)(end_t - start_t) / frequency;
#else
     gettimeofday(&end_t, NULL);
     dtime = (end_t.tv_usec - start_t.tv_usec) / 1000000. + (end_t.tv_sec - start_t.tv_sec);
#endif
     count += dtime;
    }
    while(!key[KEY_ESC])
    {
     if(dtime)
#ifdef ALLEGRO_WINDOWS
      QueryPerformanceCounter((LARGE_INTEGER*)(&start_t));
#else
      gettimeofday(&start_t, NULL);
#endif
     for(int a = 0;a < Config::num_snakes;a++)
      if(!snake[a].state)
       snake[a].Logic(dtime * 120);

     max_score = 0;

     for(int a = 0;a < Config::num_snakes;a++)
      if(!snake[a].state)
       if(snake[a].score > max_score) max_score = snake[a].score;

     if(max_score / (int)score_size > ((SCREEN_W * 5) >> 3))
      score_size += (max_score / score_size - ((SCREEN_W *5) >> 3) ) / 10000.;
     if(score_size > 1)
      if(max_score / (int)score_size < (SCREEN_W >> 1))
      {
       score_size -= ((SCREEN_W >> 1) - max_score / score_size) / 100000.;
       if(score_size < 1) score_size = 1;
      }

     for(int a = 0;a < Config::num_snakes;a++)
      if(!snake[a].state)
       snake[a].Draw(screenbmp, dtime * 120);

     if(target.r < 100.)
     {
      drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
      set_trans_blender(0, 0, 0, 255 - (int)(target.r * 2.55));
      circle(screenbmp, target.x, target.y, (int)target.r, makecol(255 - (int)(target.r * 2.55), 255, 255 - (int)(target.r * 2.55)));
      drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
      circlefill(screenbmp, target.x, target.y, (target.r > 25) ? 3 : (int)(target.r / 25 * 3), makecol(255,255,255));
      target.r += dtime * 100;
     }
     else circlefill(screenbmp, target.x, target.y, 3, makecol(255,255,255));

     rectfill(screenbmp, 0, SCREEN_H - Config::num_snakes * 15 - 5, SCREEN_W, SCREEN_H, makecol(128,128,128));

     for(int a = 0;a < Config::num_snakes;a++)
      if(!snake[a].state)
       snake[a].DrawScore(screenbmp, dtime * 120);

     if(Config::show_fps) alfont_textprintf_right_ex(screenbmp, myfont[FONT_NORMAL], SCREEN_W - 10, 10,
                                             makecol(255, 255, 255), -1,
                                             "FPS: %.2f", fps);

     switch(Config::bpp)
     {
      case 32: switch_antialias(32); break;
      case 16: switch_antialias(16); break;
      case 15: switch_antialias(15); break;
      default: blit(screenbmp, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
     }
     if(key[KEY_F12]) Screenshot();

     clear_bitmap(screenbmp);
     if(Config::do_vsync) vsync();

#ifdef ALLEGRO_WINDOWS
     QueryPerformanceCounter((LARGE_INTEGER*)(&end_t));
     dtime = (float)(end_t - start_t) / frequency;
#else
     gettimeofday(&end_t, NULL);
     dtime = (end_t.tv_usec - start_t.tv_usec) / 1000000. + (end_t.tv_sec - start_t.tv_sec);
#endif
    }
    break;
   }
   case MENU_EXIT:
        destroy_bitmap(screenbmp);
        remove_int(UpdateFPS);
        for(int a = 0;a < 8;a++)
         alfont_destroy_font(myfont[a]);
        alfont_exit();
        allegro_exit();
        exit(0);
        break;
  }
}
END_OF_MAIN()
