/*   Copyright 2005,2006 Paweł Niegowski
*
*    This file is part of Fenrir.
*
*    Fenrir is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    Fenrir is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with Fenrir; if not, write to the Free Software
*    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "main.h"
#include "login.h"
#include "play.h"
#include "edit.h"
#include "network.h"
#include "palette.h"
#include "player.h"
#include "sky.h"
#include "lookup.h"
#include "map.h"
#include "item.h"
#include "script.h"
#include "skill.h"
#include <stdio.h>
#ifndef WIN32
#include <signal.h>
#endif

volatile int timer = 0, fps = 0, frame = 0;
volatile bool shutdown_flag = false;
bool vsynced = false;
void inc_timer() { timer++; } END_OF_FUNCTION(inc_timer);
void count_fps() { fps = frame; frame = 0; } END_OF_FUNCTION(count_fps);
void close_game() { shutdown_flag = true; } END_OF_FUNCTION(close_game);

int conf_fullscreen,conf_lowres,conf_sky,conf_antialiasing, conf_vsync, conf_triplebuffer, conf_sleep;

GAME_STATE game_state = GAME_LOGIN;
BITMAP *buf = 0;
BITMAP *scaled_buf = 0;
//for triple buffering
BITMAP *page[2];

DATAFILE *maindata = 0;
int font_width = 0, font_height = 0;

int current_page = 0;


void main_update_screen()
{
 vsynced = false;
 BITMAP *target = conf_triplebuffer?page[!current_page]:screen;
 if(conf_sky && !(map_flags & MAPFLAGC_INDOOR) && game_state != GAME_LOGIN)
 {
  drawing_mode(DRAW_MODE_TRANS,0,0,0);
  color_map = trans_map+6;
  hline(buf,0,0,buf->w,horizon_color);
  color_map = trans_map+4;
  hline(buf,0,1,buf->w,horizon_color);
  color_map = trans_map+2;
  hline(buf,0,2,buf->w,horizon_color);
  solid_mode();
 }
 if(conf_vsync && !vsynced)
  vsync();
 if(conf_lowres)
  blit(buf,target,0,0,0,conf_sky*40,SCREEN_W,SCREEN_H);
 else
 {
  //our amazing custom scaling blit
  acquire_bitmap(target);
  unsigned long addr = 0;
  unsigned long addr_2 = 0;

  unsigned int pixel_buf = 0;
  unsigned char *ptr = buf->line[0];
  for(int i = 0; i < buf->h; i++)
  {
   addr = bmp_write_line(target,i*2+conf_sky*80);
   addr_2 = bmp_write_line(target,i*2+1+conf_sky*80);
   for(int j = 0; j < buf->w/2; j++)
   {
    pixel_buf = (*(ptr)) | ((*(ptr))<<8) | ((*(++ptr))<<16) | ((*(ptr++))<<24);
    bmp_write32(addr+(j<<2),pixel_buf);
    bmp_write32(addr_2+(j<<2),pixel_buf);
   }
  }
  bmp_unwrite_line(target);
  release_bitmap(target);
  //and yet another version of it
/*  for(int i = 0; i < buf->h*2; i++)
   for(int j = 0; j < buf->w*2; j++)
    scaled_buf->line[i][j] = buf->line[i>>1][j>>1];
  blit(scaled_buf,target,0,0,0,conf_sky*40,SCREEN_W,SCREEN_H);*/
 }
 if(conf_triplebuffer)
 {
  current_page = !current_page;
  show_video_bitmap(page[current_page]);
 }
}


void close_signal_handler(int sig)
{
 shutdown_flag = true;
}



void run_logic(GAME_STATE state)
{
 switch(game_state)
 {
  case GAME_LOGIN: login_run_logic(); break;
  case GAME_PLAY:  play_run_logic(); break;
  case GAME_EDIT:  edit_run_logic(); break;
 }
}

void draw_all(GAME_STATE state)
{
 switch(game_state)
 {
  case GAME_LOGIN: login_draw_all(); break;
  case GAME_PLAY:  play_draw_all(); break;
  case GAME_EDIT:  edit_draw_all(); break;
 }
 if(key[KEY_F2])
  textprintf_ex(buf,font,0,0,255,-1,"FPS:%d",fps);
}

