/*
  Hatari - dlgJoystick.c

  This file is distributed under the GNU General Public License, version 2
  or at your option any later version. Read the file gpl.txt for details.
*/
const char DlgJoystick_fileid[] = "Hatari dlgJoystick.c : " __DATE__ " " __TIME__;

#include "main.h"
#include "configuration.h"
#include "dialog.h"
#include "sdlgui.h"


#define DLGJOY_DISABLED    3
#define DLGJOY_USEREALJOY  4
#define DLGJOY_USEKEYS     5
#define DLGJOY_DEFINEKEYS  6
#define DLGJOY_SDLJOYNAME  8
#define DLGJOY_PREVSDLJOY  9
#define DLGJOY_NEXTSDLJOY 10
#define DLGJOY_AUTOFIRE   11
#define DLGJOY_STJOYNAME  13
#define DLGJOY_PREVSTJOY  14  
#define DLGJOY_NEXTSTJOY  15
#define DLGJOY_EXIT       16


/* The joysticks dialog: */

static char sSdlStickName[20];

static SGOBJ joydlg[] =
{
	{ SGBOX, 0, 0, 0,0, 32,18, NULL },
	{ SGTEXT, 0, 0, 8,1, 15,1, "Joysticks setup" },

	{ SGBOX, 0, 0, 1,4, 30,11, NULL },
	{ SGRADIOBUT, 0, 0, 2,5, 10,1, "disabled" },
	{ SGRADIOBUT, 0, 0, 2,9, 20,1, "use real joystick:" },
	{ SGRADIOBUT, 0, 0, 2,7, 14,1, "use keyboard" },

	{ SGBUTTON, 0, 0, 19,7, 11,1, "Define keys" },
	{ SGBOX, 0, 0, 5,11, 22,1, NULL },
	{ SGTEXT, 0, 0, 6,11, 20,1, sSdlStickName },
	{ SGBUTTON, 0, 0, 4,11, 1,1, "\x04" },         /* Arrow left */
	{ SGBUTTON, 0, 0, 27,11, 1,1, "\x03" },        /* Arrow right */

	{ SGCHECKBOX, 0, 0, 2,13, 17,1, "Enable autofire" },

	{ SGBOX, 0, 0, 4,3, 24,1, NULL },
	{ SGTEXT, 0, 0, 5,3, 22,1, NULL },
	{ SGBUTTON, 0, 0, 1,3, 3,1, "\x04" },         /* Arrow left */
	{ SGBUTTON, 0, 0, 28,3, 3,1, "\x03" },        /* Arrow right */

	{ SGBUTTON, SG_DEFAULT, 0, 6,16, 20,1, "Back to main menu" },
	{ -1, 0, 0, 0,0, 0,0, NULL }
};


/* The joystick keys setup dialog: */

static char sKeyInstruction[24];
static char sKeyName[24];

static SGOBJ joykeysdlg[] =
{
	{ SGBOX, 0, 0, 0,0, 28,5, NULL },
	{ SGTEXT, 0, 0, 2,1, 24,1, sKeyInstruction },
	{ SGTEXT, 0, 0, 2,3, 24,1, sKeyName },
	{ -1, 0, 0, 0,0, 0,0, NULL }
};


static char *sJoystickNames[JOYSTICK_COUNT] =
{
	"ST Joystick 0",
	"ST Joystick 1",
	"STE Joypad A",
	"STE Joypad B",
	"Parallel port stick 1",
	"Parallel port stick 2"
};


/*-----------------------------------------------------------------------*/
/**
 * Show dialogs for defining joystick keys and wait for a key press.
 */
static void DlgJoystick_DefineOneKey(char *pType, int *pKey)
{
	SDL_Event sdlEvent;

	if (bQuitProgram)
		return;

	snprintf(sKeyInstruction, sizeof(sKeyInstruction), "Press key for '%s'...", pType);
	snprintf(sKeyName, sizeof(sKeyName), "(was: '%s')", SDL_GetKeyName(*pKey));

	SDLGui_DrawDialog(joykeysdlg);

	do
	{
		SDL_WaitEvent(&sdlEvent);
		if (sdlEvent.type == SDL_KEYDOWN)
		{
			*pKey = sdlEvent.key.keysym.sym;
			snprintf(sKeyName, sizeof(sKeyName), "(now: '%s')", SDL_GetKeyName(*pKey));
			SDLGui_DrawDialog(joykeysdlg);
		}
		else if (sdlEvent.type == SDL_QUIT)
		{
			bQuitProgram = true;
			return;
		}
	} while (sdlEvent.type != SDL_KEYUP);
	SDL_Delay(200);
}


/*-----------------------------------------------------------------------*/
/**
 * Let the user define joystick keys.
 */
static void DlgJoystick_DefineKeys(int nActJoy)
{

	SDLGui_CenterDlg(joykeysdlg);
	DlgJoystick_DefineOneKey("up", &ConfigureParams.Joysticks.Joy[nActJoy].nKeyCodeUp);
	DlgJoystick_DefineOneKey("down", &ConfigureParams.Joysticks.Joy[nActJoy].nKeyCodeDown);
	DlgJoystick_DefineOneKey("left", &ConfigureParams.Joysticks.Joy[nActJoy].nKeyCodeLeft);
	DlgJoystick_DefineOneKey("right", &ConfigureParams.Joysticks.Joy[nActJoy].nKeyCodeRight);
	DlgJoystick_DefineOneKey("fire", &ConfigureParams.Joysticks.Joy[nActJoy].nKeyCodeFire);
}


/*-----------------------------------------------------------------------*/
/**
 * Adapt dialog using the values from the configration structure.
 */
