const isRtl = () => document.querySelector('html').dir === 'rtl'

const isEligibleForSubmenu = (el) =>
	el.classList.contains('animated-submenu') &&
	(!el.parentNode.classList.contains('menu') ||
		(el.className.indexOf('ct-mega-menu') === -1 &&
			el.parentNode.classList.contains('menu')))

const getAllParents = (a) => {
	var els = []

	while (a) {
		els.unshift(a)
		a = a.parentNode
	}

	return els
}

function furthest(el, s) {
	var nodes = []

	while (el.parentNode) {
		if (
			el.parentNode &&
			el.parentNode.matches &&
			el.parentNode.matches(s)
		) {
			nodes.push(el.parentNode)
		}

		el = el.parentNode
	}

	return nodes[nodes.length - 1]
}

const getPreferedPlacementFor = (el) => {
	const farmost = furthest(el, 'li.menu-item')

	if (!farmost) {
		return isRtl() ? 'left' : 'right'
	}

	if (!farmost.querySelector('.sub-menu .sub-menu .sub-menu')) {
		return isRtl() ? 'left' : 'right'
	}

	return farmost.getBoundingClientRect().left > innerWidth / 2
		? 'left'
		: 'right'
}

const computeItemSubmenuFor = (
	reference,
	{
		// left -- 1st level menu items
		// end  -- submenus
		startPosition = 'end',
	}
) => {
	const menu = reference.querySelector('.sub-menu')
	const placement = getPreferedPlacementFor(menu)

	const { left, width, right } = menu.getBoundingClientRect()

	let futurePlacement = placement
	let referenceRect = reference.getBoundingClientRect()

	if (placement === 'left') {
		let referencePoint =
			startPosition === 'end' ? referenceRect.left : referenceRect.right

		if (referencePoint - width < 0) {
			futurePlacement = 'right'
		}
	}

	if (placement === 'right') {
		let referencePoint =
			startPosition === 'end' ? referenceRect.right : referenceRect.left

		if (referencePoint + width > innerWidth) {
			futurePlacement = 'left'
		}
	}

	reference.dataset.submenu = futurePlacement

	reference.addEventListener('click', () => {})
}

const openSubmenu = (e) => {
	const li = e.target.closest('li')

	li.classList.add('ct-active')

	li.firstElementChild
		.querySelector('.child-indicator')
		.setAttribute('aria-expanded', 'true')
}

const closeSubmenu = (e) => {
	const li = e.target.closest('li')
	li.classList.remove('ct-active')

	li.firstElementChild
		.querySelector('.child-indicator')
		.setAttribute('aria-expanded', 'false')
}

export const mountMenuLevel = (menuLevel, args = {}) => {
	;[...menuLevel.children]
		.filter((el) =>
			el.matches('.menu-item-has-children, .page_item_has_children')
		)
		.map((el) => {
			if (el.classList.contains('ct-mega-menu-custom-width')) {
				const menu = el.querySelector('.sub-menu')
				const elRect = el.getBoundingClientRect()
				const menuRect = menu.getBoundingClientRect()

				if (
					elRect.left + elRect.width / 2 + menuRect.width / 2 >
					innerWidth
				) {
					el.dataset.submenu = 'left'
				}

				if (elRect.left + elRect.width / 2 - menuRect.width / 2 < 0) {
					el.dataset.submenu = 'right'
				}
			}

			if (isEligibleForSubmenu(el)) {
				computeItemSubmenuFor(el, args)
			}

			let childIndicator = el.firstElementChild.querySelector(
				'.child-indicator'
			)

			if (childIndicator && !childIndicator.hasEventListener) {
				childIndicator.hasEventListener = true

				childIndicator.addEventListener('keyup', (e) => {
					if (e.keyCode !== 13) {
						return
					}

					if (
						e.target.closest('li').classList.contains('ct-active')
					) {
						closeSubmenu(e)
					} else {
						openSubmenu(e)

						e.target
							.closest('li')
							.addEventListener('focusout', (evt) => {
								if (
									!e.target
										.closest('li')
										.contains(evt.relatedTarget)
								) {
									closeSubmenu(e)
								}
							})
					}
				})
			}
		})
}

const mouseenterHandler = ({ target }) => {
	if (!target.matches('.menu-item-has-children, .page_item_has_children')) {
		target = target.closest(
			'.menu-item-has-children, .page_item_has_children'
		)
	}

	if (
		target.parentNode.classList.contains('menu') &&
		target.className.indexOf('ct-mega-menu') > -1 &&
		target.className.indexOf('ct-mega-menu-custom-width') === -1 &&
		wp &&
		wp.customize &&
		wp.customize('active_theme')
	) {
		const menu = target.querySelector('.sub-menu')

		menu.style.left = `${
			Math.round(
				target
					.closest('[class*="ct-container"]')
					.firstElementChild.getBoundingClientRect().x
			) - Math.round(target.closest('nav').getBoundingClientRect().x)
		}px`
	}

	if (!isEligibleForSubmenu(target)) {
		return
	}

	const menu = target.querySelector('.sub-menu')

	mountMenuLevel(menu)

	if (menu._timeout_id) {
		clearTimeout(menu._timeout_id)
	}

	menu.parentNode.addEventListener(
		'mouseleave',
		() => {
			menu._timeout_id = setTimeout(() => {
				menu._timeout_id = null
				;[...menu.children]
					.filter((el) => isEligibleForSubmenu(el))
					.map((el) => el.removeAttribute('data-submenu'))
			}, 200)
		},
		{ once: true }
	)
}

export const handleUpdate = (menu) => {
	if (!menu.parentNode) {
		menu = document.querySelector(`[class="${menu.className}"]`)
	}

	if (!menu) {
		return
	}

	if (
		!menu.querySelector('.menu-item-has-children') &&
		!menu.querySelector('.page_item_has_children')
	) {
		return
	}

	menu.removeEventListener('mouseenter', mouseenterHandler)
	menu.addEventListener('mouseenter', mouseenterHandler)

	menu.removeEventListener('focusin', mouseenterHandler)
	menu.addEventListener('focusin', mouseenterHandler)
}
