import SDL2


public class Input
{
	private static let _instance = Input()
	public static var instance: Input { _instance }

	public var keyboard: Keyboard { _keyboard }
	public func getPad(id: Int) -> GamePad? { _pads[Int32(id)] }
	public var firstPadID: Int? { _firstJoyID >= 0 ? Int(_firstJoyID) : nil }

	private var _keyboard = Keyboard()
	private var _pads = Dictionary<Int32, GamePad>()
	private var _firstJoyID: Int32 = -1

	private init() {}

	internal func pressEvent(scan: SDL_Scancode, repeat r: Bool) { keyboard.pressEvent(scan: scan, repeat: r) }
	internal func releaseEvent(scan: SDL_Scancode) { keyboard.releaseEvent(scan: scan) }

	internal func padConnectedEvent(index: Int32)
	{
		guard let sdlPad = SDL_GameControllerOpen(index)
		else { return }
		let id = SDL_JoystickGetDeviceInstanceID(index)
		_pads[id] = GamePad(pad: sdlPad)
		print("Using gamepad #\(id), \"\(String(cString: SDL_GameControllerName(sdlPad)))\"")
		if _firstJoyID < 0 { _firstJoyID = id }
	}

	internal func padRemovedEvent(index: Int32)
	{
		let id = SDL_JoystickGetDeviceInstanceID(index)
		_pads.removeValue(forKey: id)
		if id == _firstJoyID
		{
			_firstJoyID = _pads.keys.first ?? -1
		}
	}

	internal func padButtonPressEvent(id: Int32, btn: UInt8)
	{
		_pads[id]?.buttonPressEvent(btn)
	}

	internal func padButtonReleaseEvent(id: Int32, btn: UInt8)
	{
		_pads[id]?.buttonReleaseEvent(btn)
	}

	internal func padAxisEvent(id: Int32, axis: UInt8, value: Int16)
	{
		_pads[id]?.axisEvent(axis, value)
	}

	internal func newTick()
	{
		_keyboard.newTick()
		for pad in _pads.values { pad.newTick() }
	}
}
