#include <allegro.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include "playgame.h"
#include "global.h"
#include "gfx.h"
#include "sound.h"
#include "gamegfx.h"
#include "dialog.h"
#include "game.h"

/* Setup data */
#define SETUP_EMBEDDED
#define SETUP_TITLE "Carcassonne SETUP"
#ifdef ALLEGRO_WINDOWS
   #define SETUP_CFG_FILE "carcass.ini"
#else
   #ifdef ALLEGRO_DOS
      #define SETUP_CFG_FILE "carcass.cfg"
   #else
      #if defined ALLEGRO_UNIX && !defined CROSSCOMPILE
         static char *configfile_and_path;

         #define SETUP_CFG_FILE configfile_and_path
      #else
         #define SETUP_CFG_FILE "allegro.cfg"
      #endif
   #endif
#endif

#define GAMESPEED 25

#ifdef ALLEGRO_WINDOWS
   #define TABS "\t\t"
   #define STAB "\t"
#else
   #define TABS "\t"
   #define STAB "\t"
#endif

/* Custom trace handler for Linux: I want the trace data dumped on the */
/*  console instead of in a log file */
int trace_handler(const char *msg)
{
   printf("%s", msg);
   fflush(stdout);

   return TRUE;
}

void close_button_handler(void)
{
   close_button_pressed = 1;
   return;
}
END_OF_FUNCTION(close_button_handler)

