<script lang="ts">
	import { mediaListCollection, Type, type Media } from '$lib/AniList/media';
	import type { UserIdentity, AniListAuthorisation } from '$lib/AniList/identity';
	import { onDestroy, onMount } from 'svelte';
	import { chapterCount, pruneAllManga } from '$lib/Media/manga';
	import manga from '../../../stores/manga';
	import { chapterDatabase } from '$lib/Media/chapters';
	import settings from '../../../stores/settings';
	import lastPruneTimes from '../../../stores/lastPruneTimes';
	import ListTitle from '../ListTitle.svelte';
	import Error from '$lib/Error.svelte';

	export let user: AniListAuthorisation;
	export let identity: UserIdentity;
	export let displayUnresolved: boolean;
	export let due: boolean;

	let mangaLists: Promise<Media[]>;
	let startTime: number;
	let endTime: number;

	const keyCacher = setInterval(() => {
		startTime = performance.now();
		endTime = -1;
		mangaLists = mediaListCollection(user, identity, Type.Manga, $manga, $lastPruneTimes.manga);
	}, $settings.cacheMinutes * 1000 * 60);

	onMount(async () => {
		startTime = performance.now();
		mangaLists = mediaListCollection(user, identity, Type.Manga, $manga, $lastPruneTimes.manga);
	});

	onDestroy(() => clearInterval(keyCacher));

	const cleanMedia = async (media: Media[], displayUnresolved: boolean) => {
		if (media === undefined) {
			return [];
		}

		if ($lastPruneTimes.chapters === 1) {
			lastPruneTimes.setKey('chapters', new Date().getTime());
		} else {
			const currentDate = new Date();

			if (
				(currentDate.getTime() - $lastPruneTimes.chapters) / 1000 / 60 >
				$settings.cacheMangaMinutes
			) {
				const unresolved = await chapterDatabase.chapters.where('chapters').equals(-1).toArray();
				const ids = unresolved.map((m) => m.id);

				lastPruneTimes.setKey('chapters', currentDate.getTime());
				await chapterDatabase.chapters.bulkDelete(ids);
			}
		}

		const releasingMedia = media.filter(
			(media: Media) =>
				(due ? media.status === 'RELEASING' : media.status === 'FINISHED') &&
				(media.mediaListEntry || { status: 'DROPPED' }).status !==
					($settings.displayPausedMedia ? '' : 'PAUSED') &&
				(media.mediaListEntry || { progress: 0 }).progress >=
					($settings.displayNotStarted === true ? 0 : 1)
		);
		let finalMedia = releasingMedia;
		const chapterPromises = finalMedia.map((m: Media) => chapterCount(identity, m));
		const chapterCounts = await Promise.all(chapterPromises);

		finalMedia.forEach((m: Media, i) => {
			m.episodes = chapterCounts[i] || -1337;
		});

		if (!displayUnresolved) {
			finalMedia = finalMedia.filter((m: Media) => m.episodes !== -1337);
		}

		finalMedia.sort((a: Media, b: Media) => {
			return (
				(a.episodes || 9999) -
				(a.mediaListEntry || { progress: 0 }).progress -
				((b.episodes || 9999) - (b.mediaListEntry || { progress: 0 }).progress)
			);
		});

		finalMedia = finalMedia.filter((item, index, array) => {
			return (
				array.findIndex((i) => {
					return i.id === item.id;
				}) === index &&
				(item.episodes === -1337 && displayUnresolved
					? true
					: (item.mediaListEntry?.progress || 0) <
					  ($settings.roundDownChapters === true ? Math.floor(item.episodes) : item.episodes))
			);
		});

		if (!endTime || endTime === -1) {
			endTime = performance.now() - startTime;
		}

		return finalMedia;
	};

	const updateMedia = async (id: number, progress: number | undefined) => {
		await chapterDatabase.chapters.delete(id);
		await fetch(`/api/anilist-increment?id=${id}&progress=${(progress || 0) + 1}`).then(() => {
			mangaLists = mediaListCollection(
				user,
				identity,
				Type.Manga,
				$manga,
				$lastPruneTimes.manga,
				true
			);
		});
	};

	const cleanCache = async () => {
		await pruneAllManga();

		mangaLists = mediaListCollection(
			user,
			identity,
			Type.Manga,
			$manga,
			$lastPruneTimes.manga,
			true
		);
	};
</script>

{#await mangaLists}
	<ListTitle />

	<ul><li>Loading ...</li></ul>
{:then media}
	{#await cleanMedia(media, displayUnresolved)}
		<ListTitle />

		<ul><li>Loading ...</li></ul>
	{:then cleanedMedia}
		<ListTitle count={cleanedMedia.length} time={endTime / 1000}>
			<a href={'#'} title="Force a refresh" on:click={cleanCache}>Force</a>
		</ListTitle>

		{#if cleanedMedia.length === 0}
			<ul>
				<li>No manga to display. <a href={'#'} on:click={cleanCache}>Force refresh</a></li>
			</ul>
		{/if}

		<ul>
			{#each cleanedMedia as manga}
				<li>
					<a href={`https://anilist.co/manga/${manga.id}`} target="_blank">
						{manga.title.english || manga.title.romaji || manga.title.native}
					</a>
					<span style="opacity: 50%;">|</span>
					{(manga.mediaListEntry || { progress: 0 }).progress}
					<a href={'#'} on:click={() => updateMedia(manga.id, manga.mediaListEntry?.progress)}>+</a>
					[{manga.episodes || '?'}]
				</li>
			{/each}
		</ul>
	{:catch}
		<ListTitle count={'?'} time={0} />

		<Error />
	{/await}
{/await}
