import {
	getNavigationType,
	getPathId,
	isBackNavigation,
	shouldNotIntercept,
	updateTheDOMSomehow,
	useTvFragment,
} from './utils';

// View Transitions support cross-document navigations.
// Should compare performace.
// https://github.com/WICG/view-transitions/blob/main/explainer.md#cross-document-same-origin-transitions
// https://github.com/WICG/view-transitions/blob/main/explainer.md#script-events
function shouldDisableSpa() {
	return false;
}

navigation.addEventListener('navigate', (navigateEvent) => {
	if (shouldDisableSpa()) return;
	if (shouldNotIntercept(navigateEvent)) return;

	const toUrl = new URL(navigateEvent.destination.url);
	const toPath = toUrl.pathname;
	const fromPath = location.pathname;
	const navigationType = getNavigationType(fromPath, toPath);

	if (location.origin !== toUrl.origin) return;

	switch (navigationType) {
		case 'home-to-movie':
		case 'tv-to-show':
			handleHomeToMovieTransition(navigateEvent, getPathId(toPath));
			break;
		case 'movie-to-home':
		case 'show-to-tv':
			handleMovieToHomeTransition(navigateEvent, getPathId(fromPath));
			break;
		case 'movie-to-person':
			handleMovieToPersonTransition(navigateEvent, getPathId(fromPath), getPathId(toPath));
			break;
		case 'person-to-movie':
		case 'person-to-show':
			handlePersonToMovieTransition(navigateEvent, getPathId(fromPath), getPathId(toPath));
			break;
		default:
			return;
	}
});

// TODO: https://developer.chrome.com/docs/web-platform/view-transitions/#transitions-as-an-enhancement
function handleHomeToMovieTransition(navigateEvent, movieId) {
	navigateEvent.intercept({
		async handler() {
			const fragmentUrl = useTvFragment(navigateEvent)
				? '/fragments/TvDetails'
				: '/fragments/MovieDetails';
			const response = await fetch(`${fragmentUrl}/${movieId}`);
			const data = await response.text();

			if (!document.startViewTransition) {
				updateTheDOMSomehow(data);
				return;
			}

			const thumbnail = document.getElementById(`movie-poster-${movieId}`);
			if (thumbnail) {
				thumbnail.style.viewTransitionName = 'movie-poster';
			}

			const transition = document.startViewTransition(() => {
				if (thumbnail) {
					thumbnail.style.viewTransitionName = '';
				}
				document.getElementById('container').scrollTop = 0;
				updateTheDOMSomehow(data);
			});

			await transition.finished;
		},
	});
}

function handleMovieToHomeTransition(navigateEvent, movieId) {
	navigateEvent.intercept({
		scroll: 'manual',
		async handler() {
			const fragmentUrl = useTvFragment(navigateEvent)
				? '/fragments/TvList'
				: '/fragments/MovieList';
			const response = await fetch(fragmentUrl);
			const data = await response.text();

			if (!document.startViewTransition) {
				updateTheDOMSomehow(data);
				return;
			}

			const tempHomePage = document.createElement('div');
			const moviePoster = document.getElementById(`movie-poster`);
			let thumbnail;

			// If the movie poster is not in the home page, removes the transition style so that
			// the poster doesn't stay on the page while transitioning
			tempHomePage.innerHTML = data;
			if (!tempHomePage.querySelector(`#movie-poster-${movieId}`)) {
				moviePoster?.classList.remove('movie-poster');
			}

			const transition = document.startViewTransition(() => {
				updateTheDOMSomehow(data);

				thumbnail = document.getElementById(`movie-poster-${movieId}`);
				if (thumbnail) {
					thumbnail.scrollIntoViewIfNeeded();
					thumbnail.style.viewTransitionName = 'movie-poster';
				}
			});

			await transition.finished;

			if (thumbnail) {
				thumbnail.style.viewTransitionName = '';
			}
		},
	});
}

function handleMovieToPersonTransition(navigateEvent, movieId, personId) {
	// TODO: https://developer.chrome.com/docs/web-platform/view-transitions/#not-a-polyfill
	// ...has example of `back-transition` class applied to document
	const isBack = isBackNavigation(navigateEvent);

	navigateEvent.intercept({
		async handler() {
			const response = await fetch('/fragments/PersonDetails/' + personId);
			const data = await response.text();

			if (!document.startViewTransition) {
				updateTheDOMSomehow(data);
				return;
			}

			let personThumbnail;
			let moviePoster;
			let movieThumbnail;

			if (!isBack) {
				// We're transitioning the person photo; we need to remove the transition of the poster
				// so that it doesn't stay on the page while transitioning
				moviePoster = document.getElementById(`movie-poster`);
				if (moviePoster) {
					moviePoster.classList.remove('movie-poster');
				}

				personThumbnail = document.getElementById(`person-photo-${personId}`);
				if (personThumbnail) {
					personThumbnail.style.viewTransitionName = 'person-photo';
				}
			}

			const transition = document.startViewTransition(() => {
				updateTheDOMSomehow(data);

				if (personThumbnail) {
					personThumbnail.style.viewTransitionName = '';
				}

				if (isBack) {
					// If we're coming back to the person page, we're transitioning
					// into the movie poster thumbnail, so we need to add the tag to it
					movieThumbnail = document.getElementById(`movie-poster-${movieId}`);
					if (movieThumbnail) {
						movieThumbnail.scrollIntoViewIfNeeded();
						movieThumbnail.style.viewTransitionName = 'movie-poster';
					}
				}

				document.getElementById('container').scrollTop = 0;
			});

			await transition.finished;

			if (movieThumbnail) {
				movieThumbnail.style.viewTransitionName = '';
			}
		},
	});
}

function handlePersonToMovieTransition(navigateEvent, personId, movieId) {
	const isBack = isBackNavigation(navigateEvent);

	navigateEvent.intercept({
		scroll: 'manual',
		async handler() {
			const fragmentUrl = useTvFragment(navigateEvent)
				? '/fragments/TvDetails'
				: '/fragments/MovieDetails';
			const response = await fetch(`${fragmentUrl}/${movieId}`);
			const data = await response.text();

			if (!document.startViewTransition) {
				updateTheDOMSomehow(data);
				return;
			}

			let thumbnail;
			let moviePoster;
			let movieThumbnail;

			if (!isBack) {
				movieThumbnail = document.getElementById(`movie-poster-${movieId}`);
				if (movieThumbnail) {
					movieThumbnail.style.viewTransitionName = 'movie-poster';
				}
			}

			const transition = document.startViewTransition(() => {
				updateTheDOMSomehow(data);

				if (isBack) {
					moviePoster = document.getElementById(`movie-poster`);
					if (moviePoster) {
						moviePoster.classList.remove('movie-poster');
					}

					if (personId) {
						thumbnail = document.getElementById(`person-photo-${personId}`);
						if (thumbnail) {
							thumbnail.scrollIntoViewIfNeeded();
							thumbnail.style.viewTransitionName = 'person-photo';
						}
					}
				} else {
					document.getElementById('container').scrollTop = 0;

					if (movieThumbnail) {
						movieThumbnail.style.viewTransitionName = '';
					}
				}
			});

			await transition.finished;

			if (thumbnail) {
				thumbnail.style.viewTransitionName = '';
			}

			if (moviePoster) {
				moviePoster.classList.add('movie-poster');
			}
		},
	});
}
