
#include <Windows.h>

#include <Spectre/Input/InputEvent.h>
#include <Spectre/Input/InputModule.h>
#include "Win32Input.h"
#include "Win32Keyboard.h"
#include "Win32MsgBuffer.h"

static Win32MsgBuffer msg_buf;

static const Key::Type deviceToKey[256] = {
	/* 0		1		2		3		4		5		6		7 */
	/* 8		9		A		B		C		D		E		F */
	// 00-0F
	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	Key::Backspace, Key::Tab,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Enter,	Key::Unknown,	Key::Unknown,
	// 10-1F
	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Pause,	Key::Capslock,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Escape,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	// 20-2F
	Key::Space,	Key::PageUp,	Key::PageDown,	Key::End,	Key::Home,	Key::Left,	Key::Up,	Key::Right,
	Key::Down,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Insert,	Key::Delete,	Key::Unknown,
	// 30-3F
	Key::Zero,	Key::One,	Key::Two,	Key::Three,	Key::Four,	Key::Five,	Key::Six,	Key::Seven,
	Key::Eight,	Key::Nine,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	// 40-4F
	Key::Unknown,	Key::A,		Key::B,		Key::C,		Key::D,		Key::E,		Key::F,		Key::G,
	Key::H,		Key::I,		Key::J,		Key::K,		Key::L,		Key::M,		Key::N,		Key::O,
	// 50-5F
	Key::P,		Key::Q,		Key::R,		Key::S,		Key::T,		Key::U,		Key::V,		Key::W,
	Key::X,		Key::Y,		Key::Z,		Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	// 60-6F
	Key::NUMPAD_0,	Key::NUMPAD_1,	Key::NUMPAD_2,	Key::NUMPAD_3,	Key::NUMPAD_4,	Key::NUMPAD_5,	Key::NUMPAD_6,	Key::NUMPAD_7,
	Key::NUMPAD_8,	Key::NUMPAD_9,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	// 70-7F
	Key::F1,	Key::F2,	Key::F3,	Key::F4,	Key::F5,	Key::F6,	Key::F7,	Key::F8,
	Key::F9,	Key::F10,	Key::F11,	Key::F12,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	// 80-8F
	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	// 90-9F
	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	// A0-AF
	Key::LShift,	Key::RShift,	Key::LCtrl,	Key::RCtrl,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	// B0-BF
	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Comma,	Key::Unknown,	Key::Period,	Key::Unknown,
	// C0-CF
	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	// E0-EF
	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	// F0-FF
	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,	Key::Unknown,
};

void Win32Keyboard::init()
{
	Win32Input::inputMsgBuffer.enabled = true;

	memset(m_btnState, 0, sizeof(m_btnState) / sizeof(m_btnState[0]));
}

bool Win32Keyboard::isKeyDown(Key::Type key)
{
	return m_btnState[key];
}

void Win32Keyboard::update(InputModule *input)
{
	for(int i = 0; i < msg_buf.index; i++) {

		MSG msg = msg_buf.messages[i];

		if (msg.message == WM_KILLFOCUS) {

			for(int i = 0; i < Key::NUM_KEYS; i++) {

				if (m_btnState[i]) {
					InputEvent event(InputEvent::Key);
					event.key.code = (Key::Type) i;
					event.key.pressed = msg.message == WM_KEYDOWN;

					m_btnState[i] = false;
					input->postInputEvent(event);
				}
			}

			continue;
		}

		if (msg.message != WM_KEYDOWN && msg.message != WM_KEYUP) {
			continue;
		}

		Key::Type key = deviceToKey[msg.wParam % 0xFF];

		if (key != Key::Unknown) {
			InputEvent event(InputEvent::Key);
			event.key.code = key;
			event.key.pressed = msg.message == WM_KEYDOWN;

			m_btnState[key] = event.key.pressed;
			input->postInputEvent(event);
		}
	}

	msg_buf.index = 0;
}

bool Win32Keyboard::handleMessage(MSG message)
{
	return msg_buf.postMessage(message);
}
