/**
 * @license Copyright (c) 2017-2025, CKSource Holding sp. z o.o. All rights reserved.
 * For licensing, see LICENSE.md.
 */

const ON_ESCAPE_CALLBACK_STACK = new Set();
let globalEscapeHandler = null;

/**
 * Executes a callback when the Escape key is pressed.
 *
 * This function follows the UI layering pattern where pressing Escape
 * only closes the topmost layer (like modals, dropdowns, or overlays).
 * The most recently added callback is considered to be associated with
 * the topmost UI layer and will be the only one executed.
 *
 * @param callback - The function to execute on Escape key press when it's the most recent addition.
 * @returns A function that removes the event listener when called.
 */
export function onEscapeKeyPress( callback ) {
	if ( typeof callback !== 'function' ) {
		throw new Error( 'Callback must be a function' );
	}

	// Global escape key handler (defined once)
	if ( !globalEscapeHandler ) {
		globalEscapeHandler = event => {
			if ( event.key === 'Escape' || event.keyCode === 27 ) {
				// Get the latest callback from the stack (if any)
				const latestCallback = Array.from( ON_ESCAPE_CALLBACK_STACK ).pop();

				if ( latestCallback ) {
					latestCallback();

					// Remove the executed callback
					ON_ESCAPE_CALLBACK_STACK.delete( latestCallback );
				}
			}
		};

		document.addEventListener( 'keydown', globalEscapeHandler );
	}

	// Add the callback to the stack
	ON_ESCAPE_CALLBACK_STACK.add( callback );

	function unmount() {
		ON_ESCAPE_CALLBACK_STACK.delete( callback );

		// If stack is empty, remove the global handler
		if ( ON_ESCAPE_CALLBACK_STACK.size === 0 && globalEscapeHandler ) {
			document.removeEventListener( 'keydown', globalEscapeHandler );
			globalEscapeHandler = null;
		}
	}

	// Return a function to remove the callback if needed
	return unmount;
}
