#include "KeyboardSettings.hh"
#include "EnumSetting.hh"
#include "BooleanSetting.hh"
#include "memory.hh"
#include <cassert>

namespace openmsx {

KeyboardSettings::KeyboardSettings(CommandController& commandController)
	: alwaysEnableKeypad(make_unique<BooleanSetting>(
		commandController, "kbd_numkeypad_always_enabled",
		"Numeric keypad is always enabled, even on an MSX that does not have one",
		false))
	, traceKeyPresses(make_unique<BooleanSetting>(
		commandController, "kbd_trace_key_presses",
		"Trace key presses (show SDL key code, SDL modifiers and Unicode code-point value)",
		false, Setting::DONT_SAVE))
	, autoToggleCodeKanaLock(make_unique<BooleanSetting>(commandController,
		"kbd_auto_toggle_code_kana_lock",
		"Automatically toggle the CODE/KANA lock, based on the characters entered on the host keyboard",
		true))
{
	EnumSetting<Keys::KeyCode>::Map allowedKeys;
	allowedKeys.push_back(std::make_pair("RALT",        Keys::K_RALT));
	allowedKeys.push_back(std::make_pair("MENU",        Keys::K_MENU));
	allowedKeys.push_back(std::make_pair("RCTRL",       Keys::K_RCTRL));
	allowedKeys.push_back(std::make_pair("HENKAN_MODE", Keys::K_HENKAN_MODE));
	allowedKeys.push_back(std::make_pair("RSHIFT",      Keys::K_RSHIFT));
	allowedKeys.push_back(std::make_pair("RMETA",       Keys::K_RMETA));
	allowedKeys.push_back(std::make_pair("LMETA",       Keys::K_LMETA));
	allowedKeys.push_back(std::make_pair("LSUPER",      Keys::K_LSUPER));
	allowedKeys.push_back(std::make_pair("RSUPER",      Keys::K_RSUPER));
	allowedKeys.push_back(std::make_pair("HELP",        Keys::K_HELP));
	allowedKeys.push_back(std::make_pair("UNDO",        Keys::K_UNDO));
	allowedKeys.push_back(std::make_pair("END",         Keys::K_END));
	allowedKeys.push_back(std::make_pair("PAGEUP",      Keys::K_PAGEUP));
	allowedKeys.push_back(std::make_pair("PAGEDOWN",    Keys::K_PAGEDOWN));
	codeKanaHostKey = make_unique<EnumSetting<Keys::KeyCode>>(
		commandController, "kbd_code_kana_host_key",
		"Host key that maps to the MSX CODE/KANA key. Please note that the HENKAN_MODE key only exists on Japanese host keyboards)",
		Keys::K_RALT, allowedKeys);

	deadkeyHostKey[0] = make_unique<EnumSetting<Keys::KeyCode>>(
		commandController, "kbd_deadkey1_host_key",
		"Host key that maps to deadkey 1. Not applicable to Japanese and Korean MSX models",
		Keys::K_RCTRL, allowedKeys);

	deadkeyHostKey[1] = make_unique<EnumSetting<Keys::KeyCode>>(
		commandController, "kbd_deadkey2_host_key",
		"Host key that maps to deadkey 2. Only applicable to Brazilian MSX models (Sharp Hotbit and Gradiente)",
		Keys::K_PAGEUP, allowedKeys);

	deadkeyHostKey[2] = make_unique<EnumSetting<Keys::KeyCode>>(
		commandController, "kbd_deadkey3_host_key",
		"Host key that maps to deadkey 3. Only applicable to Brazilian Sharp Hotbit MSX models",
		Keys::K_PAGEDOWN, allowedKeys);

	EnumSetting<KpEnterMode>::Map kpEnterModeMap;
	kpEnterModeMap.push_back(std::make_pair("KEYPAD_COMMA", MSX_KP_COMMA));
	kpEnterModeMap.push_back(std::make_pair("ENTER",        MSX_ENTER));
	kpEnterMode = make_unique<EnumSetting<KpEnterMode>>(
		commandController, "kbd_numkeypad_enter_key",
		"MSX key that the enter key on the host numeric keypad must map to",
		MSX_KP_COMMA, kpEnterModeMap);

	EnumSetting<MappingMode>::Map mappingModeMap;
	mappingModeMap.push_back(std::make_pair("KEY",       KEY_MAPPING));
	mappingModeMap.push_back(std::make_pair("CHARACTER", CHARACTER_MAPPING));
	mappingMode = make_unique<EnumSetting<MappingMode>>(
		commandController, "kbd_mapping_mode",
		"Keyboard mapping mode",
		CHARACTER_MAPPING, mappingModeMap);
}

KeyboardSettings::~KeyboardSettings()
{
}

EnumSetting<Keys::KeyCode>& KeyboardSettings::getCodeKanaHostKey() const
{
	return *codeKanaHostKey;
}

Keys::KeyCode KeyboardSettings::getDeadkeyHostKey(unsigned n) const
{
	assert(n < 3);
	return deadkeyHostKey[n]->getEnum();
}

EnumSetting<KeyboardSettings::KpEnterMode>& KeyboardSettings::getKpEnterMode() const
{
	return *kpEnterMode;
}

EnumSetting<KeyboardSettings::MappingMode>& KeyboardSettings::getMappingMode() const
{
	return *mappingMode;
}

BooleanSetting& KeyboardSettings::getAlwaysEnableKeypad() const
{
	return *alwaysEnableKeypad;
}

BooleanSetting& KeyboardSettings::getTraceKeyPresses() const
{
	return *traceKeyPresses;
}

BooleanSetting& KeyboardSettings::getAutoToggleCodeKanaLock() const
{
	return *autoToggleCodeKanaLock;
}

} // namespace openmsx
