import SDL2


public class Input
{
	private static let _instance = Input()

	public static var instance: Input { _instance }

	//private let _UP: UInt8      = 0
	//private let _PRESS: UInt8   = 1
	//private let _DOWN: UInt8    = 2
	//private let _RELEASE: UInt8 = 3

	private static let _UP: UInt8      = 0b000
	private static let _DOWN: UInt8    = 0b010
	private static let _IMPULSE: UInt8 = 0b001
	private static let _REPEAT: UInt8  = 0b100
	private static let _PRESS: UInt8   = _DOWN | _IMPULSE
	private static let _RELEASE: UInt8 = _UP | _IMPULSE

	private var _keys = [UInt8](repeating: _UP, count: Int(SDL_NUM_SCANCODES.rawValue))

	private init() {}

	internal func newTick()
	{
		//_keys = _keys.map({ i in (i & 0x1) == 0x1 ? ((i &+ 1) & 0x3) : i })
		_keys = _keys.map({ $0 & ~Input._IMPULSE })
		//for i in 0..<Int(SDL_NUM_SCANCODES.rawValue)
		//{
		//	_keys[i] &= ~0x1
		//}
	}

	internal func pressEvent(scan: SDL_Scancode)
	{
		_keys[Int(scan.rawValue)] = Input._PRESS
	}

	internal func releaseEvent(scan: SDL_Scancode)
	{
		_keys[Int(scan.rawValue)] = Input._RELEASE
	}

	public func keyDown(_ key: Key) -> Bool
	{
		//SDL_GetKeyboardState(nil).withMemoryRebound(to: UInt8.self, capacity: Int(SDL_NUM_SCANCODES.rawValue))
		//{ state in
		//	state[Int(key.sdlScancode.rawValue)] != 0
		//}
		_keys[Int(key.sdlScancode.rawValue)] & Input._DOWN == Input._DOWN
	}

	public func keyPressed(_ key: Key) -> Bool
	{
		_keys[Int(key.sdlScancode.rawValue)] == Input._PRESS
	}

	public func keyReleased(_ key: Key) -> Bool
	{
		_keys[Int(key.sdlKeycode.rawValue)] == Input._RELEASE
	}
}

public enum Key
{
	case a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
	case right, left, down, up
}

extension Key
{
	internal var sdlKeycode: SDL_KeyCode
	{
		switch self
		{
		case .a: SDLK_a
		case .b: SDLK_a
		case .c: SDLK_a
		case .d: SDLK_a
		case .e: SDLK_a
		case .f: SDLK_a
		case .g: SDLK_a
		case .h: SDLK_a
		case .i: SDLK_a
		case .j: SDLK_a
		case .k: SDLK_a
		case .l: SDLK_a
		case .m: SDLK_a
		case .n: SDLK_a
		case .o: SDLK_a
		case .p: SDLK_a
		case .q: SDLK_a
		case .r: SDLK_a
		case .s: SDLK_a
		case .t: SDLK_a
		case .u: SDLK_a
		case .v: SDLK_a
		case .w: SDLK_a
		case .x: SDLK_a
		case .y: SDLK_a
		case .z: SDLK_a
		case .left:  SDLK_LEFT
		case .right: SDLK_RIGHT
		case .up:    SDLK_UP
		case .down:  SDLK_DOWN
		}
	}

	internal var sdlScancode: SDL_Scancode
	{
		switch self
		{
		case .a:     SDL_SCANCODE_A
		case .b:     SDL_SCANCODE_B
		case .c:     SDL_SCANCODE_C
		case .d:     SDL_SCANCODE_D
		case .e:     SDL_SCANCODE_E
		case .f:     SDL_SCANCODE_F
		case .g:     SDL_SCANCODE_G
		case .h:     SDL_SCANCODE_H
		case .i:     SDL_SCANCODE_I
		case .j:     SDL_SCANCODE_J
		case .k:     SDL_SCANCODE_K
		case .l:     SDL_SCANCODE_L
		case .m:     SDL_SCANCODE_M
		case .n:     SDL_SCANCODE_N
		case .o:     SDL_SCANCODE_O
		case .p:     SDL_SCANCODE_P
		case .q:     SDL_SCANCODE_Q
		case .r:     SDL_SCANCODE_R
		case .s:     SDL_SCANCODE_S
		case .t:     SDL_SCANCODE_T
		case .u:     SDL_SCANCODE_U
		case .v:     SDL_SCANCODE_V
		case .w:     SDL_SCANCODE_W
		case .x:     SDL_SCANCODE_X
		case .y:     SDL_SCANCODE_Y
		case .z:     SDL_SCANCODE_Z
		case .left:  SDL_SCANCODE_LEFT
		case .right: SDL_SCANCODE_RIGHT
		case .up:    SDL_SCANCODE_UP
		case .down:  SDL_SCANCODE_DOWN
		}
	}
}

extension SDL_KeyCode
{
	internal init(scancode: SDL_Scancode)
	{
		self.init(scancode.rawValue | UInt32(SDLK_SCANCODE_MASK))
	}
}
