import React from 'react';
import imgnotfound from '@assets/images/rastas/imgnotfound.png';
import placeholderImage from '@assets/images/rastas/loading-placeholder.png';

interface LazyLoadInterface {
	Image: Function;
	Video: Function;
	Component: Function
}

interface MediaInterface {
	src: string;
	alt: string;
	[propName: string]: any;
}

interface CallBackInterface {
	children,
	fallBack?
}

const Image = ({ src, alt, ...customProps }: MediaInterface) => {
	const [dataInfo, setDataInfo] = React.useState('');

	const imageRef = React.useRef<HTMLImageElement>(null);
	// const placeholderImage =
	// 	'https://via.placeholder.com/200/202127/FFFFFF.webp/?text=Loading...';

	React.useEffect(() => {
		// determine if intersection observer is supported
		// will polyfill for unsupported browsers later 😓
		if ('IntersectionObserver' in window) {
			const lazyBackgroundObserver = new IntersectionObserver(
				(entries) => {
					entries.forEach(async (entry) => {
						if (entry.isIntersecting) {
							// element is considered to be in viewport
							// but is actually 200px away from entering the viewport 😎

							// temporary alert to show when image has started loading
							// just in case your internet speed is so fast 🐌
							// console.log('original image has started loading');

							// change the image src so it renders the original image
							entry.target.setAttribute('src', src);

							// add class maybe for some effects or stye options 👀
							// entry.target.classList.add('visible-lazyloaded-asset');

							lazyBackgroundObserver.unobserve(entry.target);
						}
					});
				},
				{
					// rootMargin defines how far away the component should be from
					// entering viewport before firing.
					// eg: when element is 200px away from entering the viewport,
					// fire the intersection observer.
					// default threshold is 0, default root element is document
					rootMargin: '200px'
				}
			);

			lazyBackgroundObserver.observe(imageRef.current);
		} else {
			imageRef.current.setAttribute('src', src);
		}
	}, []);

	const imageErrorHandler = () => {
		setDataInfo(src);
		imageRef.current.src = imgnotfound;
	};

	return (
		<img
			data-info={dataInfo}
			onError={imageErrorHandler}
			ref={imageRef}
			src={placeholderImage}
			alt={alt}
			{...customProps}
		/>
	);
};


const Component = ({ children, fallBack }: CallBackInterface) => {

	const
		[ret, setRet] = React.useState(fallBack),
		compRef = React.useRef();

	React.useEffect(() => {
		if ('IntersectionObserver' in window) {
			const lazyBackgroundObserver = new IntersectionObserver(
				(entries) => {
					entries.forEach(async (entry) => {
						if (entry.isIntersecting) {
							// element is considered to be in viewport
							// but is actually 200px away from entering the viewport 😎

							// temporary alert to show when image has started loading
							// just in case your internet speed is so fast 🐌
							// console.log('component has been rendered');

							// execute callback
							setRet(children);

							// add class maybe for some effects or stye options 👀
							// entry.target.classList.add('visible-lazyloaded-asset');

							lazyBackgroundObserver.unobserve(entry.target);
						}
					});
				},
				{
					// rootMargin defines how far away the component should be from
					// entering viewport before firing.
					// eg: when element is 200px away from entering the viewport,
					// fire the intersection observer.
					// default threshold is 0, default root element is document
					rootMargin: '140px'
				}
			);

			lazyBackgroundObserver.observe(compRef?.current);
		} else {
			setRet(children);
		}
	}, []);

	return (
		<>
			<ins ref={compRef}></ins>
			{ret}
		</>
	);

};

/**
 * @deprecated The method is unimplemented and should not be used
 * The method serves as a placeholder for a future use case of video lazyloading
 */
const Video = ({ src, alt }: MediaInterface) => {
	return (
		<video src={src}>
			<track default kind="captions" srcLang="en" src="/something.vtt" />
			{alt}
		</video>
	);
};

const LazyLoad: LazyLoadInterface = {
	Image,
	Video,
	Component
};

export default LazyLoad;
