#include "allegro.h"

#include "GfxSoundConfig.h"
#include "GameSettings.h"
#include "MusicSound.h"

string GfxSoundConfig :: gfxDescription ("");
GameSettings * GfxSoundConfig :: gfxgs = NULL;
MusicSound * GfxSoundConfig :: gfxms = NULL;

int GfxSoundConfig :: gfxBgColorR = 255;
int GfxSoundConfig :: gfxBgColorB = 183;
int GfxSoundConfig :: gfxBgColorG = 171;

int GfxSoundConfig :: gfxFgColorR = 0;
int GfxSoundConfig :: gfxFgColorB = 0;
int GfxSoundConfig :: gfxFgColorG = 0;

int GfxSoundConfig :: gfxSoundIndex = 7;
char GfxSoundConfig :: gfxgvoldesc [80] = "";
char GfxSoundConfig :: gfxmvoldesc [80] = "";
char GfxSoundConfig :: gfxsvoldesc [80] = "";

DIALOG GfxSoundConfig :: gfxConfigDialog [] = 
  {
    /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */
    { d_clear_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
    { d_box_proc, 0, 0, 210, 150, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
    { d_box_proc, 210, 0, 265, 150, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },

    { d_text_proc, 5, 30, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
    { gfx_my_button_proc, 5, 50, 200, 60, 0, 0,  0, D_EXIT, 0, 0, (char *)"Change Graphics Mode", NULL, (void *)pickScreenMode },
    { gfx_my_button_proc, 5, 125, 200, 20, 0, 0,  0, D_EXIT, 0, 0, (char *)"Default Graphics", NULL, (void *)pickDefaultScreenMode },
    { gfx_my_button_proc, 160, 180, 200, 40, 0, 0, 0, D_EXIT, 0, 0, (char *)"Main Menu", NULL, (void *)gfxToMain },

    //gfx sound index
    { d_text_proc, 215, 30, 0, 0, 0, 0, 0, 0, 0, 0, gfxgvoldesc, NULL, NULL },
    { d_slider_proc, 215, 40, 255, 20, 0, 0, 0, 0, 255, 0, NULL, (void *)updateGVolSlider, NULL },

    { d_text_proc, 215, 70, 0, 0, 0, 0, 0, 0, 0, 0, gfxmvoldesc, NULL, NULL },
    { d_slider_proc, 215, 80, 255, 20, 0, 0, 0, 0, 255, 0, NULL, (void *)updateMVolSlider, NULL },

    { d_text_proc, 215, 110, 0, 0, 0, 0, 0, 0, 0, 0, gfxsvoldesc, NULL, NULL },
    { d_slider_proc, 215, 120, 255, 20, 0, 0, 0, 0, 255, 0, NULL, (void *)updateSVolSlider, NULL },
    
    { d_ctext_proc, 105, 5, 0, 0, 0, 0, 0, 0, 0, 0, (char *)"Graphics Settings", NULL, NULL },

    { d_ctext_proc, 340, 5, 0, 0, 0, 0, 0, 0, 0, 0, (char *)"Sound Settings", NULL, NULL },

    { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL},
    { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL  }
  };

int GfxSoundConfig :: gfx_my_button_proc (int msg, DIALOG *d, int c)
{
   int ret = d_button_proc (msg, d, c);
   if (ret == D_CLOSE && d->dp3)
      return ((int (*)(void))d->dp3)();
   return ret;
}

int GfxSoundConfig :: gfxToMain(void)
{
  //save settings
  gfxgs -> saveGraphicsSettings ();
  gfxgs -> saveVolume (gfxms);

  return D_CLOSE;  
}

int GfxSoundConfig :: pickScreenMode(void)
{
  int gfxCard2 = gfxgs -> getGfxDriver ();
  int gfxWidth2 = gfxgs -> getResX ();
  int gfxHeight2 = gfxgs -> getResY ();
  int gfxDepth2 = gfxgs -> getColorDepth ();
  int gfxSetResponse = 0;

  gfxSetResponse = gfx_mode_select_filter(&gfxCard2, &gfxWidth2, &gfxHeight2, &gfxDepth2, screenModeFilter);

  //if 0, user cancelled process
  if (gfxSetResponse != 0)
    {
      tryToSwitchMode (gfxDepth2, gfxCard2, gfxWidth2, gfxHeight2);
    }
  return D_O_K;
}

int GfxSoundConfig :: pickDefaultScreenMode(void)
{
  int gfxCard2 = GFX_AUTODETECT_FULLSCREEN;
  int gfxWidth2 = 640;
  int gfxHeight2 = 480;
  int gfxDepth2 = 32;

  tryToSwitchMode (gfxDepth2, gfxCard2, gfxWidth2, gfxHeight2);

  //OK, it worked. Copy the variables over.
  //gfxCard = gfxCard2;
  //gfxWidth = gfxWidth2;
  //gfxHeight = gfxHeight2;
  //gfxDepth = gfxDepth2;

  char tempSter [80];
  sprintf (tempSter, "%dx%d at %d-bit color", gfxWidth2, gfxHeight2, gfxDepth2);
  gfxDescription.assign (tempSter);
  gfxConfigDialog [3].dp = (void *) gfxDescription.c_str ();

  gfxgs -> setGfxSettings (gfxDepth2, gfxCard2, gfxWidth2, gfxHeight2);
  return D_O_K;
}

int GfxSoundConfig :: tryToSwitchMode (int gfxDepth2, int gfxCard2, int gfxWidth2, int gfxHeight2)
{
  int gfxSetResponse = 1;
  char tempSter [80];

  //try to set the mode and cancel if it fails
  set_color_depth (gfxDepth2);
  gfxSetResponse = set_gfx_mode(gfxCard2, gfxWidth2, gfxHeight2, 0, 0);
  if (gfxSetResponse != 0 || gfxDepth2 == 8)
    {
      //! error!
      set_color_depth (gfxgs -> getColorDepth ());
      set_gfx_mode(gfxgs -> getGfxDriver (), gfxgs -> getResX (), gfxgs -> getResY (), 0, 0);
      
      gfxRedrawMenu ();

      if (gfxDepth2 != 8)
	alert("These graphics settings don't work.", "Try a different set.", NULL, "&OK", NULL, 'o', 0);
      else
	alert("TASM does not support 8-bit color depth.", "Try a different color depth.", NULL, "&OK", NULL, 'o', 0);
      
      show_mouse (screen);
    }
  else
    {
      //OK, it worked. Copy the variables over.
      sprintf (tempSter, "%dx%d at %d-bit color", gfxWidth2, gfxHeight2, gfxDepth2);
      gfxDescription.assign (tempSter);
      gfxConfigDialog [3].dp = (void *) gfxDescription.c_str ();

      alert("New graphics mode set!", NULL, NULL, "&OK", NULL, 'o', 0);
      gfxgs -> setGfxSettings (gfxDepth2, gfxCard2, gfxWidth2, gfxHeight2);
      gfxRedrawMenu ();
      show_mouse (screen);
    }

  return D_O_K;
}

int GfxSoundConfig :: screenModeFilter (int c, int w, int h, int d)
{
  //this is used by gfx_mode_select_filter. It will return 0 (and will be included in the screen mode selection if:
  //it's not 8-bit color Depth. (no palettes!)
  //it's at least 640 pixels wide and 480 pixels tall
  if (d == 8 || w < 640 || h < 480)
    return 1;

  return 0;
}

void GfxSoundConfig :: gfxRedrawMenu ()
{
  set_dialog_color (gfxConfigDialog, 
		    makecol (gfxFgColorR, gfxFgColorB, gfxFgColorG),
		    makecol (gfxBgColorR, gfxBgColorB, gfxBgColorG));

  centre_dialog (gfxConfigDialog);
  dialog_message (gfxConfigDialog, MSG_DRAW, 0, NULL); 
}

int GfxSoundConfig :: updateGVolSlider (void *dp3, int d2)
{
  if (d2 < 10)
    sprintf (gfxgvoldesc, "Global:   %d", d2);
  else if (d2 < 100)
    sprintf (gfxgvoldesc, "Global:  %d", d2);
  else
    sprintf (gfxgvoldesc, "Global: %d", d2);

  dialog_message (&(gfxConfigDialog [gfxSoundIndex]), MSG_DRAW, 0, NULL);
  show_mouse (screen);

  gfxms -> setVolumeGlobal (d2);
  return D_O_K;
}

int GfxSoundConfig :: updateMVolSlider (void *dp3, int d2)
{
  if (d2 < 10)
    sprintf (gfxmvoldesc, "Music :   %d", d2);
  else if (d2 < 100)
    sprintf (gfxmvoldesc, "Music :  %d", d2);
  else
    sprintf (gfxmvoldesc, "Music : %d", d2);

  dialog_message (&(gfxConfigDialog [gfxSoundIndex + 2]), MSG_DRAW, 0, NULL);
  show_mouse (screen);

  gfxms -> setVolumeMusic (d2);
  return D_O_K;
}

int GfxSoundConfig :: updateSVolSlider (void *dp3, int d2)
{
  if (d2 < 10)
    sprintf (gfxsvoldesc, "Sound :   %d", d2);
  else if (d2 < 100)
    sprintf (gfxsvoldesc, "Sound :  %d", d2);
  else
    sprintf (gfxsvoldesc, "Sound : %d", d2);

  dialog_message (&(gfxConfigDialog [gfxSoundIndex + 4]), MSG_DRAW, 0, NULL);
  show_mouse (screen);

  gfxms -> setVolumeSfx (d2);
  return D_O_K;
}

GfxSoundConfig :: GfxSoundConfig (GameSettings * gs, MusicSound * ms)
{
  gfxgs = gs;
  gfxms = ms;

  char tempSter [80];
  sprintf (tempSter, "%dx%d at %d-bit color", gfxgs -> getResX (), gfxgs -> getResY (), gfxgs -> getColorDepth ());
  gfxDescription.assign (tempSter);
  gfxConfigDialog [3].dp = (void *) gfxDescription.c_str ();

  if (ms -> getVolumeGlobal () < 100)
    sprintf (gfxgvoldesc, "Global:  %d", ms -> getVolumeGlobal ());
  else
    sprintf (gfxgvoldesc, "Global: %d", ms -> getVolumeGlobal ());
  gfxConfigDialog [gfxSoundIndex + 1].d2 = ms -> getVolumeGlobal ();

  if (ms -> getVolumeMusic () < 100)
    sprintf (gfxmvoldesc, "Music :  %d", ms -> getVolumeMusic ());
  else
    sprintf (gfxmvoldesc, "Music : %d", ms -> getVolumeMusic ());
  gfxConfigDialog [gfxSoundIndex + 3].d2 = ms -> getVolumeMusic ();

  if (ms -> getVolumeSfx () < 100)
    sprintf (gfxsvoldesc, "Sound :  %d", ms -> getVolumeSfx ());
  else
    sprintf (gfxsvoldesc, "Sound : %d", ms -> getVolumeSfx ());
  gfxConfigDialog [gfxSoundIndex + 5].d2 = ms -> getVolumeSfx ();
}

void GfxSoundConfig :: go (int index)
{
  gfxRedrawMenu ();
  show_mouse (screen);
  do_dialog (gfxConfigDialog, index);
}

GfxSoundConfig :: ~GfxSoundConfig ()
{
}
