/*
 * Copyright (C) 2026 Fluxer Contributors
 *
 * This file is part of Fluxer.
 *
 * Fluxer is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Fluxer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
 */

export const UiohookKeycode = {
	Escape: 1,
	F1: 59,
	F2: 60,
	F3: 61,
	F4: 62,
	F5: 63,
	F6: 64,
	F7: 65,
	F8: 66,
	F9: 67,
	F10: 68,
	F11: 87,
	F12: 88,
	F13: 91,
	F14: 92,
	F15: 93,
	F16: 99,
	F17: 100,
	F18: 101,
	F19: 102,
	F20: 103,
	F21: 104,
	F22: 105,
	F23: 106,
	F24: 107,

	Backquote: 41,
	Digit1: 2,
	Digit2: 3,
	Digit3: 4,
	Digit4: 5,
	Digit5: 6,
	Digit6: 7,
	Digit7: 8,
	Digit8: 9,
	Digit9: 10,
	Digit0: 11,
	Minus: 12,
	Equal: 13,
	Backspace: 14,

	Tab: 15,
	KeyQ: 16,
	KeyW: 17,
	KeyE: 18,
	KeyR: 19,
	KeyT: 20,
	KeyY: 21,
	KeyU: 22,
	KeyI: 23,
	KeyO: 24,
	KeyP: 25,
	BracketLeft: 26,
	BracketRight: 27,
	Backslash: 43,

	CapsLock: 58,
	KeyA: 30,
	KeyS: 31,
	KeyD: 32,
	KeyF: 33,
	KeyG: 34,
	KeyH: 35,
	KeyJ: 36,
	KeyK: 37,
	KeyL: 38,
	Semicolon: 39,
	Quote: 40,
	Enter: 28,

	ShiftLeft: 42,
	KeyZ: 44,
	KeyX: 45,
	KeyC: 46,
	KeyV: 47,
	KeyB: 48,
	KeyN: 49,
	KeyM: 50,
	Comma: 51,
	Period: 52,
	Slash: 53,
	ShiftRight: 54,

	ControlLeft: 29,
	MetaLeft: 3675,
	AltLeft: 56,
	Space: 57,
	AltRight: 3640,
	MetaRight: 3676,
	ControlRight: 3613,

	PrintScreen: 3639,
	ScrollLock: 70,
	Pause: 3653,
	Insert: 57426,
	Delete: 57427,
	Home: 57415,
	End: 57423,
	PageUp: 57417,
	PageDown: 57425,

	ArrowUp: 57416,
	ArrowLeft: 57419,
	ArrowDown: 57424,
	ArrowRight: 57421,

	NumLock: 69,
	NumpadDivide: 3637,
	NumpadMultiply: 55,
	NumpadSubtract: 74,
	NumpadAdd: 78,
	NumpadEnter: 3612,
	NumpadDecimal: 83,
	Numpad0: 82,
	Numpad1: 79,
	Numpad2: 80,
	Numpad3: 81,
	Numpad4: 75,
	Numpad5: 76,
	Numpad6: 77,
	Numpad7: 71,
	Numpad8: 72,
	Numpad9: 73,

	AudioVolumeMute: 57376,
	AudioVolumeDown: 57390,
	AudioVolumeUp: 57392,
	MediaPlayPause: 57378,
	MediaStop: 57380,
	MediaTrackPrevious: 57360,
	MediaTrackNext: 57369,
} as const;

