#include "InputHandler.h"

#include "EventManager.h"
#include "InputEvents.h"
#include "ApplicationEvents.h"

#include "GameException.h"

// #ifdef _GP2X
// #include <linux/ioctl.h>
// #include <unistd.h>
// #include <sys/types.h>
// #include <sys/stat.h>
// #include <fcntl.h>
// #endif

#include "DebugUtil.h"

template<> InputHandler* TSingleton<InputHandler>::m_pInstance = NULL;

InputHandler::InputHandler()
#ifdef _GP2X
: m_pJoystick(0)
#endif
{
	for(int i = 0; i < eNumInputKeys; i++)
		m_keyArray[i] = false;
}

InputHandler::~InputHandler()
{

}

void InputHandler::Update()
{
// #ifdef _GP2X
// 	int fd = open("/dev/GPIO", O_RDWR | O_NDELAY);
// 	if(fd < 0)
// 	{
// 		DebugUtil::outputDebugText("GPIO Open failed!\n");
// 		return; //Throw exception
// 	}
// 
// 	DebugUtil::outputDebugText("GPIO Open succeeded!\n");
// 
// 	unsigned long buff = 0;
// 	if (read(fd, &buff, 4) != 4) 
// 	{
// 		DebugUtil::outputDebugText("GPIO Read failed!\n");
// 		return; //throw exception
// 	}
// 
// 	DebugUtil::outputDebugText("GPIO Read succeeded!\n");
// 
// 	close(fd);
// 
// 	RegisterKeyValue(eKeyUp, (buff & GP2X_VK_UP));
// 	RegisterKeyValue(eKeyDown, (buff & GP2X_VK_DOWN));
// 	RegisterKeyValue(eKeyLeft, (buff & GP2X_VK_LEFT));
// 	RegisterKeyValue(eKeyRight, (buff & GP2X_VK_RIGHT));
// 	RegisterKeyValue(eKeyButtonStart, (buff & GP2X_VK_START));
// 	RegisterKeyValue(eKeyButtonSelect, (buff & GP2X_VK_SELECT));
// 	RegisterKeyValue(eKeyButtonVolumeUp, (buff & GP2X_VK_VOL_UP));
// 	RegisterKeyValue(eKeyButtonVolumeDown, (buff & GP2X_VK_VOL_DOWN));
// 	RegisterKeyValue(eKeyButtonA, (buff & GP2X_VK_FA));
// 	RegisterKeyValue(eKeyButtonB, (buff & GP2X_VK_FB));
// 	RegisterKeyValue(eKeyButtonX, (buff & GP2X_VK_FX));
// 	RegisterKeyValue(eKeyButtonY, (buff & GP2X_VK_FY));
// 	RegisterKeyValue(eKeyButtonL, (buff & GP2X_VK_FL));
// 	RegisterKeyValue(eKeyButtonR, (buff & GP2X_VK_FR));
// 
// #endif

	
#ifdef _GP2X
	m_pJoystick = SDL_JoystickOpen(0);
	if(!m_pJoystick)
		DebugUtil::outputDebugText("ERROR WITH JOYSTICK!!\n");

	SDL_Event event;
	while(SDL_PollEvent(&event))
	{
		DebugUtil::outputDebugText("event found in gp2x joystick thing: %d\n", event.jbutton.button);
		if(event.type == SDL_JOYBUTTONDOWN || event.type == SDL_JOYBUTTONUP)
		{
			eInputKey keyType = ConvertGP2XToEnum(event.jbutton.button);
			
			DebugUtil::outputDebugText("Joystick Button ID Found: %d\n", (int)keyType);
			RegisterKeyValue(keyType, (event.type == SDL_JOYBUTTONDOWN));
		}
	}

	return;
#endif

#ifdef _WIN32
	SDL_Event event;
	while (SDL_PollEvent(&event)) 
	{
		if(event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
		{
			eInputKey keyType = eKeyUndefined;
			switch(event.key.keysym.sym)
			{
				case SDLK_UP:
					keyType = eKeyUp;
					break;
				case SDLK_DOWN:
					keyType = eKeyDown;
					break;
				case SDLK_LEFT:
					keyType = eKeyLeft;
					break;
				case SDLK_RIGHT:
					keyType = eKeyRight;
					break;
				case SDLK_x:
					keyType = eKeyButtonX;
					break;
				case SDLK_s:
					keyType = eKeyButtonY;
					break;
				case SDLK_c:
					keyType = eKeyButtonA;
					break;
				case SDLK_d:
					keyType = eKeyButtonB;
					break;
				case SDLK_w:
					keyType = eKeyButtonL;
					break;
				case SDLK_e:
					keyType = eKeyButtonR;
					break;
				case SDLK_m:
					keyType = eKeyButtonStart;
					break;
				case SDLK_n:
					keyType = eKeyButtonSelect;
					break;
				case SDLK_PAGEUP:
					keyType = eKeyButtonVolumeUp;
					break;
				case SDLK_PAGEDOWN:
					keyType = eKeyButtonVolumeDown;
					break;
			}

			RegisterKeyValue(keyType, (event.type == SDL_KEYDOWN));
		}
		if(event.type == SDL_QUIT)
		{
			ApplicationQuitEvent* pEvent = new ApplicationQuitEvent();
			EventManager::getSingleton()->TriggerEvent(pEvent);
		}
	}
#endif
}

bool InputHandler::IsKeyDown(const eInputKey &key)
{
#ifdef _GP2X
	int button = ConvertEnumToGP2X(key);

	SDL_JoystickUpdate();

	if(button)
		return (bool)SDL_JoystickGetButton(m_pJoystick, button);
	else
		return 0;
#else
	if(key > eNumInputKeys)
	{
		throw GameException(eMinorError, "InputHandler: Key requested in IsKeyDown beyond range: %d", (int)key);
		return false; //Throw exception
	}

	return m_keyArray[key];
#endif
}

void InputHandler::RegisterKeyValue(const eInputKey &key, const bool &bIsDown)
{
	if(key == eKeyUndefined)
		return;

	if(m_keyArray[key] != bIsDown)
	{
		m_keyArray[key] = bIsDown;
		ButtonInputEvent* pEvent = new ButtonInputEvent((int)key, bIsDown);
		DebugUtil::outputDebugText("Button Event sent to event manager: %d || %s\n", (int)key, pEvent->GetEventType().getStr().c_str());
		EventManager::getSingleton()->TriggerEvent(pEvent);
	}
}

#ifdef _GP2X
eInputKey InputHandler::ConvertGP2XToEnum(const Uint8 &button)
{
	eInputKey keyType = eKeyUndefined;
	switch(button)
	{
		case GP2X_BUTTON_UP:
			keyType = eKeyUp;
			break;
		case GP2X_BUTTON_DOWN:
			keyType = eKeyDown;
			break;
		case GP2X_BUTTON_LEFT:
			keyType = eKeyLeft;
			break;
		case GP2X_BUTTON_UPLEFT:
			keyType = eKeyUpLeft;
			break;
		case GP2X_BUTTON_DOWNLEFT:
			keyType = eKeyDownLeft;
			break;
		case GP2X_BUTTON_RIGHT:
			keyType = eKeyRight;
			break;
		case GP2X_BUTTON_UPRIGHT:
			keyType = eKeyUpRight;
			break;
		case GP2X_BUTTON_DOWNRIGHT:
			keyType = eKeyDownRight;
			break;

		case GP2X_BUTTON_X:
			keyType = eKeyButtonX;
			break;
		case GP2X_BUTTON_Y:
			keyType = eKeyButtonY;
			break;
		case GP2X_BUTTON_A:
			keyType = eKeyButtonA;
			break;
		case GP2X_BUTTON_B:
			keyType = eKeyButtonB;
			break;

		case GP2X_BUTTON_L:
			keyType = eKeyButtonL;
			break;
		case GP2X_BUTTON_R:
			keyType = eKeyButtonR;
			break;

		case GP2X_BUTTON_START:
			keyType = eKeyButtonStart;
			break;
		case GP2X_BUTTON_SELECT:
			keyType = eKeyButtonSelect;
			break;

		case GP2X_BUTTON_VOLUP:
			keyType = eKeyButtonVolumeUp;
			break;
		case GP2X_BUTTON_VOLDOWN:
			keyType = eKeyButtonVolumeDown;
			break;
	}

	return keyType;
}

int InputHandler::ConvertEnumToGP2X(const eInputKey &keyType)
{
	int buttonVal = 0;
	switch(keyType)
	{
		case eKeyUp:
			buttonVal = GP2X_BUTTON_UP;
			break;
		case eKeyUpLeft:
			buttonVal = GP2X_BUTTON_UPLEFT;
			break;
		case eKeyUpRight:
			buttonVal = GP2X_BUTTON_UPRIGHT;
			break;
		case eKeyDown:
			buttonVal = GP2X_BUTTON_DOWN;
			break;
		case eKeyDownLeft:
			buttonVal = GP2X_BUTTON_DOWNLEFT;
			break;
		case eKeyDownRight:
			buttonVal = GP2X_BUTTON_DOWNRIGHT;
			break;
		case eKeyLeft:
			buttonVal = GP2X_BUTTON_LEFT;
			break;
		case eKeyRight:
			buttonVal = GP2X_BUTTON_RIGHT;
			break;

		case eKeyButtonA:
			buttonVal = GP2X_BUTTON_A;
			break;
		case eKeyButtonB:
			buttonVal = GP2X_BUTTON_B;
			break;
		case eKeyButtonX:
			buttonVal = GP2X_BUTTON_X;
			break;
		case eKeyButtonY:
			buttonVal = GP2X_BUTTON_Y;
			break;
		case eKeyButtonL:
			buttonVal = GP2X_BUTTON_L;
			break;
		case eKeyButtonR:
			buttonVal = GP2X_BUTTON_R;
			break;

		case eKeyButtonStart:
			buttonVal = GP2X_BUTTON_START;
			break;
		case eKeyButtonSelect:
			buttonVal = GP2X_BUTTON_SELECT;
			break;

		case eKeyButtonVolumeUp:
			buttonVal = GP2X_BUTTON_VOLUP;
			break;
		case eKeyButtonVolumeDown:
			buttonVal = GP2X_BUTTON_VOLDOWN;
			break;
	}

	return buttonVal;
}

#endif