int main(int argc, char *argv[])
{
#ifdef ALLEGRO_WINDOWS
   int width, height;
   int set_width, set_height;
#endif
   char *cdir;
   int w;

   set_uformat(U_ASCII);
   allegro_init();

   set_window_close_hook(close_button_handler);

#if defined ALLEGRO_UNIX && !defined CROSSCOMPILE

   #ifdef DEBUGMODE
   /* Register new trace handler */
   register_trace_handler(trace_handler);
   #endif

   /* give up privileges */
   setuid(getuid());

   configfile_and_path = malloc(256);
   if (getenv("HOME")) {
      sprintf(configfile_and_path, "%s/%s", getenv("HOME"), ".carcassrc");
      if (!file_exists(configfile_and_path, FA_HIDDEN, NULL)) {
         sprintf(configfile_and_path, "/etc/carcassrc");
      }
   } else if (exists("/etc/carcassrc") && !exists(".carcassrc")) {
      sprintf(configfile_and_path, "/etc/carcassrc");
   } else {
      sprintf(configfile_and_path, ".carcassrc");
   }
#endif

   /* The game directory defaults to the current directory */
   cdir = malloc(1024);
   get_current_dir(cdir, 1024);
   set_game_directory(cdir);

   set_config_file(SETUP_CFG_FILE);
   settings.width = get_config_int("video", "width", settings.width);
   settings.height = get_config_int("video", "height", settings.height);
   settings.colour_depth =
      get_config_int("video", "depth", settings.colour_depth);

   set_digi_volume(get_config_int("sound", "digi_volume", get_digi_volume()));
   set_midi_volume(get_config_int("sound", "midi_volume", get_midi_volume()));


   if (get_config_int("video", "gouraud_shading", 0)) {
      settings.flags &= ~(LIT_PLAIN + LIT_GOURAUD);
      settings.flags |= LIT_GOURAUD;
   } else {
      settings.flags &= ~(LIT_PLAIN + LIT_GOURAUD);
      settings.flags |= LIT_PLAIN;
   }

   w = get_config_int("video", "windowed", -1);
   if (w==1)
      settings.flags |= WINDOWED_MODE;
   else if (w==0)
      settings.flags &= ~WINDOWED_MODE;

   set_game_directory(get_config_string("game", "game_dir", get_game_path("")));

   /* Now change to the game directory */
   chdir(get_game_path(""));

#if defined ALLEGRO_UNIX && !defined CROSSCOMPILE
   /* If the config file was read from /etc, save new settings in the user's */
   /*  home dir */
   if (strcmp(configfile_and_path, "/etc/carcassrc")==0) {
      if (getenv("HOME")) {
         sprintf(configfile_and_path, "%s/%s", getenv("HOME"), ".carcassrc");
      } else {
         sprintf(configfile_and_path, ".carcassrc");
      }
   }

   set_config_file(SETUP_CFG_FILE);
#endif

   if (argc > 1) {
      int c;

      for (c = 1; c < argc; c++)
         if (!strcmp(argv[c], "-15bpp")) {
            settings.colour_depth = 15;
         } else if (!strcmp(argv[c], "-16bpp")) {
            settings.colour_depth = 16;
         } else if (!strcmp(argv[c], "-24bpp")) {
            settings.colour_depth = 24;
         } else if (!strcmp(argv[c], "-32bpp")) {
            settings.colour_depth = 32;
         } else if (!strcmp(argv[c], "-dblbuffer")) {
            settings.flags &=
               ~(DOUBLE_BUFFER + PAGE_FLIP + IMMEDIATE + TRIPLE_BUFFER +
                 DIRTY_RECTANGLE);
            settings.flags |= DOUBLE_BUFFER;
         } else if (!strcmp(argv[c], "-tribuffer")) {
            settings.flags &=
               ~(DOUBLE_BUFFER + PAGE_FLIP + IMMEDIATE + TRIPLE_BUFFER +
                 DIRTY_RECTANGLE);
            settings.flags |= TRIPLE_BUFFER;
         } else if (!strcmp(argv[c], "-pageflip")) {
            settings.flags &=
               ~(DOUBLE_BUFFER + PAGE_FLIP + IMMEDIATE + TRIPLE_BUFFER +
                 DIRTY_RECTANGLE);
            settings.flags |= PAGE_FLIP;
         } else if (!strcmp(argv[c], "-immediate")) {
            settings.flags &=
               ~(DOUBLE_BUFFER + PAGE_FLIP + IMMEDIATE + TRIPLE_BUFFER +
                 DIRTY_RECTANGLE);
            settings.flags |= IMMEDIATE;
         } else if (!strcmp(argv[c], "-drect")) {
            settings.flags &=
               ~(DOUBLE_BUFFER + PAGE_FLIP + IMMEDIATE + TRIPLE_BUFFER +
                 DIRTY_RECTANGLE);
            settings.flags |= DIRTY_RECTANGLE;
         } else if (!strcmp(argv[c], "-hires")) {
            settings.width = 800;
            settings.height = 600;
         } else if (!strcmp(argv[c], "-ultrares")) {
            settings.width = 1024;
            settings.height = 768;
         } else if (!strcmp(argv[c], "-midi")) {
            settings.flags &= ~(MUSIC_MIDI + MUSIC_CD);
            settings.flags |= MUSIC_MIDI;
         } else if (!strcmp(argv[c], "-cd")) {
            settings.flags &= ~(MUSIC_MIDI + MUSIC_CD);
            settings.flags |= MUSIC_CD;
         } else if (!strcmp(argv[c], "-nomusic")) {
            settings.flags &= ~(MUSIC_MIDI + MUSIC_CD);
         } else if (!strcmp(argv[c], "-nosound")) {
            settings.flags &= ~(MUSIC_MIDI + MUSIC_CD + SFX_DIGI);
#ifndef ALLEGRO_DOS
         } else if (!strcmp(argv[c], "-window")) {
            settings.flags |= WINDOWED_MODE;
         } else if (!strcmp(argv[c], "-fullscrn")) {
            settings.flags &= ~WINDOWED_MODE;
         } else if (!strcmp(argv[c], "-w")) {
            c++;
            sscanf(argv[c], "%d", &(settings.width));
            /* make sensible window dimensions */
            if (settings.width < 320)
               settings.width = 320;
         } else if (!strcmp(argv[c], "-h")) {
            c++;
            sscanf(argv[c], "%d", &(settings.height));
            /* make sensible window dimensions */
            if (settings.height < 200)
               settings.height = 200;
#endif
//         } else if (!strcmp(argv[c], "-setup")) {
//            set_gfx_mode(GFX_SAFE, 640, 480, 0, 0);
//            return setup_main();
         } else {
/* *INDENT-OFF* */
            allegro_message("Valid command-line options are:\n"
                            " -xbpp     " TABS " where x=15,16,24 or 32. selects the desired colourdepth.\n"
                            " -dblbuffer" TABS " Selects doublebuffering for screen updates\n"
                            " -tribuffer" TABS " Selects triple buffering for screen updates\n"
                            " -pageflip " TABS " Selects pageflipping for screen updates\n"
                            " -immediate" STAB " Select immediate screen updates\n"
                            " -drect    " TABS " Select dirty-rectangle screen updates (default)\n"
                            " -hires    " TABS " Select high resolution (800x600, default)\n"
                            " -ultrares " TABS " Select very high resolution (1024x768)\n"
#ifndef ALLEGRO_DOS
                            " -window "   TABS " Run in windowed mode\n"
                            " -fullscrn " TABS " Run in full-screen mode\n"
                            " -w width "  TABS " Set width of window\n"
                            " -h height " TABS " Set height of window\n"
#endif
                            " -midi     " TABS " Select MIDI music\n"
                            " -cd       " TABS " Select CD music\n"
                            " -nomusic"   TABS " Disables music\n"
                            " -nosound"   TABS " Disables all sound effects and music\n"
                            " -setup    " TABS " Change default settings\n");
/* *INDENT-ON* */
            exit(0);
         }
   }

   LOCK_FUNCTION(close_button_handler);

#ifdef ALLEGRO_WINDOWS
   /* Windows doesn't like windows larger than the screen... */
   set_height = settings.height;
   set_width = settings.width;
   if (get_desktop_resolution(&width, &height) == 0) {
      if (height<=settings.height)
         settings.height = height - 96;
      if (width<=settings.width)
         settings.width = width - 96;
   }
#endif

   set_sound();
   if (set_graphics()==-1) {
#ifdef ALLEGRO_WINDOWS
      settings.height = set_height;
      settings.width = set_width;
#endif
      if (settings.flags & WINDOWED_MODE) {
         settings.flags &= ~WINDOWED_MODE;
      }
      if (set_graphics()==-1) {
         allegro_message("Cannot set graphics mode!\n");
         exit(EXIT_FAILURE);
      }
   }

   set_window_title("Carcassonne");
   set_window_close_button(TRUE);

   if (set_display_switch_mode(SWITCH_BACKGROUND)!=0)
      set_display_switch_mode(SWITCH_BACKAMNESIA);

   install_timer();
   install_keyboard();
   if (install_mouse() < 0) {
      set_gfx_mode(GFX_TEXT, 0,0, 0,0);
      allegro_message("This game requires a mouse, but I couldn't find one.\n"
                      "Perhaps you should query your cat?\n");
      return 0;
   }

   //load_midi_patches();
   /* Initizlize music lookup tables */
   read_music_aliases(get_game_path("carcass.gme"));
   read_sample_aliases(get_game_path("carcass.gme"));
   
   /* Load and initialize graphics */
   load_global_gfx();
   
   /* Initialize dialog boxes */
   dialog_init();

   /* Prepare the screen, set up page flipping, double buffering etc. */
   prepare_screen();
   playgame_init(GAMESPEED);
   install_fps_counter();

   start_game();

   stop_sound();
   remove_sound();
   set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
   allegro_exit();

   /* Now return to the original directory */
   chdir(cdir);

   return 0;
}
END_OF_MAIN()
