//	SDL2.0KeyManager.cpp - SDL2.0-specific KeyManager.
//  ----------------------------------------------------------------------------
//	This file is part of 'NiallsAVLib', base code for any kind of audiovisual
//	apps.
//	Copyright (C) 2012  Niall Moody
//	
//	This program 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 3 of the License, or
//	(at your option) any later version.
//
//	This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
//	----------------------------------------------------------------------------

#include "SDL2.0KeyManager.h"

#include <sstream>

using std::wstringstream;
using std::wstring;
using std::vector;

//------------------------------------------------------------------------------
SDL2_0KeyManager::SDL2_0KeyManager()
{

}

//------------------------------------------------------------------------------
SDL2_0KeyManager::~SDL2_0KeyManager()
{

}

//------------------------------------------------------------------------------
void SDL2_0KeyManager::getActions(SDL_Keysym& keysym,
								  vector<std::wstring>& actions) const
{
	wstring keyString;

	//First prefix the string with any modifiers.
	if(keysym.mod&KMOD_CTRL)
		keyString = L"Ctrl-";
	if(keysym.mod&KMOD_SHIFT)
		keyString = L"Shift-";
	if(keysym.mod&KMOD_ALT)
		keyString = L"Alt-";
	if(keysym.mod&KMOD_GUI)
		keyString = L"Meta-";

	//Now write the actual key identifier.
	keyString.append(getKeyString(keysym.sym));

	KeyManager::getActions(keyString, actions);
}

//------------------------------------------------------------------------------
void SDL2_0KeyManager::getActions(SDL_JoyAxisEvent& event,
								  vector<std::wstring>& actions) const
{
	wstringstream keyString;

	keyString << L"Joy" << event.which;

	//x-axis.
	if(event.axis == 0)
	{
		if(event.value < 128) //128 so there's a bit of a dead zone.
			keyString << L"Left";
		else if(event.value > 128)
			keyString << L"Right";
		else
			keyString << L"Centre";
	}
	//y-axis.
	else if(event.axis == 1)
	{
		if(event.value < 128)
			keyString << L"Up";
		else if(event.value > 128)
			keyString << L"Down";
		else
			keyString << L"Centre";
	}
	//Triggers.
	//TODO: Update this for SDL 2.0's handling of XInput.
	else if(event.axis == 2)
	{
		if(event.value < 128)
			keyString << L"TriggerLeft";
		else if(event.value > 128)
			keyString << L"TriggerRight";
		else
			keyString << L"TriggerCentre";
	}
	//x-axis 2.
	else if(event.axis == 3)
	{
		if(event.value < 128)
			keyString << L"Left2";
		else if(event.value > 128)
			keyString << L"Right2";
		else
			keyString << L"Centre2";
	}
	//y-axis 2.
	else if(event.axis == 4)
	{
		if(event.value < 128)
			keyString << L"Up2";
		else if(event.value > 128)
			keyString << L"Down2";
		else
			keyString << L"Centre2";
	}

	KeyManager::getActions(keyString.str(), actions);
}

//------------------------------------------------------------------------------
void SDL2_0KeyManager::getActions(SDL_JoyButtonEvent& event,
								  vector<std::wstring>& actions) const
{
	wstringstream keyString;

	keyString << L"Joy" << event.which << L"Button" << event.button;

	KeyManager::getActions(keyString.str(), actions);
}

//------------------------------------------------------------------------------
void SDL2_0KeyManager::getActions(SDL_JoyHatEvent& event,
								  vector<std::wstring>& actions) const
{
	wstringstream keyString;

	keyString << L"Joy" << event.which << L"Hat" << event.hat;

	if(event.value&SDL_HAT_CENTERED)
		keyString << L"Centre";
	else
	{
		if(event.value&SDL_HAT_UP)
			keyString << L"Up";
		else if(event.value&SDL_HAT_DOWN)
			keyString << L"Down";
		if(event.value&SDL_HAT_LEFT)
			keyString << L"Left";
		else if(event.value&SDL_HAT_RIGHT)
			keyString << L"Right";
	}

	KeyManager::getActions(keyString.str(), actions);
}

//------------------------------------------------------------------------------
int SDL2_0KeyManager::getModVal(SDL_Keymod mod) const
{
	int retval = 0;

	if(mod&KMOD_CTRL)
		retval = 1;
	if(mod&KMOD_SHIFT)
		retval = 2;
	if(mod&KMOD_ALT)
		retval = 3;
	if(mod&KMOD_GUI)
		retval = 4;

	return retval;
}

