const initializedRoots = new WeakSet();
let keyboardDismissInitialized = false;

function closeNode(node) {
	node.classList.remove("is-open");
	node.querySelectorAll("[aria-expanded='true']").forEach(trigger => {
		trigger.setAttribute("aria-expanded", "false");
	});
}

function closeAll(except = null) {
	document.querySelectorAll(".dropdown.is-open, .popover.is-open, .tooltip.is-open").forEach(node => {
		if(node !== except) {
			closeNode(node);
		}
	});
}

function initDropdowns(root = document) {
	root.addEventListener("click", event => {
		const trigger = event.target.closest("[data-dropdown-toggle]");

		if(!trigger) {
			return;
		}

		const dropdown = trigger.closest(".dropdown");

		if(!dropdown) {
			return;
		}

		event.preventDefault();
		const isOpen = dropdown.classList.contains("is-open");
		closeAll(dropdown);
		dropdown.classList.toggle("is-open", !isOpen);
		trigger.setAttribute("aria-expanded", String(!isOpen));
	});
}

function initPopovers(root = document) {
	root.addEventListener("click", event => {
		const trigger = event.target.closest("[data-popover-toggle]");

		if(!trigger) {
			return;
		}

		const popover = trigger.closest(".popover");

		if(!popover) {
			return;
		}

		event.preventDefault();
		const isOpen = popover.classList.contains("is-open");
		closeAll(popover);
		popover.classList.toggle("is-open", !isOpen);
		trigger.setAttribute("aria-expanded", String(!isOpen));
	});
}

function initTooltips(root = document) {
	root.addEventListener("click", event => {
		const trigger = event.target.closest("[data-tooltip-toggle]");

		if(!trigger) {
			return;
		}

		const tooltip = trigger.closest(".tooltip");

		if(!tooltip) {
			return;
		}

		event.preventDefault();
		const isOpen = tooltip.classList.contains("is-open");
		closeAll(tooltip);
		tooltip.classList.toggle("is-open", !isOpen);
	});
}

function initDismiss(root = document) {
	root.addEventListener("click", event => {
		if(event.target.closest(".dropdown, .popover, .tooltip")) {
			return;
		}

		closeAll();
	});

	if(!keyboardDismissInitialized) {
		document.addEventListener("keydown", event => {
			if(event.key === "Escape") {
				closeAll();
			}
		});

		keyboardDismissInitialized = true;
	}
}

function init(root = document) {
	if(initializedRoots.has(root)) {
		return;
	}

	initDropdowns(root);
	initPopovers(root);
	initTooltips(root);
	initDismiss(root);
	initializedRoots.add(root);
}

export default {
	init,
	closeAll
};
