/*********************************************************\
         __      __           __  __
        / /     / / _____    / / / / ______   __     __
       / /     / / /___  \  / / / / / ___  | / /    / /
      / /_____/ / _____| / / / / / / /__/ / / /    / /
     / ______  / / ___  / / / / / / _____/ / /    / /
    / /     / / / /__/ / / / / / / |____  / |____/ /
   /_/     /_/ |______/ /_/ /_/  \_____/  \_____  /
                                         ______/ /
            High Level Game Framework   /_______/

  ------------------------------------------------------

  Copyright (c) 2009 - Rodrigo Braz Monteiro.
  This file is subject to the terms of license.txt.

\*********************************************************/

#include <SDL_joystick.h>
#include "input_joystick_sdl.h"
#include "utils.h"
#include "exception.h"
using namespace Halley;


InputJoystickSDL::InputJoystickSDL(int number)
	: index(number)
{
	// Open
	joystick = SDL_JoystickOpen(index);
	if (!joystick) throw Exception("Could not open Joystick");

	// Axes
	axes.resize(SDL_JoystickNumAxes(joystick));
	axisAdjust = &defaultAxisAdjust;
	
	// Hats
	int nHats = SDL_JoystickNumHats(joystick);
	for (int i=0; i<nHats; i++) {
		hats.push_back(spInputButtonBase(new InputJoystickHatSDL));
	}

	// Buttons
	int buttons = SDL_JoystickNumButtons(joystick);
	init(buttons);

	// Done
	std::cout << "Initialized SDL joystick: \"" << getName() << "\".\n";
}

InputJoystickSDL::~InputJoystickSDL()
{
	if (joystick != NULL) {
		SDL_JoystickClose(joystick);
		joystick = NULL;
	}
}

std::string InputJoystickSDL::getName() const
{
	return SDL_JoystickName(index);
}

void InputJoystickSDL::processEvent(const SDL_Event& _event)
{
	switch (_event.type) {
		case SDL_JOYAXISMOTION:
			{
				SDL_JoyAxisEvent event = _event.jaxis;
				axes[event.axis] = mid(-1.0f, axisAdjust(event.value / 32767.0f), 1.0f);
				break;
			}
		case SDL_JOYBUTTONDOWN:
			{
				SDL_JoyButtonEvent event = _event.jbutton;
				onButtonPressed(event.button);
				break;
			}
		case SDL_JOYBUTTONUP:
			{
				SDL_JoyButtonEvent event = _event.jbutton;
				onButtonReleased(event.button);
				break;
			}
		case SDL_JOYHATMOTION:
			{
				SDL_JoyHatEvent event = _event.jhat;
				dynamic_pointer_cast<InputJoystickHatSDL>(hats[event.hat])->processEvent(_event);
				break;
			}
		case SDL_JOYBALLMOTION:
			{
				break;
			}
	}
}


void InputJoystickHatSDL::processEvent(const SDL_Event& _event)
{
	SDL_JoyHatEvent event = _event.jhat;
	int value = event.value;

	for (int i=0; i<4; i++) {
		if (value & (1 << i)) {
			onButtonPressed(i);
		} else {
			onButtonReleased(i);
		}
	}
}
