<script lang="ts">
	import userIdentity from '../../stores/userIdentity.js';
	import {
		userIdentity as getUserIdentity,
		type AniListAuthorisation
	} from '$lib/AniList/identity';
	import { onMount } from 'svelte';
	import { wrapped } from '$lib/AniList/wrapped.js';
	import { activityHistory, fillMissingDays } from '$lib/AniList/activity.js';
	import { Type, mediaListCollection, type Media } from '$lib/AniList/media.js';
	import anime from '../../stores/anime.js';
	import lastPruneTimes from '../../stores/lastPruneTimes.js';
	import manga from '../../stores/manga.js';
	import Error from '$lib/Error.svelte';
	import { domToBlob } from 'modern-screenshot';

	export let user: AniListAuthorisation;

	let currentUserIdentity = { name: '', id: -1 };
	let episodes = 0;
	let animeList: Media[] | undefined = undefined;
	let mangaList: Media[] | undefined = undefined;
	let abbreviateTitles = true;
	let maxAbbreviateLength = 40;
	let transparency = false;
	let darkTheme = true;

	onMount(async () => {
		if (user !== undefined) {
			if ($userIdentity === '') {
				userIdentity.set(JSON.stringify(await getUserIdentity(user)));
			}

			currentUserIdentity = JSON.parse($userIdentity);
			currentUserIdentity.name = currentUserIdentity.name;

			const currentYear = new Date(Date.now()).getFullYear();

			animeList = (
				await mediaListCollection(
					user,
					currentUserIdentity,
					Type.Anime,
					$anime,
					$lastPruneTimes.anime,
					true,
					true
				)
			)
				.filter(
					(item, index, self) =>
						self.findIndex((itemToCompare) => itemToCompare.id === item.id) === index
				)
				.filter((m) => m.mediaListEntry?.startedAt.year === currentYear)
				.sort((a, b) => {
					if (a.mediaListEntry?.score === undefined) {
						return 1;
					} else if (b.mediaListEntry?.score === undefined) {
						return -1;
					} else {
						return b.mediaListEntry?.score - a.mediaListEntry?.score;
					}
				});
			mangaList = (
				await mediaListCollection(
					user,
					currentUserIdentity,
					Type.Manga,
					$manga,
					$lastPruneTimes.manga,
					true,
					true
				)
			)
				.filter(
					(item, index, self) =>
						self.findIndex((itemToCompare) => itemToCompare.id === item.id) === index
				)
				.filter((m) => m.mediaListEntry?.startedAt.year === currentYear)
				.sort((a, b) => {
					if (a.mediaListEntry?.score === undefined) {
						return 1;
					} else if (b.mediaListEntry?.score === undefined) {
						return -1;
					} else {
						return b.mediaListEntry?.score - a.mediaListEntry?.score;
					}
				});

			for (const media of animeList) {
				episodes += media.mediaListEntry?.progress || 0;
			}
		} else {
			currentUserIdentity.id = -2;
		}
	});

	/* eslint-disable @typescript-eslint/no-explicit-any */
	const year = (statistic: { startYears: any }) => {
		return statistic.startYears.find((y: { startYear: number }) => y.startYear === 2023);
	};

	const screenshot = async (dark = false) => {
		let element = document.querySelector('.categories-grid') as HTMLElement;

		element.classList.add('invert');

		if (dark) {
			// element.classList.add('light-theme');
			darkTheme = false;
		}

		if (element !== null) {
			domToBlob(element, {
				backgroundColor: transparency ? undefined : dark ? '#0b1622' : '#edf1f5',
				quality: 1,
				scale: 2,
				fetch: {
					requestInit: {
						mode: 'cors'
					},
					bypassingCache: true
				}
			}).then((blob) => {
				const downloadWrapper = document.createElement('a');
				const wrappedImageButton = document.getElementById(
					'wrapped-image-download'
				) as HTMLAnchorElement;
				const image = document.createElement('img');
				const object = (window.URL || window.webkitURL || window || {}).createObjectURL(blob);

				// downloadWrapper.download = `due_dot_moe_wrapped_${dark ? 'dark' : 'light'}.png`;
				downloadWrapper.href = object;
				downloadWrapper.target = '_blank';
				image.src = object;

				downloadWrapper.appendChild(image);

				if (wrappedImageButton !== null) {
					wrappedImageButton.href = object;
				}

				const wrappedFinal = document.getElementById('wrapped-final');

				if (wrappedFinal !== null) {
					wrappedFinal.innerHTML = '';
					wrappedFinal.appendChild(downloadWrapper);
				}

				downloadWrapper.click();
			});

			await new Promise((resolve) => setTimeout(resolve, 1000));

			element.classList.remove('invert');
			darkTheme = true;
			// element.classList.remove('light-theme');
		}
	};

	const abbreviate = (string: string, maxLength = 40, enabled = true) => {
		if (!enabled) {
			return string;
		}

		if (string.length <= maxLength) {
			return string;
		}

		return string.slice(0, maxLength - 3) + ' …';
	};
