/**
 * Cache module — Hover-prefetch internal links
 *
 * On `mouseover` / `focus` over an internal `<a>` tag, prepares a
 * `<link rel="prefetch">` so the browser starts the request before the user
 * actually clicks. Works only for same-origin GET-only links and the page
 * is NOT in incognito (where browser-level prefetch is disabled anyway).
 *
 * Inspired by instant.page; written from scratch.
 *
 * @package BlaminhorEssentials
 */
(function () {
	'use strict';

	if (!('connection' in navigator) || !navigator.connection || navigator.connection.saveData) {
		// Respect data-saver users.
		return;
	}

	var origin = window.location.origin;
	var prefetched = new Set();

	function prefetch(href) {
		if (prefetched.has(href)) { return; }
		prefetched.add(href);
		var link = document.createElement('link');
		link.rel = 'prefetch';
		link.href = href;
		link.as = 'document';
		document.head.appendChild(link);
	}

	function isEligible(a) {
		if (!a || !a.href || a.target === '_blank') { return false; }
		if (a.protocol !== 'http:' && a.protocol !== 'https:') { return false; }
		if (a.origin !== origin) { return false; }
		if (a.hash && a.pathname === window.location.pathname) { return false; }
		// Skip download / print / mailto links.
		if (a.hasAttribute('download')) { return false; }
		// Skip admin URLs.
		if (a.pathname.indexOf('/wp-admin/') !== -1) { return false; }
		return true;
	}

	function onHover(e) {
		var a = e.target.closest('a[href]');
		if (!a) { return; }
		if (!isEligible(a)) { return; }
		// Wait 65ms — WP Rocket / instant.page found this is the sweet spot to
		// avoid prefetching links the user moved over without intent.
		var t = setTimeout(function () { prefetch(a.href); }, 65);
		a.addEventListener('mouseout', function () { clearTimeout(t); }, { once: true });
	}

	function onFocus(e) {
		var a = e.target.closest('a[href]');
		if (!a) { return; }
		if (isEligible(a)) { prefetch(a.href); }
	}

	document.addEventListener('mouseover', onHover, { passive: true, capture: true });
	document.addEventListener('focusin', onFocus, { passive: true, capture: true });
})();
