package rdp

// RDP mouse event flags — these match the MS-RDPBCGR specification.
const (
	MouseFlagMove    uint32 = 0x0800 // Mouse moved (no button change)
	MouseFlagButton1 uint32 = 0x1000 // Left button
	MouseFlagButton2 uint32 = 0x2000 // Right button
	MouseFlagButton3 uint32 = 0x4000 // Middle button
	MouseFlagDown    uint32 = 0x8000 // Button pressed (absence = released)

	// Extended mouse flags for wheel events
	MouseFlagWheel     uint32 = 0x0200 // Vertical wheel rotation
	MouseFlagWheelNeg  uint32 = 0x0100 // Negative wheel direction (scroll down)
	MouseFlagHWheel    uint32 = 0x0400 // Horizontal wheel rotation
)

// ScancodeMap maps JavaScript KeyboardEvent.code strings to RDP hardware
// scancodes (Set 1 / XT scan codes). This covers the standard US 104-key
// layout. Extended keys (those with a 0xE0 prefix on the wire) have the
// high byte set to 0xE0.
//
// Reference: USB HID to PS/2 scancode mapping + MS-RDPBCGR 2.2.8.1.1.3.1.1.1
var ScancodeMap = map[string]uint32{
	// ── Row 0: Escape + Function keys ──────────────────────────────
	"Escape":      0x0001,
	"F1":          0x003B,
	"F2":          0x003C,
	"F3":          0x003D,
	"F4":          0x003E,
	"F5":          0x003F,
	"F6":          0x0040,
	"F7":          0x0041,
	"F8":          0x0042,
	"F9":          0x0043,
	"F10":         0x0044,
	"F11":         0x0057,
	"F12":         0x0058,

	// ── Row 1: Number row ──────────────────────────────────────────
	"Backquote":   0x0029, // ` ~
	"Digit1":      0x0002,
	"Digit2":      0x0003,
	"Digit3":      0x0004,
	"Digit4":      0x0005,
	"Digit5":      0x0006,
	"Digit6":      0x0007,
	"Digit7":      0x0008,
	"Digit8":      0x0009,
	"Digit9":      0x000A,
	"Digit0":      0x000B,
	"Minus":       0x000C, // - _
	"Equal":       0x000D, // = +
	"Backspace":   0x000E,

	// ── Row 2: QWERTY row ─────────────────────────────────────────
	"Tab":         0x000F,
	"KeyQ":        0x0010,
	"KeyW":        0x0011,
	"KeyE":        0x0012,
	"KeyR":        0x0013,
	"KeyT":        0x0014,
	"KeyY":        0x0015,
	"KeyU":        0x0016,
	"KeyI":        0x0017,
	"KeyO":        0x0018,
	"KeyP":        0x0019,
	"BracketLeft": 0x001A, // [ {
	"BracketRight":0x001B, // ] }
	"Backslash":   0x002B, // \ |

	// ── Row 3: Home row ───────────────────────────────────────────
	"CapsLock":    0x003A,
	"KeyA":        0x001E,
	"KeyS":        0x001F,
	"KeyD":        0x0020,
	"KeyF":        0x0021,
	"KeyG":        0x0022,
	"KeyH":        0x0023,
	"KeyJ":        0x0024,
	"KeyK":        0x0025,
	"KeyL":        0x0026,
	"Semicolon":   0x0027, // ; :
	"Quote":       0x0028, // ' "
	"Enter":       0x001C,

	// ── Row 4: Bottom row ─────────────────────────────────────────
	"ShiftLeft":   0x002A,
	"KeyZ":        0x002C,
	"KeyX":        0x002D,
	"KeyC":        0x002E,
	"KeyV":        0x002F,
	"KeyB":        0x0030,
	"KeyN":        0x0031,
	"KeyM":        0x0032,
	"Comma":       0x0033, // , <
	"Period":      0x0034, // . >
	"Slash":       0x0035, // / ?
	"ShiftRight":  0x0036,

	// ── Row 5: Bottom modifiers + space ───────────────────────────
	"ControlLeft":  0x001D,
	"MetaLeft":     0xE05B, // Left Windows / Super
	"AltLeft":      0x0038,
	"Space":        0x0039,
	"AltRight":     0xE038, // Right Alt (extended)
	"MetaRight":    0xE05C, // Right Windows / Super
	"ContextMenu":  0xE05D, // Application / Menu key
	"ControlRight": 0xE01D, // Right Ctrl (extended)

	// ── Navigation cluster ────────────────────────────────────────
	"PrintScreen":  0xE037,
	"ScrollLock":   0x0046,
	"Pause":        0x0045, // Note: Pause has special handling on wire
	"Insert":       0xE052,
	"Home":         0xE047,
	"PageUp":       0xE049,
	"Delete":       0xE053,
	"End":          0xE04F,
	"PageDown":     0xE051,

	// ── Arrow keys ────────────────────────────────────────────────
	"ArrowUp":      0xE048,
	"ArrowLeft":    0xE04B,
	"ArrowDown":    0xE050,
	"ArrowRight":   0xE04D,

	// ── Numpad ────────────────────────────────────────────────────
	"NumLock":       0x0045,
	"NumpadDivide":  0xE035,
	"NumpadMultiply":0x0037,
	"NumpadSubtract":0x004A,
	"Numpad7":       0x0047,
	"Numpad8":       0x0048,
	"Numpad9":       0x0049,
	"NumpadAdd":     0x004E,
	"Numpad4":       0x004B,
	"Numpad5":       0x004C,
	"Numpad6":       0x004D,
	"Numpad1":       0x004F,
	"Numpad2":       0x0050,
	"Numpad3":       0x0051,
	"NumpadEnter":   0xE01C,
	"Numpad0":       0x0052,
	"NumpadDecimal": 0x0053,

	// ── Multimedia / browser keys (common on 104+ key layouts) ───
	"BrowserBack":    0xE06A,
	"BrowserForward": 0xE069,
	"BrowserRefresh": 0xE067,
	"BrowserStop":    0xE068,
	"BrowserSearch":  0xE065,
	"BrowserFavorites":0xE066,
	"BrowserHome":    0xE032,
	"VolumeMute":     0xE020,
	"VolumeDown":     0xE02E,
	"VolumeUp":       0xE030,
	"MediaTrackNext": 0xE019,
	"MediaTrackPrevious":0xE010,
	"MediaStop":      0xE024,
	"MediaPlayPause": 0xE022,
	"LaunchMail":     0xE06C,
	"LaunchApp1":     0xE06B,
	"LaunchApp2":     0xE021,

	// ── International keys ────────────────────────────────────────
	"IntlBackslash": 0x0056, // key between left Shift and Z on ISO keyboards
	"IntlYen":       0x007D, // Yen key on Japanese keyboards
	"IntlRo":        0x0073, // Ro key on Japanese keyboards
}

// JSKeyToScancode translates a JavaScript KeyboardEvent.code string to an
// RDP hardware scancode. Returns the scancode and true if a mapping exists,
// or 0 and false for unmapped keys.
func JSKeyToScancode(jsCode string) (uint32, bool) {
	sc, ok := ScancodeMap[jsCode]
	return sc, ok
}

// IsExtendedKey returns true if the scancode has the 0xE0 extended prefix.
// Extended keys require a two-byte sequence on the RDP wire.
func IsExtendedKey(scancode uint32) bool {
	return (scancode & 0xFF00) == 0xE000
}

// ScancodeValue returns the low byte of the scancode (the actual scan code
// value without the extended prefix).
func ScancodeValue(scancode uint32) uint8 {
	return uint8(scancode & 0xFF)
}
