import * as React from 'react';
import { useEffect, useState, useRef, useCallback } from 'react';
import { isInsideContainer } from '@joplin/lib/dom';

type OnButtonClick = ()=> void;
interface Props {
	onOkButtonClick: null|OnButtonClick;
	onCancelButtonClick: null|OnButtonClick;
}

const globalKeydownHandlers: string[] = [];

export default (props: Props) => {
	const [elementId] = useState(`${Math.round(Math.random() * 10000000)}`);
	const globalKeydownHandlersRef = useRef(globalKeydownHandlers);

	useEffect(() => {
		globalKeydownHandlersRef.current.push(elementId);
		return () => {
			const idx = globalKeydownHandlersRef.current.findIndex(e => e === elementId);
			// eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied
			globalKeydownHandlersRef.current.splice(idx, 1);
		};
		// eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied
	}, []);

	const isTopDialog = () => {
		const ln = globalKeydownHandlersRef.current.length;
		return ln && globalKeydownHandlersRef.current[ln - 1] === elementId;
	};

	// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
	const isInSubModal = (targetElement: any) => {
		// If we are inside a sub-modal within the dialog, we shouldn't handle
		// global key events. It can be for example the emoji picker. In general
		// it's difficult to know whether an element is a modal or not, so we'll
		// have to add special cases here. Normally there shouldn't be many of
		// these.
		if (isInsideContainer(targetElement, 'emoji-picker')) return true;
		return false;
	};

	const onKeyDown = useCallback((event: KeyboardEvent|React.KeyboardEvent) => {
		// Early exit if it's neither ENTER nor ESCAPE, because isInSubModal
		// function can be costly.
		if (event.keyCode !== 13 && event.keyCode !== 27) return;

		if (!isTopDialog() || isInSubModal(event.target)) return;

		if (event.keyCode === 13 && props.onOkButtonClick) {
			if ('nodeName' in event.target && event.target.nodeName === 'INPUT') {
				const target = event.target as HTMLInputElement;

				if (target.type !== 'button' && target.type !== 'checkbox') {
					event.preventDefault();
					props.onOkButtonClick();
				}
			}
		} else if (event.keyCode === 27 && props.onCancelButtonClick) {
			event.preventDefault();
			props.onCancelButtonClick();
		}
		// eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied
	}, [props.onOkButtonClick, props.onCancelButtonClick]);

	useEffect(() => {
		document.addEventListener('keydown', onKeyDown);
		return () => {
			document.removeEventListener('keydown', onKeyDown);
		};
	}, [onKeyDown]);

	return onKeyDown;
};
