<script lang="ts">
	import Error from '$lib/Error/RateLimited.svelte';
	import type { SubsPlease, SubsPleaseEpisode } from '$lib/Media/Anime/Airing/Subtitled/subsPlease';
	import { onMount } from 'svelte';
	import settings from '../../stores/settings';
	import { parseOrDefault } from '$lib/Utility/parameters';
	import { browser } from '$app/environment';
	import type { Media } from '$lib/AniList/media';
	import { scheduleMediaListCollection } from '$lib/AniList/schedule';
	import { season } from '$lib/Media/Anime/season';
	import { findClosestMedia } from '$lib/Media/Anime/Airing/Subtitled/match';
	import MediaTitleDisplay from '$lib/List/MediaTitleDisplay.svelte';
	import { outboundLink } from '$lib/Media/links';

	let subsPleasePromise: Promise<SubsPlease>;
	let scheduledMediaPromise: Promise<Partial<Media[]>>;
	const urlParameters = browser ? new URLSearchParams(window.location.search) : null;
	let timeZone = parseOrDefault(
		urlParameters,
		'tz',
		Intl.DateTimeFormat().resolvedOptions().timeZone
	);
	let day: string | null = parseOrDefault(urlParameters, 'day', null);

	onMount(async () => {
		subsPleasePromise = fetch(`/api/subsplease?tz=${timeZone}`).then((r) => r.json());
		scheduledMediaPromise = scheduleMediaListCollection(new Date().getFullYear(), season());
	});

	let hoveredItem: SubsPleaseEpisode | null = null;
	let hoveredMedia: Media | null = null;
	let imageStyle = '';
	let imageHeight = 0;

	const onMouseMove = (event: MouseEvent) => {
		const imageWidth = 300;
		const offset = 10;
		let imageLeft = 0;
		let imageTop = 0;
		const image = document.getElementsByClassName('hover-image')[0] as HTMLImageElement;

		image.onload = () => (imageHeight = image.height);
		imageLeft =
			event.pageX + imageWidth + offset > window.innerWidth
				? event.pageX - imageWidth - offset
				: event.pageX + offset;
		imageTop =
			event.pageY + imageHeight + offset > window.innerHeight
				? event.pageY - imageHeight
				: event.pageY + offset;
		imageStyle = `top: ${imageTop}px; left: ${imageLeft}px;`;
	};

	const shiftSubsPleaseSchedule = (schedule: SubsPlease['schedule']) => {
		const shiftedSchedule: { [key: string]: SubsPleaseEpisode[] } = {};

		if (day && Object.keys(schedule).includes(day)) {
			shiftedSchedule[day] = schedule[
				day as keyof typeof schedule
			] as unknown as SubsPleaseEpisode[];

			return shiftedSchedule;
		}

		const days = Object.keys(schedule);
		const currentDayIndex = days.indexOf(new Date().toLocaleString('en-us', { weekday: 'long' }));

		days
			.slice(currentDayIndex)
			.concat(days.slice(0, currentDayIndex))
			.forEach((day) => {
				const scheduleEntry = schedule[day as keyof typeof schedule];
				shiftedSchedule[day] = Array.isArray(scheduleEntry)
					? scheduleEntry
					: ([scheduleEntry] as unknown as SubsPleaseEpisode[]);
			});

		return shiftedSchedule;
	};

	const associateMedia = (media: (Media | undefined)[], title: string) =>
		findClosestMedia(media as Media[], title);

	const titleSelect = (media: Media | null) =>
		media ? media.title.english || media.title.romaji || media.title.native : null;
</script>

<blockquote>
	<select
		bind:value={timeZone}
		on:change={() =>
			(subsPleasePromise = fetch(`/api/subsplease?tz=${timeZone}`).then((r) => r.json()))}
	>
		{#each Intl.supportedValuesOf('timeZone') as zone}
			<option value={zone}>
				{zone.split('/').reverse().join(', ').replace(/_/g, ' ')}
			</option>
		{/each}
	</select>
</blockquote>

{#await subsPleasePromise}
	Loading subtitle release data ... 49.5%
{:then subsPlease}
	{#if subsPlease}
		{#await scheduledMediaPromise}
			Loading anime schedule ... 82.5%
		{:then scheduledMedia}
			{#if scheduledMedia}
				<div id="list-container">
					{#each Object.entries(shiftSubsPleaseSchedule(subsPlease.schedule)) as [day, scheduleEntry]}
						<details
							open
							class="list"
							class:today={day === new Date().toLocaleString('en-us', { weekday: 'long' })}
						>
							<summary>{day}</summary>

							<ul>
								{#each Object.values(scheduleEntry) as entry}
									{@const media = associateMedia(scheduledMedia, entry.title)}

									<li
										class="entry"
										on:mouseenter={() => {
											hoveredItem = entry;
											hoveredMedia = media;
										}}
										on:mouseleave={() => {
											hoveredItem = null;
											hoveredMedia = null;
										}}
										on:mousemove={onMouseMove}
									>
										<a
											href={media
												? outboundLink(media, 'anime', $settings.displayOutboundLinksTo)
												: outboundLink(
														null,
														'anime',
														$settings.displayOutboundLinksTo,
														true,
														titleSelect(media) || entry.title
												  )}
											target="_blank"
										>
											{#if media}
												<MediaTitleDisplay title={media.title} />
											{:else}
												{entry.title}
											{/if}
										</a>
										{#if !$settings.displayCountdownRightAligned}
											<span style="opacity: 50%;">|</span>
										{/if}
										<span class:countdown={$settings.displayCountdownRightAligned}>
											{#if media && media.nextAiringEpisode}
												<span style="opacity: 50%;">
													&nbsp;
													{media.nextAiringEpisode?.episode}/{media.episodes} at
												</span>
											{/if}
											{entry.time}
										</span>
									</li>
								{/each}
							</ul>

							<p />
						</details>
					{/each}
				</div>
			{:else}
				Loading anime schedule ... 66%
			{/if}
		{:catch}
			<Error type="Media" loginSessionError={false} />
		{/await}
	{:else}
		Loading subtitle release data ... 33%
	{/if}
{:catch}
	<Error type="Schedule" loginSessionError={false} />
{/await}

{#if hoveredItem}
	<img
		class="hover-image show"
		src={hoveredMedia
			? hoveredMedia.coverImage.extraLarge
			: `https://subsplease.org${hoveredItem.image_url}`}
		alt="Media Cover"
		style={imageStyle}
	/>
{/if}

<style>
	#list-container {
		display: flex;
		flex-wrap: wrap;
	}

	.list {
		overflow-y: auto;
		min-width: 250px;
		min-width: 200px;
		flex: 1 1;
	}

	.entry::after {
		content: '';
		display: table;
		clear: both;
	}

	.countdown {
		white-space: nowrap;
		float: right;
	}

	.today {
		font-weight: bold;
	}

	.hover-image {
		position: fixed;
		z-index: 1000;
		width: 300px;
		height: auto;
		display: none;
	}

	.show {
		display: block;
	}
</style>
