/**
 * jsdom implements no `CSS` interface at all, and React Aria's collection code
 * calls `CSS.escape` unguarded when it looks an item up by key
 * (`react-aria/dist/private/selection/utils.mjs:22`). Without this, opening a
 * RAC Select or moving between RAC Tabs throws in tests but works in a browser.
 *
 * The implementation is CSSOM's `serialize an identifier` algorithm
 * (https://drafts.csswg.org/cssom/#serialize-an-identifier), not an
 * approximation: a wrong escape would silently break the key lookups instead of
 * failing loudly.
 */

function escapeIdentifier(value: string): string {
	let result = "";
	for (let index = 0; index < value.length; index += 1) {
		const code = value.charCodeAt(index);
		const char = value[index]!;
		if (code === 0x0000) {
			result += "�";
		} else if (
			(code >= 0x0001 && code <= 0x001f) ||
			code === 0x007f ||
			(index === 0 && code >= 0x0030 && code <= 0x0039) ||
			(index === 1 && code >= 0x0030 && code <= 0x0039 && value.charCodeAt(0) === 0x002d)
		) {
			result += `\\${code.toString(16)} `;
		} else if (index === 0 && code === 0x002d && value.length === 1) {
			result += `\\${char}`;
		} else if (
			code >= 0x0080 ||
			code === 0x002d ||
			code === 0x005f ||
			(code >= 0x0030 && code <= 0x0039) ||
			(code >= 0x0041 && code <= 0x005a) ||
			(code >= 0x0061 && code <= 0x007a)
		) {
			result += char;
		} else {
			result += `\\${char}`;
		}
	}
	return result;
}

if (globalThis.CSS === undefined) {
	Object.defineProperty(globalThis, "CSS", { value: { escape: escapeIdentifier }, configurable: true });
} else if (typeof globalThis.CSS.escape !== "function") {
	globalThis.CSS.escape = escapeIdentifier;
}
