//Copyright (C) Ben Parbury - All Rights Reserved. Unauthorized copying of this file, via any medium is strictly prohibited. Written by Ben Parbury <ben@gridlockinteractive.com> 2014

EPadButtonCode =
{
	a : 0,
	b : 1,
	x : 2,
	y : 3,
	
	//lb : 4,
	rb : 5,
	lt : 6,
	//rt : 7,

	back : 8,
	start : 9,

	up : 12,
	down : 13,
	left : 14,
	right : 15,
}

//Copyright (C) Ben Parbury - All Rights Reserved. Unauthorized copying of this file, via any medium is strictly prohibited. Written by Ben Parbury <ben@gridlockinteractive.com> 2014
function PadCodeToString(padcode)
{
	return gPadCodeToString[padcode];
}

var gPadCodeToString = new Array();
gPadCodeToString[EPadButtonCode.a] = "A"
gPadCodeToString[EPadButtonCode.b] = "B"
gPadCodeToString[EPadButtonCode.x] = "X"
gPadCodeToString[EPadButtonCode.y] = "Y"


EPadAxisCode =
{
	leftRight : 0,
	upDown : 1,
	leftRightAlt : 2,
	upDownAlt : 3,
}

function AxisState()
{
	this.refireTime = 0;
	this.prevValue = 0;
}

var gPad = new Pad();

function Pad()
{
	this.axisThreshold = 0.7;
	
	this.buttonThreshold = 0.5;
	
	this.refireSpeed = 15;
	this.heldRefireSpeed = 3;
	
	this.gamepad = null;
	this.registeringPad = null;
	
	this.Update = function()
	{
		var gamepad = navigator.webkitGetGamepads && navigator.webkitGetGamepads()[0];
		if(gamepad)
		{
			if(!this.gamepad)
			{
				gConsole.Log(1, "[PAD] Added " + gamepad.id);
				this.gamepad = gamepad;
				this.registeringPad = this.refireSpeed;
				SetInputType(EInputType.Pad);
				return;
			}
			else if(this.registeringPad)
			{
				this.registeringPad--;
				if(this.registeringPad <= 0)
				{
					this.registeringPad = null;
				}
				return;
			}
			for(var button in EPadButtonCode)
			{
				if(gamepad.buttons[EPadButtonCode[button]] > this.buttonThreshold)
				{
					if(!this.buttonState[button])
					{
						this.buttonState[button] = this.refireSpeed;
						this.OnPadDown(button);
						this.OnPadPress(button);
					}
					else if(this.buttonState[button] == 1)
					{
						this.buttonState[button] = this.heldRefireSpeed;
						this.OnPadDown(button);
					}
					else
					{
						this.buttonState[button]--;
					}
					
					SetInputType(EInputType.Pad);
				}
				else
				{
					if(this.buttonState[button])
					{
						this.OnPadUp(button);
						this.buttonState[button] = 0;
					}
				}
			}
			
			for(var axis in EPadAxisCode)
			{
				var value = gamepad.axes[EPadAxisCode[axis]];
				if(Math.abs(value) > this.axisThreshold)
				{
					if(this.axisState[axis].refireTime == 0)
					{
						this.axisState[axis].refireTime = this.refireSpeed;
						this.axisState[axis].prevValue = value;
						this.OnPadAxisDown(axis, value > 0);
						this.OnPadAxisPress(axis, value > 0);
					}
					else if(this.axisState[axis].refireTime == 1)
					{
						this.axisState[axis].refireTime = this.heldRefireSpeed;
						this.OnPadAxisDown(axis, value > 0);
					}
					else
					{
						this.axisState[axis].refireTime--;
					}
					SetInputType(EInputType.Pad);
				}
				else
				{
					if(this.axisState[axis].refireTime > 0)
					{
						this.OnPadAxisUp(axis, this.axisState[axis].prevValue > 0);
						this.axisState[axis].refireTime = 0;
					}
				}
			}
		}
		else if (this.gamepad)
		{
			gConsole.Log(1, "[PAD] Removed " + this.gamepad.id);
			this.gamepad = null;
		}
	}
	
	this.padDownCallback;
	this.padUpCallback;
	this.padPressCallback;

	this.buttonState = new Array();
	this.axisState = new Array();
	for(var axis in EPadAxisCode)
	{
		this.axisState[axis] = new AxisState();
	}
	
	this.gamepad = null;
	
	this.Init = function(padDownCallback, padUpCallback, padPressCallback)
	{
		gConsole.Log(1, "[PAD] Init");
		
		this.padDownCallback = padDownCallback;
		this.padUpCallback = padUpCallback;
		this.padPressCallback = padPressCallback;
	}

	this.OnPadDown = function(button)
	{
		gConsole.Log(11, "[PAD] PadDown " + button);	
		this.padDownCallback(this.PadToKey(button));
	}

	this.OnPadUp = function(button)
	{
		gConsole.Log(11, "[PAD] PadUp " + button);
		this.padUpCallback(this.PadToKey(button));
	}

	this.OnPadPress = function(button)
	{
		gConsole.Log(11, "[PAD] PadPress " + button);
		this.padPressCallback(this.PadToKey(button));
	}
	
	this.OnPadAxisDown = function(axis, second)
	{
		switch(EPadAxisCode[axis])
		{
			case EPadAxisCode.leftRight:
			case EPadAxisCode.leftRightAlt:
				this.OnPadDown(second ? "right" : "left");
				break;
			case EPadAxisCode.upDown:
			case EPadAxisCode.upDownAlt:
				this.OnPadDown(second ? "down" : "up");
				break;
		}
	}

	this.OnPadAxisUp = function(axis, second)
	{
		switch(EPadAxisCode[axis])
		{
			case EPadAxisCode.leftRight:
			case EPadAxisCode.leftRightAlt:
				this.OnPadUp(second ? "right" : "left");
				break;
			case EPadAxisCode.upDown:
			case EPadAxisCode.upDownAlt:
				this.OnPadUp(second ? "down" : "up");
				break;
		}
	}

	this.OnPadAxisPress = function(axis, second)
	{
		switch(EPadAxisCode[axis])
		{
			case EPadAxisCode.leftRight:
			case EPadAxisCode.leftRightAlt:
				this.OnPadPress(second ? "right" : "left");
				break;
			case EPadAxisCode.upDown:
			case EPadAxisCode.upDownAlt:
				this.OnPadPress(second ? "down" : "up");
				break;
		}
	}
	
	this.PadToKey = function(button)
	{
		switch(EPadButtonCode[button])
		{
			case EPadButtonCode.start:
				return EKeyCode.escape;
			case EPadButtonCode.b:
				return EKeyCode.closemenu;
			case EPadButtonCode.a:
				return EKeyCode.return;
			case EPadButtonCode.x:
			case EPadButtonCode.lt:
				return EKeyCode.z;
			case EPadButtonCode.rb:
				return EKeyCode.c;
			case EPadButtonCode.y:
			case EPadButtonCode.back:
				return EKeyCode.r;
			case EPadButtonCode.up:
				return EKeyCode.up;
			case EPadButtonCode.down:
				return EKeyCode.down;
			case EPadButtonCode.left:
				return EKeyCode.left;
			case EPadButtonCode.right:
				return EKeyCode.right;
		}
		return null;
	}
}

