"""Utility functions for actor operations.

Performance optimizations:
- Cached key_map as module-level constant (frozendict pattern)
- Utils class uses __slots__
"""

from typing import Final

# Module-level constant key mapping for O(1) lookup
# Based on standard Windows Virtual Key Codes
# https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
_KEY_MAP: Final[dict[str, tuple[str, int]]] = {
	# Navigation keys
	'Backspace': ('Backspace', 8),
	'Tab': ('Tab', 9),
	'Enter': ('Enter', 13),
	'Escape': ('Escape', 27),
	'Space': ('Space', 32),
	' ': ('Space', 32),
	'PageUp': ('PageUp', 33),
	'PageDown': ('PageDown', 34),
	'End': ('End', 35),
	'Home': ('Home', 36),
	'ArrowLeft': ('ArrowLeft', 37),
	'ArrowUp': ('ArrowUp', 38),
	'ArrowRight': ('ArrowRight', 39),
	'ArrowDown': ('ArrowDown', 40),
	'Insert': ('Insert', 45),
	'Delete': ('Delete', 46),
	# Modifier keys
	'Shift': ('ShiftLeft', 16),
	'ShiftLeft': ('ShiftLeft', 16),
	'ShiftRight': ('ShiftRight', 16),
	'Control': ('ControlLeft', 17),
	'ControlLeft': ('ControlLeft', 17),
	'ControlRight': ('ControlRight', 17),
	'Alt': ('AltLeft', 18),
	'AltLeft': ('AltLeft', 18),
	'AltRight': ('AltRight', 18),
	'Meta': ('MetaLeft', 91),
	'MetaLeft': ('MetaLeft', 91),
	'MetaRight': ('MetaRight', 92),
	# Function keys F1-F24
	'F1': ('F1', 112),
	'F2': ('F2', 113),
	'F3': ('F3', 114),
	'F4': ('F4', 115),
	'F5': ('F5', 116),
	'F6': ('F6', 117),
	'F7': ('F7', 118),
	'F8': ('F8', 119),
	'F9': ('F9', 120),
	'F10': ('F10', 121),
	'F11': ('F11', 122),
	'F12': ('F12', 123),
	'F13': ('F13', 124),
	'F14': ('F14', 125),
	'F15': ('F15', 126),
	'F16': ('F16', 127),
	'F17': ('F17', 128),
	'F18': ('F18', 129),
	'F19': ('F19', 130),
	'F20': ('F20', 131),
	'F21': ('F21', 132),
	'F22': ('F22', 133),
	'F23': ('F23', 134),
	'F24': ('F24', 135),
	# Numpad keys
	'NumLock': ('NumLock', 144),
	'Numpad0': ('Numpad0', 96),
	'Numpad1': ('Numpad1', 97),
	'Numpad2': ('Numpad2', 98),
	'Numpad3': ('Numpad3', 99),
	'Numpad4': ('Numpad4', 100),
	'Numpad5': ('Numpad5', 101),
	'Numpad6': ('Numpad6', 102),
	'Numpad7': ('Numpad7', 103),
	'Numpad8': ('Numpad8', 104),
	'Numpad9': ('Numpad9', 105),
	'NumpadMultiply': ('NumpadMultiply', 106),
	'NumpadAdd': ('NumpadAdd', 107),
	'NumpadSubtract': ('NumpadSubtract', 109),
	'NumpadDecimal': ('NumpadDecimal', 110),
	'NumpadDivide': ('NumpadDivide', 111),
	# Lock keys
	'CapsLock': ('CapsLock', 20),
	'ScrollLock': ('ScrollLock', 145),
	# OEM/Punctuation keys (US keyboard layout)
	'Semicolon': ('Semicolon', 186),
	';': ('Semicolon', 186),
	'Equal': ('Equal', 187),
	'=': ('Equal', 187),
	'Comma': ('Comma', 188),
	',': ('Comma', 188),
	'Minus': ('Minus', 189),
	'-': ('Minus', 189),
	'Period': ('Period', 190),
	'.': ('Period', 190),
	'Slash': ('Slash', 191),
	'/': ('Slash', 191),
	'Backquote': ('Backquote', 192),
	'`': ('Backquote', 192),
	'BracketLeft': ('BracketLeft', 219),
	'[': ('BracketLeft', 219),
	'Backslash': ('Backslash', 220),
	'\\': ('Backslash', 220),
	'BracketRight': ('BracketRight', 221),
	']': ('BracketRight', 221),
	'Quote': ('Quote', 222),
	"'": ('Quote', 222),
	# Media/Browser keys
	'AudioVolumeMute': ('AudioVolumeMute', 173),
	'AudioVolumeDown': ('AudioVolumeDown', 174),
	'AudioVolumeUp': ('AudioVolumeUp', 175),
	'MediaTrackNext': ('MediaTrackNext', 176),
	'MediaTrackPrevious': ('MediaTrackPrevious', 177),
	'MediaStop': ('MediaStop', 178),
	'MediaPlayPause': ('MediaPlayPause', 179),
	'BrowserBack': ('BrowserBack', 166),
	'BrowserForward': ('BrowserForward', 167),
	'BrowserRefresh': ('BrowserRefresh', 168),
	'BrowserStop': ('BrowserStop', 169),
	'BrowserSearch': ('BrowserSearch', 170),
	'BrowserFavorites': ('BrowserFavorites', 171),
	'BrowserHome': ('BrowserHome', 172),
	# Additional common keys
	'Clear': ('Clear', 12),
	'Pause': ('Pause', 19),
	'Select': ('Select', 41),
	'Print': ('Print', 42),
	'Execute': ('Execute', 43),
	'PrintScreen': ('PrintScreen', 44),
	'Help': ('Help', 47),
	'ContextMenu': ('ContextMenu', 93),
}


class Utils:
	"""Utility functions for actor operations.
	
	Performance optimizations:
	- Uses module-level constant key map
	- __slots__ to prevent instance dict creation
	"""
	
	__slots__ = ()

	@staticmethod
	def get_key_info(key: str) -> tuple[str, int | None]:
		"""Get the code and windowsVirtualKeyCode for a key.

		Args:
			key: Key name (e.g., 'Enter', 'ArrowUp', 'a', 'A')

		Returns:
			Tuple of (code, windowsVirtualKeyCode)
		"""
		# Fast path: check module-level constant map
		if key in _KEY_MAP:
			return _KEY_MAP[key]

		# Handle alphanumeric keys dynamically
		if len(key) == 1:
			if key.isalpha():
				# Letter keys: A-Z have VK codes 65-90
				return (f'Key{key.upper()}', ord(key.upper()))
			elif key.isdigit():
				# Digit keys: 0-9 have VK codes 48-57 (same as ASCII)
				return (f'Digit{key}', ord(key))

		# Fallback: use the key name as code, no virtual key code
		return (key, None)


def get_key_info(key: str) -> tuple[str, int | None]:
	"""Get the code and windowsVirtualKeyCode for a key.

	Args:
		key: Key name (e.g., 'Enter', 'ArrowUp', 'a', 'A')

	Returns:
		Tuple of (code, windowsVirtualKeyCode)

	Reference: Windows Virtual Key Codes
	https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
	"""
	# Fast path: check module-level constant map
	if key in _KEY_MAP:
		return _KEY_MAP[key]

	# Handle alphanumeric keys dynamically
	if len(key) == 1:
		if key.isalpha():
			return (f'Key{key.upper()}', ord(key.upper()))
		elif key.isdigit():
			return (f'Digit{key}', ord(key))

	return (key, None)