//------------------------------------------------------------------------------
wstring SDL2_0KeyManager::getKeyString(SDL_Keycode key) const
{
	wstring retval;

	switch(key)
	{
		case SDLK_BACKSPACE:
			retval = L"Backspace";
			break;
		case SDLK_TAB:
			retval = L"Tab";
			break;
		case SDLK_CLEAR:
			retval = L"Clear";
			break;
		case SDLK_RETURN:
			retval = L"Return";
			break;
		case SDLK_PAUSE:
			retval = L"Pause";
			break;
		case SDLK_ESCAPE:
			retval = L"Escape";
			break;
		case SDLK_SPACE:
			retval = L"Space";
			break;
		case SDLK_EXCLAIM:
			retval = L"!";
			break;
		case SDLK_QUOTEDBL:
			retval = L"\"";
			break;
		case SDLK_HASH:
			retval = L"#";
			break;
		case SDLK_DOLLAR:
			retval = L"$";
			break;
		case SDLK_AMPERSAND:
			retval = L"&";
			break;
		case SDLK_QUOTE:
			retval = L"'";
			break;
		case SDLK_LEFTPAREN:
			retval = L"(";
			break;
		case SDLK_RIGHTPAREN:
			retval = L")";
			break;
		case SDLK_ASTERISK:
			retval = L"*";
			break;
		case SDLK_PLUS:
			retval = L"+";
			break;
		case SDLK_COMMA:
			retval = L",";
			break;
		case SDLK_MINUS:
			retval = L"-";
			break;
		case SDLK_PERIOD:
			retval = L".";
			break;
		case SDLK_SLASH:
			retval = L"/";
			break;
		case SDLK_0:
			retval = L"0";
			break;
		case SDLK_1:
			retval = L"1";
			break;
		case SDLK_2:
			retval = L"2";
			break;
		case SDLK_3:
			retval = L"3";
			break;
		case SDLK_4:
			retval = L"4";
			break;
		case SDLK_5:
			retval = L"5";
			break;
		case SDLK_6:
			retval = L"6";
			break;
		case SDLK_7:
			retval = L"7";
			break;
		case SDLK_8:
			retval = L"8";
			break;
		case SDLK_9:
			retval = L"9";
			break;
		case SDLK_COLON:
			retval = L":";
			break;
		case SDLK_SEMICOLON:
			retval = L";";
			break;
		case SDLK_LESS:
			retval = L"<";
			break;
		case SDLK_EQUALS:
			retval = L"=";
			break;
		case SDLK_GREATER:
			retval = L">";
			break;
		case SDLK_QUESTION:
			retval = L"?";
			break;
		case SDLK_AT:
			retval = L"@";
			break;
		case SDLK_LEFTBRACKET:
			retval = L"[";
			break;
		case SDLK_BACKSLASH:
			retval = L"\\";
			break;
		case SDLK_RIGHTBRACKET:
			retval = L"]";
			break;
		case SDLK_CARET:
			retval = L"^";
			break;
		case SDLK_UNDERSCORE:
			retval = L"_";
			break;
		case SDLK_BACKQUOTE:
			retval = L"`";
			break;
		case SDLK_a:
			retval = L"a";
			break;
		case SDLK_b:
			retval = L"b";
			break;
		case SDLK_c:
			retval = L"c";
			break;
		case SDLK_d:
			retval = L"d";
			break;
		case SDLK_e:
			retval = L"e";
			break;
		case SDLK_f:
			retval = L"f";
			break;
		case SDLK_g:
			retval = L"g";
			break;
		case SDLK_h:
			retval = L"h";
			break;
		case SDLK_i:
			retval = L"i";
			break;
		case SDLK_j:
			retval = L"j";
			break;
		case SDLK_k:
			retval = L"k";
			break;
		case SDLK_l:
			retval = L"l";
			break;
		case SDLK_m:
			retval = L"m";
			break;
		case SDLK_n:
			retval = L"n";
			break;
		case SDLK_o:
			retval = L"o";
			break;
		case SDLK_p:
			retval = L"p";
			break;
		case SDLK_q:
			retval = L"q";
			break;
		case SDLK_r:
			retval = L"r";
			break;
		case SDLK_s:
			retval = L"s";
			break;
		case SDLK_t:
			retval = L"t";
			break;
		case SDLK_u:
			retval = L"u";
			break;
		case SDLK_v:
			retval = L"v";
			break;
		case SDLK_w:
			retval = L"w";
			break;
		case SDLK_x:
			retval = L"x";
			break;
		case SDLK_y:
			retval = L"y";
			break;
		case SDLK_z:
			retval = L"z";
			break;
		case SDLK_DELETE:
			retval = L"Delete";
			break;
		case SDLK_KP_0:
			retval = L"NumPad0";
			break;
		case SDLK_KP_1:
			retval = L"NumPad1";
			break;
		case SDLK_KP_2:
			retval = L"NumPad2";
			break;
		case SDLK_KP_3:
			retval = L"NumPad3";
			break;
		case SDLK_KP_4:
			retval = L"NumPad4";
			break;
		case SDLK_KP_5:
			retval = L"NumPad5";
			break;
		case SDLK_KP_6:
			retval = L"NumPad6";
			break;
		case SDLK_KP_7:
			retval = L"NumPad7";
			break;
		case SDLK_KP_8:
			retval = L"NumPad8";
			break;
		case SDLK_KP_9:
			retval = L"NumPad9";
			break;
		case SDLK_KP_PERIOD:
			retval = L"NumPad.";
			break;
		case SDLK_KP_DIVIDE:
			retval = L"NumPad/";
			break;
		case SDLK_KP_MULTIPLY:
			retval = L"NumPad*";
			break;
		case SDLK_KP_MINUS:
			retval = L"NumPad-";
			break;
		case SDLK_KP_PLUS:
			retval = L"NumPad+";
			break;
		case SDLK_KP_ENTER:
			retval = L"NumPadEnter";
			break;
		case SDLK_KP_EQUALS:
			retval = L"NumPad=";
			break;
		case SDLK_UP:
			retval = L"CursorUp";
			break;
		case SDLK_DOWN:
			retval = L"CursorDown";
			break;
		case SDLK_LEFT:
			retval = L"CursorLeft";
			break;
		case SDLK_RIGHT:
			retval = L"CursorRight";
			break;
		case SDLK_INSERT:
			retval = L"Insert";
			break;
		case SDLK_HOME:
			retval = L"Home";
			break;
		case SDLK_END:
			retval = L"End";
			break;
		case SDLK_PAGEUP:
			retval = L"PageUp";
			break;
		case SDLK_PAGEDOWN:
			retval = L"PageDown";
			break;
		case SDLK_F1:
			retval = L"F1";
			break;
		case SDLK_F2:
			retval = L"F2";
			break;
		case SDLK_F3:
			retval = L"F3";
			break;
		case SDLK_F4:
			retval = L"F4";
			break;
		case SDLK_F5:
			retval = L"F5";
			break;
		case SDLK_F6:
			retval = L"F6";
			break;
		case SDLK_F7:
			retval = L"F7";
			break;
		case SDLK_F8:
			retval = L"F8";
			break;
		case SDLK_F9:
			retval = L"F9";
			break;
		case SDLK_F10:
			retval = L"F10";
			break;
		case SDLK_F11:
			retval = L"F11";
			break;
		case SDLK_F12:
			retval = L"F12";
			break;
		case SDLK_F13:
			retval = L"F13";
			break;
		case SDLK_F14:
			retval = L"F14";
			break;
		case SDLK_F15:
			retval = L"F15";
			break;
		case SDLK_HELP:
			retval = L"Help";
			break;
		case SDLK_PRINTSCREEN:
			retval = L"PrintScreen";
			break;
		default: //To avoid gcc warnings.
			break;
	}

	return retval;
}

//------------------------------------------------------------------------------
wstring SDL2_0KeyManager::getJoyButtonText(SDL_JoyButtonEvent& event) const
{
	wstringstream keyString;

	keyString << L"Joy" << event.which << L"Button" << event.button;

	return keyString.str();
}

//------------------------------------------------------------------------------
wstring SDL2_0KeyManager::getJoyHatText(SDL_JoyHatEvent& event) const
{
	wstringstream keyString;

	keyString << L"Joy" << event.which << L"Hat" << event.hat;

	if(event.value&SDL_HAT_CENTERED)
		keyString << L"Centre";
	else
	{
		if(event.value&SDL_HAT_UP)
			keyString << L"Up";
		else if(event.value&SDL_HAT_DOWN)
			keyString << L"Down";
		if(event.value&SDL_HAT_LEFT)
			keyString << L"Left";
		else if(event.value&SDL_HAT_RIGHT)
			keyString << L"Right";
	}

	return keyString.str();
}