void init()
{
 #ifndef WIN32
 signal(SIGPIPE,SIG_IGN);
 signal(SIGTERM,close_signal_handler);
 signal(SIGABRT,close_signal_handler);
 signal(SIGHUP,close_signal_handler);
 signal(SIGQUIT,close_signal_handler);
 #endif
 srand(time(0));
 allegro_init();
 install_timer();
 install_keyboard();
// set_color_depth(8);

 conf_fullscreen = get_config_int("gfx","fullscreen",0);
 conf_lowres = get_config_int("gfx","lowres",1);
 conf_sky = get_config_int("gfx","sky",1);
 conf_antialiasing = get_config_int("gfx","antialiasing",0);
 conf_vsync = get_config_int("gfx","vsync",0);
 conf_triplebuffer = get_config_int("gfx","triplebuffer",0);
 conf_sleep = get_config_int("misc","sleep",0);
 int scr_w, scr_h;
 scr_w = 320;
 scr_h = conf_sky?240:200;
 if(!conf_lowres) { scr_w *= 2; scr_h *= 2; }
 if(set_gfx_mode(conf_fullscreen?GFX_AUTODETECT_FULLSCREEN:GFX_AUTODETECT_WINDOWED,scr_w,scr_h,0,0))
  allegro_message("ERROR: Couldn't initialize graphics mode.");
 clear_to_color(screen,0);
 if(conf_triplebuffer)
 {
  page[0] = create_video_bitmap(SCREEN_W,SCREEN_H);
  page[1] = create_video_bitmap(SCREEN_W,SCREEN_H);
  clear_to_color(page[0],0);
  clear_to_color(page[1],0);
  show_video_bitmap(page[0]);
 }
 set_window_title("Fenrir Client");
 game_state = GAME_LOGIN;
 shutdown_flag = false;
 buf = create_bitmap(320,200);
 if(!conf_lowres)
 scaled_buf = create_bitmap(640,400);
 clear_to_color(buf,0);
 maindata = load_datafile("gfx/main.dat");
 default_font = font;
 font = (FONT*)maindata[DATA_FONT].dat;
 font_width = text_length(font,"0");
 font_height = text_height(font);

 player_init();
 sky_init();
 item_init();
 script_init();

 install_int_ex(inc_timer,BPS_TO_TIMER(60));
 install_int_ex(count_fps,SECS_TO_TIMER(1));

 set_close_button_callback(close_game);
 set_display_switch_mode(SWITCH_BACKGROUND);
}

void cleanup()
{
 font = default_font;
 unload_datafile(maindata);
 switch(game_state)
 {
  case GAME_LOGIN: login_cleanup(); break;
  case GAME_PLAY:  play_cleanup(); break;
  case GAME_EDIT:  edit_cleanup(); break;
 }
 destroy_bitmap(buf);
 if(scaled_buf)
  destroy_bitmap(scaled_buf);
 if(conf_triplebuffer)
 {
  destroy_bitmap(page[0]);
  destroy_bitmap(page[1]);
 }
}

int main(int argc, char **argv)
{
 init();
 network_init();
 login_init();
 int print_screen = 0;
 while(!shutdown_flag)
 {
  while(timer > 0)
  {
   run_logic(game_state);
   sky_update();
   if(game_state == GAME_LOGIN || game_state == GAME_PLAY)
    network_update();
   if(print_screen) print_screen--;
   timer--;
  }
  draw_all(game_state);
  main_update_screen();
  if(conf_sky)
   sky_mode7_draw();
  if(key[KEY_PRTSCR] && !print_screen)
  {
    char path[40];
    int i = 0;
    do
     sprintf(path,"screen%d.bmp",i++);
    while(exists(path));
    PALETTE p;
    get_palette(p);
    save_bitmap(path,buf,p);
    print_screen = 60;
  }
  frame++;
  if(conf_sleep)
   nlThreadYield();
 }
 network_cleanup();
 sky_cleanup();
 script_cleanup();
 item_cleanup();
 cleanup();
 return 0;
}
END_OF_MAIN();