static void DlgJoystick_ReadValuesFromConf(int nActJoy, int nMaxId)
{
	int i;

	/* Check if joystick ID is available */
	if (SDL_NumJoysticks() == 0)
	{
		strcpy(sSdlStickName, "0: (none available)");
	}
	else if (ConfigureParams.Joysticks.Joy[nActJoy].nJoyId <= nMaxId)
	{
		snprintf(sSdlStickName, 20, "%i: %s", ConfigureParams.Joysticks.Joy[nActJoy].nJoyId,
		         SDL_JoystickName(ConfigureParams.Joysticks.Joy[nActJoy].nJoyId));
	}
	else
	{
		snprintf(sSdlStickName, 20, "0: %s", SDL_JoystickName(0));
		/* Unavailable joystick ID -> disable it if necessary*/
		if (ConfigureParams.Joysticks.Joy[nActJoy].nJoystickMode == JOYSTICK_REALSTICK)
			ConfigureParams.Joysticks.Joy[nActJoy].nJoystickMode = JOYSTICK_DISABLED;
	}

	for (i = DLGJOY_DISABLED; i <= DLGJOY_USEKEYS; i++)
		joydlg[i].state &= ~SG_SELECTED;
	joydlg[DLGJOY_DISABLED + ConfigureParams.Joysticks.Joy[nActJoy].nJoystickMode].state |= SG_SELECTED;

	if (ConfigureParams.Joysticks.Joy[nActJoy].bEnableAutoFire)
		joydlg[DLGJOY_AUTOFIRE].state |= SG_SELECTED;
	else
		joydlg[DLGJOY_AUTOFIRE].state &= ~SG_SELECTED;
}


/*-----------------------------------------------------------------------*/
/**
 * Read values from dialog and write them to the configuration structure.
 */
static void DlgJoystick_WriteValuesToConf(int nActJoy)
{
	JOYSTICKMODE jmi;
	for (jmi = JOYSTICK_DISABLED; jmi <= JOYSTICK_KEYBOARD; jmi++)
	{
		if (joydlg[jmi + DLGJOY_DISABLED].state & SG_SELECTED)
		{
			ConfigureParams.Joysticks.Joy[nActJoy].nJoystickMode = jmi;
			break;
		}
	}

	ConfigureParams.Joysticks.Joy[nActJoy].bEnableAutoFire = (joydlg[DLGJOY_AUTOFIRE].state & SG_SELECTED);
	ConfigureParams.Joysticks.Joy[nActJoy].nJoyId = joydlg[DLGJOY_SDLJOYNAME].txt[0] - '0';
}


/*-----------------------------------------------------------------------*/
/**
 * Show and process the joystick dialog.
 */
void Dialog_JoyDlg(void)
{
	int but;
	static int nActJoy = 1;
	int nMaxJoyId;

	SDLGui_CenterDlg(joydlg);

	joydlg[DLGJOY_STJOYNAME].txt = sJoystickNames[nActJoy];

	nMaxJoyId = SDL_NumJoysticks() - 1;
	if (nMaxJoyId > 5)
		nMaxJoyId = 5;

	/* Set up dialog from actual values: */
	DlgJoystick_ReadValuesFromConf(nActJoy, nMaxJoyId);

	do
	{
    	but = SDLGui_DoDialog(joydlg, NULL);
		switch (but)
		{
		 case DLGJOY_PREVSDLJOY:        // Select the previous SDL joystick
			if (ConfigureParams.Joysticks.Joy[nActJoy].nJoyId > 0)
			{
				ConfigureParams.Joysticks.Joy[nActJoy].nJoyId -= 1;
				snprintf(sSdlStickName, 20, "%i: %s", ConfigureParams.Joysticks.Joy[nActJoy].nJoyId,
				         SDL_JoystickName(ConfigureParams.Joysticks.Joy[nActJoy].nJoyId));
			}
			break;
		 case DLGJOY_NEXTSDLJOY:        // Select the next SDL joystick
			if (ConfigureParams.Joysticks.Joy[nActJoy].nJoyId < nMaxJoyId)
			{
				ConfigureParams.Joysticks.Joy[nActJoy].nJoyId += 1;
				snprintf(sSdlStickName, 20, "%i: %s", ConfigureParams.Joysticks.Joy[nActJoy].nJoyId,
				         SDL_JoystickName(ConfigureParams.Joysticks.Joy[nActJoy].nJoyId));
			}
			break;
		 case DLGJOY_DEFINEKEYS:        // Define new keys for keyboard emulation
			DlgJoystick_DefineKeys(nActJoy);
			break;
		 case DLGJOY_PREVSTJOY:         // Switch to the previous ST joystick setup tab
			if (nActJoy > 0)
			{
				DlgJoystick_WriteValuesToConf(nActJoy);
				nActJoy -= 1;
				DlgJoystick_ReadValuesFromConf(nActJoy, nMaxJoyId);
				joydlg[DLGJOY_STJOYNAME].txt = sJoystickNames[nActJoy];
			}
			break;
		 case DLGJOY_NEXTSTJOY:         // Switch to the next ST joystick setup tab
			if (nActJoy < 5)
			{
				DlgJoystick_WriteValuesToConf(nActJoy);
				nActJoy += 1;
				DlgJoystick_ReadValuesFromConf(nActJoy, nMaxJoyId);
				joydlg[DLGJOY_STJOYNAME].txt = sJoystickNames[nActJoy];
			}
			break;
		}
	}
	while (but != DLGJOY_EXIT && but != SDLGUI_QUIT
	       && but != SDLGUI_ERROR && !bQuitProgram);

	DlgJoystick_WriteValuesToConf(nActJoy);
}
