/******************************************************************************
	Project: 	MicroMacro
	Author: 	SolarStrike Software
	URL:		www.solarstrike.net
	License:	Modified BSD (see license.txt)
******************************************************************************/

#include "gamepad_lua.h"
#include "event.h"
#include "error.h"
#include "macro.h"

extern "C"
{
	#include <lua.h>
	#include <lauxlib.h>
	#include <lualib.h>
}

int Gamepad_lua::regmod(lua_State *L)
{
	static const luaL_Reg _funcs[] = {
		{"pressed", Gamepad_lua::pressed},
		{"released", Gamepad_lua::released},
		{"isDown", Gamepad_lua::isDown},
		{"getPOV", Gamepad_lua::getPOV},
		{"getAxis", Gamepad_lua::getAxis},
		{"getCount", Gamepad_lua::getCount},
		{NULL, NULL}
	};

	luaL_newlib(L, _funcs);
	lua_setglobal(L, GAMEPAD_MODULE_NAME);

	lua_pushnumber(L, JOY_POVBACKWARD/100);
	lua_setglobal(L, "JOY_POVBACKWARD");

	lua_pushnumber(L, JOY_POVFORWARD); // Is 0, no reason to divide
	lua_setglobal(L, "JOY_POVFORWARD");

	lua_pushnumber(L, JOY_POVCENTERED/100);
	lua_setglobal(L, "JOY_POVCENTERED");

	lua_pushnumber(L, JOY_POVLEFT/100);
	lua_setglobal(L, "JOY_POVLEFT");

	lua_pushnumber(L, JOY_POVRIGHT/100);
	lua_setglobal(L, "JOY_POVRIGHT");

	return MicroMacro::ERR_OK;
}

/*	gamepad.pressed(number gamepadId, number btn)
	Returns:	boolean

	If the given gamepad has had its button pressed
	since last polling, returns true. Else, false.
*/
int Gamepad_lua::pressed(lua_State *L)
{
	if( lua_gettop(L) != 2 )
		wrongArgs(L);
	checkType(L, LT_NUMBER, 1);
	checkType(L, LT_NUMBER, 2);

	int joyId = lua_tointeger(L, 1) - 1;
	int button = lua_tointeger(L, 2) - 1;

	lua_pushboolean(L, Macro::instance()->getHid()->joyPressed(joyId, button) == 1);
	return 1;
}

/*	gamepad.released(number gamepadId, number btn)
	Returns:	boolean

	If the given gamepad has had its button released
	since last polling, returns true. Else, false.
*/
int Gamepad_lua::released(lua_State *L)
{
	if( lua_gettop(L) != 2 )
		wrongArgs(L);
	checkType(L, LT_NUMBER, 1);
	checkType(L, LT_NUMBER, 2);

	int joyId = lua_tointeger(L, 1) - 1;
	int button = lua_tointeger(L, 2) - 1;

	lua_pushboolean(L, Macro::instance()->getHid()->joyReleased(joyId, button) == 1);
	return 1;
}

/*	gamepad.isDown(number gamepadId, number btn)
	Returns:	boolean

	If the given gamepad currently has a given
	button held down (as of last polling), returns true.
	Else, returns false.
*/
int Gamepad_lua::isDown(lua_State *L)
{
	if( lua_gettop(L) != 2 )
		wrongArgs(L);
	checkType(L, LT_NUMBER, 1);
	checkType(L, LT_NUMBER, 2);

	int joyId = lua_tointeger(L, 1) - 1;
	int button = lua_tointeger(L, 2) - 1;

	lua_pushboolean(L, Macro::instance()->getHid()->joyIsDown(joyId, button) == 1);
	return 1;
}

/*	gamepad.getPOV(number gamepadId)
	Returns:	number

	Returns the angle of the POV hat (D-pad).
	If centered, returns JOY_POVCENTERED
*/
int Gamepad_lua::getPOV(lua_State *L)
{
	if( lua_gettop(L) != 1 )
		wrongArgs(L);
	checkType(L, LT_NUMBER, 1);

	int joyId = lua_tointeger(L, 1) - 1;
	lua_pushnumber(L, Macro::instance()->getHid()->joyPOV(joyId)/100);
	return 1;
}

/*	gamepad.getAxis(number gamepadId, number axisId)
	Returns:	number

	Returns the axis value for a given gamepad.
	The value will be between 0 (minimum) and 100(maximum).
	If centered, the value will be ~50.

	NOTE: This will not always be exact! Due to calibration,
	floating-point inaccuracies, and physical defects,
	you may receive a value that is a fraction off
	the intended value. I.e. ~49-51 while centered.
*/
int Gamepad_lua::getAxis(lua_State *L)
{
	if( lua_gettop(L) != 2 )
		wrongArgs(L);
	checkType(L, LT_NUMBER, 1);
	checkType(L, LT_NUMBER, 2);

	int joyId = lua_tointeger(L, 1) - 1;
	int axisId = lua_tointeger(L, 2);
	lua_pushnumber(L, Macro::instance()->getHid()->joyAxis(joyId, axisId)/65536.0f*100);
	return 1;
}

/*	NOTE: Commented out until I can find a way
	to make this work.

int Gamepad_lua::press(lua_State *L)
{
	int top = lua_gettop(L);
	if( top != 2 && top != 3 )
		wrongArgs(L);
	checkType(L, LT_NUMBER, 1);
	checkType(L, LT_NUMBER, 2);
	if( top == 3 )
		checkType(L, LT_NIL | LT_NUMBER, 3);

	bool async = true;
	int gamepad = lua_tointeger(L, 1);
	int button = lua_tointeger(L, 2);
	if( top == 3 )
		async = (bool)lua_toboolean(L, 3);

	Macro::instance()->getHid()->joyPress(gamepad, button, async);

	return 0;
}

int Gamepad_lua::hold(lua_State *L)
{
	if( lua_gettop(L) != 2 )
		wrongArgs(L);
	checkType(L, LT_NUMBER, 1);
	checkType(L, LT_NUMBER, 2);

	int gamepad = lua_tointeger(L, 1);
	int button = lua_tointeger(L, 2);

	Macro::instance()->getHid()->joyHold(gamepad, button);

	return 0;
}

int Gamepad_lua::release(lua_State *L)
{
	if( lua_gettop(L) != 2 )
		wrongArgs(L);
	checkType(L, LT_NUMBER, 1);
	checkType(L, LT_NUMBER, 2);

	int gamepad = lua_tointeger(L, 1);
	int button = lua_tointeger(L, 2);

	Macro::instance()->getHid()->joyRelease(gamepad, button);

	return 0;
}*/

/*	gamepad.getCount()
	Returns:	number

	Returns the number of connected gamepads.
*/
int Gamepad_lua::getCount(lua_State *L)
{
	if( lua_gettop(L) != 0 )
		wrongArgs(L);
	lua_pushnumber(L, Macro::instance()->getHid()->getGamepadCount());
	return 1;
}
