#include "KGF.h"

#include <time.h>

ALLEGRO_EVENT_QUEUE *Queue;
ALLEGRO_TIMER *Timer;

ALLEGRO_VOICE *Voice;
ALLEGRO_MIXER *Mixer;

ALLEGRO_MIXER *MusicMixer;

ALLEGRO_DISPLAY *Display=NULL;

bool ProgramStarted=false;

GProgram *Game;

int DebugMode=0;
bool DebugModeVisual=0;
float AspectRatio;


void StartTimer() {al_start_timer(Timer);}
void StopTimer()  {al_stop_timer(Timer);}



void GProgram::ChangeScene(std::string name) {
  std::deque<GScene *>::iterator it;
  next_scene = NULL;
  for (it=scenes.begin(); it!=scenes.end(); it++) {
    if ((*it)->GetName() == name) {
      next_scene = (*it);
      actual_scene_name = name;
      break;
    }
  }
}



void GProgram::Start() {
  srand(time(0));

  GlobalLog = new LogFileClass("gamelog.txt");

  GlobalLog->LogMessage("Log started");

  al_init();
  ALLEGRO_CONFIG *config;
  GlobalLog->LogMessage("Reading from config");
  config = al_load_config_file("Settings.ini");

  DebugMode = GetConfigInt(config, "Player", "DebugMode", 0);

  int RES_W, RES_H;
  RES_W = GetConfigInt(config, "Display", "Width", 1024);
  RES_H = GetConfigInt(config, "Display", "Height", 768);

  MotionBlurStart = GetConfigFloat(config, "Display", "MotionBlur", 3);


  AspectRatio = GetConfigFloat(config, "Display", "AspectRatio", -1);
  int WindowMode;
  WindowMode = GetConfigInt(config, "Display", "Windowed", 1);

  /* Start all allegro crap */
  al_install_mouse();
  al_install_keyboard();
  al_install_audio(ALLEGRO_AUDIO_DRIVER_AUTODETECT);
  al_init_image_addon();
  al_init_font_addon();
  al_init_ttf_addon();
  al_init_ogg_vorbis_addon();
  al_reserve_samples(GetConfigInt(config, "Audio", "SamplesReserved", 16));
  ALLEGRO_BITMAP *shadow_buffer;

  GlobalLog->LogMessage("Allegro installed succesfully");

  InitMapping();

  std::string driver;
  driver = GetConfigString(config, "Display", "Driver", "D3D");
  if (driver == "D3D") al_set_new_display_flags(ALLEGRO_DIRECT3D);
  else if (driver == "OGL") al_set_new_display_flags(ALLEGRO_OPENGL);


  Voice = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16,ALLEGRO_CHANNEL_CONF_2);
  Mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
  MusicMixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
  al_attach_mixer_to_voice(Mixer, Voice);
  al_attach_mixer_to_voice(MusicMixer, Voice);

  if (WindowMode) al_set_new_display_flags(ALLEGRO_WINDOWED);
  else al_set_new_display_flags(ALLEGRO_FULLSCREEN);

  if (GetConfigInt(config, "Display", "VSync", 1)) al_set_new_display_option(ALLEGRO_VSYNC, 1, ALLEGRO_REQUIRE);
  else al_set_new_display_option(ALLEGRO_VSYNC, 2, ALLEGRO_REQUIRE);


  Display = al_create_display(RES_W, RES_H);
  if (!Display) {
    RES_W = 640; RES_H = 480; al_set_new_display_flags(ALLEGRO_WINDOWED);
    Display = al_create_display(RES_W, RES_H);
    Warning("Requested Display couldn't be created, defaulting to 640x480 in Windowed Mode.");
  }

  al_hide_mouse_cursor();
  al_set_window_title(GetConfigStr(config, "Game", "WindowTitle", "Application"));

  if (AspectRatio == -1) AspectRatio = (float)RES_W / (float)RES_H;

  int f;
  f = GetConfigInt(config, "Game", "FPS", 60);
  Timer = al_install_timer(ALLEGRO_BPS_TO_SECS(f));
  Queue = al_create_event_queue();
  al_register_event_source(Queue, (ALLEGRO_EVENT_SOURCE *)Timer);
  al_register_event_source(Queue, (ALLEGRO_EVENT_SOURCE *)al_get_keyboard_event_source());

  GlobalLog->LogMessage("Timer started");

  al_set_new_bitmap_flags(ALLEGRO_NO_PRESERVE_TEXTURE);

  ProgramStarted=true;

  // Load Pre-loaded bitmaps

  std::deque<GResource *>::iterator it;
  for (it=ToLoad.begin(); it!=ToLoad.end(); it+=1) {
    printf("!");
    (*it)->Load();
  }
  ToLoad.clear();

  DebugModeVisual=0;



  CreateScenes();
  Main();
}


void GProgram::Draw() {
  al_clear_to_color(al_map_rgb_f(0, 0, 0));
  if (actual_scene != NULL) actual_scene->Draw();
  al_flip_display();
}

void GProgram::Update() {
  UpdateDelta();
  PollInput();
  UpdateGlobalZoomFactor();


  if (actual_scene != NULL) actual_scene->Update();

  if (KB_Input[ALLEGRO_KEY_F8]) BoolSwitch(DebugModeVisual);

  if (KB_Input[ALLEGRO_KEY_ESCAPE]) {
    ClearScene();
  }

  FramesUpdated += 1;
}


void GProgram::Main() {
  StartTimer();
  ResetDelta();
  while (actual_scene != NULL) {
    if (actual_scene != last_scene) {
      if (last_scene != NULL) last_scene->Close();
      if (actual_scene != NULL) actual_scene->Start();
    }
    ALLEGRO_EVENT event;
    al_wait_for_event(Queue, &event);
    if (event.type == ALLEGRO_EVENT_TIMER) {
      if (actual_scene != NULL) {
        Draw();
        Update();
      }
    }
    if (next_scene != actual_scene) actual_scene = next_scene;
    last_scene = actual_scene;
  }
  Close();
}

void GProgram::Close() {
  al_stop_samples();
  ClearMusic();
  ClearGResources();
  ClearVisualObjects();
}
