import { font, CHAR } from "./font.ts";

const keyboard = new Map<number, {first: boolean, repeat: boolean, held: boolean}>();

export const K = {
	ESCAPE: 256,
	ENTER: 257,
	TAB: 258,
	BACKSPACE: 259,
	INSERT: 260,
	DELETE: 261,
	ARROW_RIGHT: 262,
	ARROW_LEFT: 263,
	ARROW_DOWN: 264,
	ARROW_UP: 265,
	PAGE_UP: 266,
	PAGE_DOWN: 267,
	HOME: 268,
	END: 269,
	CAPS_LOCK: 280,
	F1: 290,
	F2: 291,
	F3: 292,
	F4: 293,
	F5: 294,
	F6: 295,
	F7: 296,
	F8: 297,
	F9: 298,
	F10: 299,
	F11: 300,
	F12: 301,
	SHIFT_LEFT: 340,
	CTRL_LEFT: 341,
	ALT_LEFT: 342,
	SHIFT_RIGHT: 344,
	CTRL_RIGHT: 345,
	ALT_RIGHT: 346,
}

export const shiftMap = {
	"1": "!",
	"2": "@",
	"3": "#",
	"4": "$",
	"5": "%",
	"6": "^",
	"7": "&",
	"8": "*",
	"9": "(",
	"0": ")",
	"`": "~",
	"-": "_",
	"=": "+",
	"[": "{",
	"]": "}",
	"\\": "|",
	";": ":",
	"'": '"',
	",": "<",
	".": ">",
	"/": "?",
}

export const altMap = {
	"w": CHAR.UP,
	"a": CHAR.LEFT,
	"s": CHAR.DOWN,
	"d": CHAR.RIGHT,
	"p": CHAR.PI,
}

addEventListener("keydown", (evt) => {
	// console.log("keydown", evt.key, evt.key.charCodeAt(0));
	const key = evt.key.charCodeAt(0);
	const isRepeat = keyboard.has(key) && keyboard.get(key)?.held!;
	keyboard.set(key, {
		first: !isRepeat,
		repeat: isRepeat,
		held: true,
	});
});

addEventListener("keyup", (evt) => {
	// console.log("keyup", evt.key, evt.key.charCodeAt(0));
	const key = evt.key.charCodeAt(0);
	keyboard.set(key, {
		first: false,
		repeat: false,
		held: false,
	});
});

export const refreshKeyboard = () => {
	keyboard.forEach(({held}, key) => {
		if (!held) {
			keyboard.delete(key);
		} else {
			keyboard.set(key, {
				first: false,
				repeat: false,
				held: true,
			});
		}
	})
}

export const keyPressed = (key: string | number) => {
	if (typeof key === "string") {
		key = key.toUpperCase().charCodeAt(0);
	}
	return keyboard.has(key) && (keyboard.get(key)?.first! || keyboard.get(key)?.repeat!);
}

export const keyDown = (key: string | number) => {
	if (typeof key === "string") {
		key = key.toUpperCase().charCodeAt(0);
	}
	return keyboard.has(key) && keyboard.get(key)?.held!;
}

export const shiftKeyDown = () => {
	return keyDown(K.SHIFT_LEFT) || keyDown(K.SHIFT_RIGHT);
}

export const ctrlKeyDown = () => {
	return keyDown(K.CTRL_LEFT) || keyDown(K.CTRL_RIGHT);
}

export const altKeyDown = () => {
	return keyDown(K.ALT_LEFT) || keyDown(K.ALT_RIGHT);
}

export const keyReleased = (key: string | number) => {
	if (typeof key === "string") {
		key = key.toUpperCase().charCodeAt(0);
	}
	return keyboard.has(key) && !keyboard.get(key)?.held!;
}

export const getKeysPressed = () => {
	const result = [...keyboard.entries()].filter(([_key, value]) => {
		return value.first || value.repeat;
	}).map(([key]) => key);
	return result;
}

export const getKeyboardString = () => {
	let str = "";
	if (ctrlKeyDown()) {
		return str;
	}
	for (const key of getKeysPressed()) {
		let char = String.fromCharCode(key).toLowerCase();
		if (shiftKeyDown()) {
			if (char in shiftMap) {
				char = shiftMap[char as keyof typeof shiftMap];
			} else {
				char = char.toUpperCase();
			}
		}
		if (altKeyDown()) {
			if (char in altMap) {
				char = altMap[char as keyof typeof altMap];
			} else {
				char = char.toUpperCase();
			}
		}
		if (char in font.chars) {
			str += char;
		}
	}
	return str;
}