const jsToUiohookMap: Record<string, number> = {
	Escape: UiohookKeycode.Escape,
	F1: UiohookKeycode.F1,
	F2: UiohookKeycode.F2,
	F3: UiohookKeycode.F3,
	F4: UiohookKeycode.F4,
	F5: UiohookKeycode.F5,
	F6: UiohookKeycode.F6,
	F7: UiohookKeycode.F7,
	F8: UiohookKeycode.F8,
	F9: UiohookKeycode.F9,
	F10: UiohookKeycode.F10,
	F11: UiohookKeycode.F11,
	F12: UiohookKeycode.F12,
	Backquote: UiohookKeycode.Backquote,
	Digit1: UiohookKeycode.Digit1,
	Digit2: UiohookKeycode.Digit2,
	Digit3: UiohookKeycode.Digit3,
	Digit4: UiohookKeycode.Digit4,
	Digit5: UiohookKeycode.Digit5,
	Digit6: UiohookKeycode.Digit6,
	Digit7: UiohookKeycode.Digit7,
	Digit8: UiohookKeycode.Digit8,
	Digit9: UiohookKeycode.Digit9,
	Digit0: UiohookKeycode.Digit0,
	Minus: UiohookKeycode.Minus,
	Equal: UiohookKeycode.Equal,
	Backspace: UiohookKeycode.Backspace,
	Tab: UiohookKeycode.Tab,
	KeyQ: UiohookKeycode.KeyQ,
	KeyW: UiohookKeycode.KeyW,
	KeyE: UiohookKeycode.KeyE,
	KeyR: UiohookKeycode.KeyR,
	KeyT: UiohookKeycode.KeyT,
	KeyY: UiohookKeycode.KeyY,
	KeyU: UiohookKeycode.KeyU,
	KeyI: UiohookKeycode.KeyI,
	KeyO: UiohookKeycode.KeyO,
	KeyP: UiohookKeycode.KeyP,
	BracketLeft: UiohookKeycode.BracketLeft,
	BracketRight: UiohookKeycode.BracketRight,
	Backslash: UiohookKeycode.Backslash,
	CapsLock: UiohookKeycode.CapsLock,
	KeyA: UiohookKeycode.KeyA,
	KeyS: UiohookKeycode.KeyS,
	KeyD: UiohookKeycode.KeyD,
	KeyF: UiohookKeycode.KeyF,
	KeyG: UiohookKeycode.KeyG,
	KeyH: UiohookKeycode.KeyH,
	KeyJ: UiohookKeycode.KeyJ,
	KeyK: UiohookKeycode.KeyK,
	KeyL: UiohookKeycode.KeyL,
	Semicolon: UiohookKeycode.Semicolon,
	Quote: UiohookKeycode.Quote,
	Enter: UiohookKeycode.Enter,
	ShiftLeft: UiohookKeycode.ShiftLeft,
	KeyZ: UiohookKeycode.KeyZ,
	KeyX: UiohookKeycode.KeyX,
	KeyC: UiohookKeycode.KeyC,
	KeyV: UiohookKeycode.KeyV,
	KeyB: UiohookKeycode.KeyB,
	KeyN: UiohookKeycode.KeyN,
	KeyM: UiohookKeycode.KeyM,
	Comma: UiohookKeycode.Comma,
	Period: UiohookKeycode.Period,
	Slash: UiohookKeycode.Slash,
	ShiftRight: UiohookKeycode.ShiftRight,
	ControlLeft: UiohookKeycode.ControlLeft,
	MetaLeft: UiohookKeycode.MetaLeft,
	AltLeft: UiohookKeycode.AltLeft,
	Space: UiohookKeycode.Space,
	AltRight: UiohookKeycode.AltRight,
	MetaRight: UiohookKeycode.MetaRight,
	ControlRight: UiohookKeycode.ControlRight,
	ArrowUp: UiohookKeycode.ArrowUp,
	ArrowLeft: UiohookKeycode.ArrowLeft,
	ArrowDown: UiohookKeycode.ArrowDown,
	ArrowRight: UiohookKeycode.ArrowRight,
	Insert: UiohookKeycode.Insert,
	Delete: UiohookKeycode.Delete,
	Home: UiohookKeycode.Home,
	End: UiohookKeycode.End,
	PageUp: UiohookKeycode.PageUp,
	PageDown: UiohookKeycode.PageDown,
	NumLock: UiohookKeycode.NumLock,
	NumpadDivide: UiohookKeycode.NumpadDivide,
	NumpadMultiply: UiohookKeycode.NumpadMultiply,
	NumpadSubtract: UiohookKeycode.NumpadSubtract,
	NumpadAdd: UiohookKeycode.NumpadAdd,
	NumpadEnter: UiohookKeycode.NumpadEnter,
	NumpadDecimal: UiohookKeycode.NumpadDecimal,
	Numpad0: UiohookKeycode.Numpad0,
	Numpad1: UiohookKeycode.Numpad1,
	Numpad2: UiohookKeycode.Numpad2,
	Numpad3: UiohookKeycode.Numpad3,
	Numpad4: UiohookKeycode.Numpad4,
	Numpad5: UiohookKeycode.Numpad5,
	Numpad6: UiohookKeycode.Numpad6,
	Numpad7: UiohookKeycode.Numpad7,
	Numpad8: UiohookKeycode.Numpad8,
	Numpad9: UiohookKeycode.Numpad9,
	' ': UiohookKeycode.Space,
	'1': UiohookKeycode.Digit1,
	'2': UiohookKeycode.Digit2,
	'3': UiohookKeycode.Digit3,
	'4': UiohookKeycode.Digit4,
	'5': UiohookKeycode.Digit5,
	'6': UiohookKeycode.Digit6,
	'7': UiohookKeycode.Digit7,
	'8': UiohookKeycode.Digit8,
	'9': UiohookKeycode.Digit9,
	'0': UiohookKeycode.Digit0,
	Q: UiohookKeycode.KeyQ,
	W: UiohookKeycode.KeyW,
	E: UiohookKeycode.KeyE,
	R: UiohookKeycode.KeyR,
	T: UiohookKeycode.KeyT,
	Y: UiohookKeycode.KeyY,
	U: UiohookKeycode.KeyU,
	I: UiohookKeycode.KeyI,
	O: UiohookKeycode.KeyO,
	P: UiohookKeycode.KeyP,
	A: UiohookKeycode.KeyA,
	S: UiohookKeycode.KeyS,
	D: UiohookKeycode.KeyD,
	F: UiohookKeycode.KeyF,
	G: UiohookKeycode.KeyG,
	H: UiohookKeycode.KeyH,
	J: UiohookKeycode.KeyJ,
	K: UiohookKeycode.KeyK,
	L: UiohookKeycode.KeyL,
	Z: UiohookKeycode.KeyZ,
	X: UiohookKeycode.KeyX,
	C: UiohookKeycode.KeyC,
	V: UiohookKeycode.KeyV,
	B: UiohookKeycode.KeyB,
	N: UiohookKeycode.KeyN,
	M: UiohookKeycode.KeyM,
	q: UiohookKeycode.KeyQ,
	w: UiohookKeycode.KeyW,
	e: UiohookKeycode.KeyE,
	r: UiohookKeycode.KeyR,
	t: UiohookKeycode.KeyT,
	y: UiohookKeycode.KeyY,
	u: UiohookKeycode.KeyU,
	i: UiohookKeycode.KeyI,
	o: UiohookKeycode.KeyO,
	p: UiohookKeycode.KeyP,
	a: UiohookKeycode.KeyA,
	s: UiohookKeycode.KeyS,
	d: UiohookKeycode.KeyD,
	f: UiohookKeycode.KeyF,
	g: UiohookKeycode.KeyG,
	h: UiohookKeycode.KeyH,
	j: UiohookKeycode.KeyJ,
	k: UiohookKeycode.KeyK,
	l: UiohookKeycode.KeyL,
	z: UiohookKeycode.KeyZ,
	x: UiohookKeycode.KeyX,
	c: UiohookKeycode.KeyC,
	v: UiohookKeycode.KeyV,
	b: UiohookKeycode.KeyB,
	n: UiohookKeycode.KeyN,
	m: UiohookKeycode.KeyM,
};

export function jsKeyToUiohookKeycode(keyNameOrCode: string | undefined): number | null {
	if (!keyNameOrCode) return null;

	if (keyNameOrCode in jsToUiohookMap) {
		return jsToUiohookMap[keyNameOrCode] ?? null;
	}

	const upper = keyNameOrCode.toUpperCase();
	if (upper in jsToUiohookMap) {
		return jsToUiohookMap[upper] ?? null;
	}

	return null;
}
