/* FoodOrd lazy image loader */

(function (window, document) {
	if (!window || !document) {
		return;
	}

	window.FOODORD_LAZY_PLACEHOLDER = window.FOODORD_LAZY_PLACEHOLDER || '';

	if (typeof window.FoodordGetLazyPlaceholder !== 'function') {
		window.FoodordGetLazyPlaceholder = function (imageUrl) {
			const placeholder = window.FOODORD_LAZY_PLACEHOLDER || '';
			if (placeholder && placeholder.length) {
				return placeholder;
			}
			return imageUrl || '';
		};
	}

	const LAZY_SELECTOR = '[data-foodord-lazy-src], source[data-foodord-lazy-srcset]';
	const ACTIVE_CLASS = 'foodord-lazy-loaded';
	const OBSERVER_MARGIN = '0px 0px 200px 0px';

	const toArray = function (nodeList) {
		return Array.prototype.slice.call(nodeList || []);
	};

	const loadImage = function (el) {
		if (!el || el.dataset.foodordLazyComplete === '1') {
			return;
		}

		const src = el.getAttribute('data-foodord-lazy-src');
		if (src) {
			el.setAttribute('src', src);
			el.removeAttribute('data-foodord-lazy-src');
		}

		const srcset = el.getAttribute('data-foodord-lazy-srcset');
		if (srcset) {
			el.setAttribute('srcset', srcset);
			el.removeAttribute('data-foodord-lazy-srcset');
		}

		const sizes = el.getAttribute('data-foodord-lazy-sizes');
		if (sizes) {
			el.setAttribute('sizes', sizes);
			el.removeAttribute('data-foodord-lazy-sizes');
		}

		const markComplete = function () {
			if (typeof el.classList !== 'undefined') {
				el.classList.add(ACTIVE_CLASS);
			}
			el.dataset.foodordLazyComplete = '1';
		};

		if (el.complete) {
			markComplete();
		} else {
			el.addEventListener('load', markComplete, { once: true });
			el.addEventListener('error', markComplete, { once: true });
		}
	};

	const loadSource = function (source) {
		if (!source || source.dataset.foodordLazyComplete === '1') {
			return;
		}
		const srcset = source.getAttribute('data-foodord-lazy-srcset');
		if (srcset) {
			source.setAttribute('srcset', srcset);
			source.removeAttribute('data-foodord-lazy-srcset');
		}
		const sizes = source.getAttribute('data-foodord-lazy-sizes');
		if (sizes) {
			source.setAttribute('sizes', sizes);
			source.removeAttribute('data-foodord-lazy-sizes');
		}
		source.dataset.foodordLazyComplete = '1';
	};

	let observer = null;
	if ('IntersectionObserver' in window) {
		observer = new IntersectionObserver(
			function (entries) {
				entries.forEach(function (entry) {
					if (entry.isIntersecting || entry.intersectionRatio > 0) {
						if (observer) {
							observer.unobserve(entry.target);
						}
						switch (entry.target.nodeName) {
							case 'SOURCE':
								loadSource(entry.target);
								break;
							case 'IMG':
							default:
								loadImage(entry.target);
						}
					}
				});
			},
			{ rootMargin: OBSERVER_MARGIN, threshold: 0.01 }
		);
	}

	const observeElement = function (el) {
		if (!el || el.dataset.foodordLazyObserved === '1') {
			return;
		}
		el.dataset.foodordLazyObserved = '1';
		if (observer) {
			observer.observe(el);
		} else {
			switch (el.nodeName) {
				case 'SOURCE':
					loadSource(el);
					break;
				case 'IMG':
				default:
					loadImage(el);
			}
		}
	};

	const scanForLazyImages = function (root) {
		const context = root || document;
		if (!context.querySelectorAll) {
			return;
		}
		const targets = context.querySelectorAll(LAZY_SELECTOR);
		toArray(targets).forEach(observeElement);
	};

	if (document.readyState === 'complete' || document.readyState === 'interactive') {
		scanForLazyImages(document);
	} else {
		document.addEventListener('DOMContentLoaded', function () {
			scanForLazyImages(document);
		});
	}

	window.addEventListener('load', function () {
		scanForLazyImages(document);
	});

	const mutationObserver = new MutationObserver(function (mutations) {
		mutations.forEach(function (mutation) {
			toArray(mutation.addedNodes).forEach(function (node) {
				if (!node) {
					return;
				}
				if (node.matches && node.matches(LAZY_SELECTOR)) {
					observeElement(node);
				}
				if (node.querySelectorAll) {
					scanForLazyImages(node);
				} else if (node.dataset && (node.dataset.foodordLazySrc || node.dataset.foodordLazySrcset)) {
					observeElement(node);
				}
			});
		});
	});

	mutationObserver.observe(document.documentElement || document.body, {
		childList: true,
		subtree: true,
	});

	window.foodordLazyLoadScan = scanForLazyImages;
})(window, document);