</script>

{#if currentUserIdentity.id === -2}
	Please log in to view this page.
{:else if currentUserIdentity.id !== -1}
	{#await wrapped(user, currentUserIdentity)}
		Loading ...
	{:then wrapped}
		{@const anime = year(wrapped.statistics.anime)}
		{@const manga = year(wrapped.statistics.manga)}

		<div class:light-theme={darkTheme} class="categories-grid">
			<div class="grid-item image-grid avatar-grid">
				<a href={`https://anilist.co/user/${currentUserIdentity.name}`} target="_blank">
					<img src={wrapped.avatar.large} alt="User Avatar" />
				</a>
				<div>
					<div>
						<a href={`https://anilist.co/user/${currentUserIdentity.name}`} target="_blank">
							<b>
								{currentUserIdentity.name}
							</b>
						</a>
					</div>
					<div>
						Status Posts: {wrapped.activities.statusCount}
					</div>
					<div>
						Messages: {wrapped.activities.messageCount}
					</div>
					<div>
						Days Active: {#await activityHistory(currentUserIdentity)}
							Loading ...
						{:then activities}
							{#if activities === undefined}
								Loading ...
							{:else}
								{fillMissingDays(activities, true).filter((a) => a.amount !== 0).length}/365
							{/if}
						{/await}
					</div>
				</div>
			</div>
			<div class="category-grid pure-category">
				<div class="grid-item">
					<b>Anime</b>
				</div>
				<div class="grid-item">
					Time Watched: {((anime.minutesWatched || 0) / 60 / 24).toFixed(2)} days
				</div>
				<div class="grid-item">
					Completed: {anime.count}
				</div>
				<div class="grid-item">Episodes: {episodes}</div>
			</div>
			<div class="category-grid pure-category">
				<div class="grid-item">
					<b>Manga</b>
				</div>
				<div class="grid-item">
					Time Read: {(((manga.chaptersRead || 0) * 8.58) / 60 / 24).toFixed(2)} days
				</div>
				<div class="grid-item">
					Completed: {manga.count}
				</div>
				<div class="grid-item">
					Chapters: {manga.chaptersRead || 0}
				</div>
			</div>
			<div class="category-grid pure-category">
				<div class="grid-item image-grid">
					{#if animeList !== undefined}
						<a href={`https://anilist.co/anime/${animeList[0].id}`} target="_blank">
							<img
								src={animeList[0].coverImage.extraLarge}
								alt="Highest Rated Anime Cover"
								class="cover-image"
							/>
						</a>
						<div>
							<b>Highest Rated Anime</b>
							<ol>
								{#each animeList?.slice(0, 5) as anime}
									<li>
										<a href={`https://anilist.co/anime/${anime.id}`} target="_blank">
											{abbreviate(
												anime.title.english || anime.title.romaji || anime.title.native,
												maxAbbreviateLength,
												abbreviateTitles
											)}
										</a>
									</li>
								{/each}
							</ol>
						</div>
					{:else}
						Loading ...
					{/if}
				</div>
			</div>
			<div class="category-grid pure-category">
				<div class="grid-item image-grid">
					{#if mangaList !== undefined}
						<a href={`https://anilist.co/manga/${mangaList[0].id}`} target="_blank">
							<img
								src={mangaList[0].coverImage.extraLarge}
								alt="Highest Rated Manga Cover"
								class="cover-image"
							/>
						</a>
						<div>
							<b>Highest Rated Manga</b>
							<ol>
								{#each mangaList?.slice(0, 5) as manga}
									<li>
										<a href={`https://anilist.co/manga/${manga.id}`} target="_blank">
											{abbreviate(
												manga.title.english || manga.title.romaji || manga.title.native,
												maxAbbreviateLength,
												abbreviateTitles
											)}
										</a>
									</li>
								{/each}
							</ol>
						</div>
					{:else}
						Loading ...
					{/if}
				</div>
			</div>
		</div>

		<br />

		<p>
			Don't be alarmed! The background will appear as its inverse in the preview, but will be
			corrected in the final image. Media covers may not appear on Apple devices.
		</p>

		<ul>
			<li>
				<a href={'#'} on:click={() => screenshot(true)}>Generate dark themed image</a>
			</li>
			<li>
				<a href={'#'} on:click={() => screenshot()}>Generate light themed image</a>
			</li>
			<li>
				<a href={'#'} on:click={() => (transparency = !transparency)}>
					<strike>
						{transparency ? 'Disable' : 'Enable'} background transparency
					</strike>
				</a>
			</li>
			<li>
				<a href={'#'} on:click={() => (abbreviateTitles = !abbreviateTitles)}>
					{abbreviateTitles ? 'Display full titles' : 'Abbreviate titles'}
				</a>
				<input type="number" bind:value={maxAbbreviateLength} />
			</li>
			<li>
				<a href={'#'} target="_blank" id="wrapped-image-download">
					Download generated image (generate first)
				</a>
			</li>
		</ul>

		<br />

		<div id="wrapped-final" />
	{:catch}
		<Error />
	{/await}
{:else}
	Loading ...
{/if}

<style>
	@import url('http://fonts.googleapis.com/css?family=Roboto:300,400,500,700');
	@import url('https://fonts.googleapis.com/css?family=Overpass:400,600,700,800');

	.categories-grid {
		display: flex;
		flex-wrap: wrap;
		row-gap: 1.5em;
		column-gap: 1.5em;
		padding: 2%;
		justify-content: center;
		/* filter: invert(0) !important; */
		background-color: #0b1622;
		font-family: Roboto, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Cantarell,
			Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
	}

	.categories-grid b {
		font-family: Overpass, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Cantarell,
			Fira Sans, Droid Sans, Helvetica Neue, sans-serif !important;
		font-weight: 600 !important;
	}

	.category-grid,
	.image-grid {
		background-color: #151f2e;
		border-radius: 4px;
		color: rgb(159, 173, 189) !important;
	}

	.pure-category,
	.avatar-grid {
		padding: 1.5%;
	}

	.category-grid {
		display: grid;
	}

	.image-grid {
		display: flex;
		column-gap: 1em;
		flex-wrap: wrap;
	}

	.image-grid img {
		height: 6em;
		border-radius: 3px;
	}

	.cover-image {
		height: 8.75em !important;
	}

	.categories-grid a {
		text-decoration: none;
		color: unset;
	}

	.light-theme .categories-grid {
		background-color: #edf1f5 !important;
	}

	.light-theme .category-grid {
		background-color: #fafafa !important;
		color: rgb(92, 114, 138) !important;
	}

	.light-theme .image-grid {
		background-color: #fafafa !important;
		color: rgb(92, 114, 138) !important;
	}

	:global(.invert *) {
		filter: invert(0) !important;
	}

	ol {
		margin: 0 !important;
	}
</style>
