<script lang="ts">
	import { goto } from "$app/navigation";
	import Uploader from "$lib/components/functional/Uploader.svelte";
	import { converters } from "$lib/converters";
	import { log } from "$lib/logger";
	import { files } from "$lib/store/index.svelte";
	import { VertFile } from "$lib/types/file.svelte";
	import { Check } from "lucide-svelte";
	import jsmediatags from "jsmediatags";
	import type { TagType } from "jsmediatags/types/index.js";

	const { data } = $props();

	let ourFiles = $state<File[]>();

	const runUpload = async () => {
		const newFilePromises = (ourFiles || []).map(async (f) => {
			return new Promise<(typeof files.files)[0] | void>(
				(resolve, reject) => {
					const from =
						"." + f.name.toLowerCase().split(".").slice(-1);
					const converter = converters.find((c) =>
						c.supportedFormats.includes(from.toLowerCase()),
					);
					if (!converter) resolve();
					const to =
						converter?.supportedFormats.find((f) => f !== from) ||
						converters[0].supportedFormats[0];
					log(
						["uploader", "converter"],
						`converting ${from} to ${to} using ${converter?.name || "... no converter??"}`,
					);
					const canvas = document.createElement("canvas");
					const ctx = canvas.getContext("2d");
					const img = new Image();
					img.src = URL.createObjectURL(f);
					const maxSize = 512;
					img.onload = () => {
						const scale = Math.max(
							maxSize / img.width,
							maxSize / img.height,
						);
						canvas.width = img.width * scale;
						canvas.height = img.height * scale;
						ctx?.drawImage(img, 0, 0, canvas.width, canvas.height);
						// get the blob
						canvas.toBlob(
							async (blob) => {
								resolve(
									new VertFile(
										f,
										to,
										converter,
										URL.createObjectURL(blob!),
									),
								);
							},
							"image/jpeg",
							0.75,
						);
					};

					img.onerror = async () => {
						// resolve(new VertFile(f, to, converter));
						const reader = new FileReader();
						const file = new VertFile(f, to, converter);
						resolve(file);
						reader.onload = async (e) => {
							const tags = await new Promise<TagType>(
								(resolve, reject) => {
									jsmediatags.read(
										new Blob([
											new Uint8Array(
												e.target?.result as ArrayBuffer,
											),
										]),
										{
											onSuccess: (tag) => resolve(tag),
											onError: (error) => reject(error),
										},
									);
								},
							);
							const picture = tags.tags.picture;
							if (!picture) return;

							const blob = new Blob(
								[new Uint8Array(picture.data)],
								{
									type: picture.format,
								},
							);
							const url = URL.createObjectURL(blob);
							file.blobUrl = url;
						};
						reader.readAsArrayBuffer(f);
					};
				},
			);
		});
		let oldLen = files.files.length;
		files.files = [
			...files.files,
			...(await Promise.all(newFilePromises)).filter(
				(f) => typeof f !== "undefined",
			),
		];
		let newLen = files.files.length;
		log(["uploader"], `handled ${newLen - oldLen} files`);
		ourFiles = [];

		if (files.files.length > 0) goto("/convert");
	};
</script>

<svelte:head>
	<title>VERT.sh — Free, fast, and awesome file convert</title>
	<meta
		name="title"
		content="VERT.sh — Free, fast, and awesome file convert"
	/>
	<meta
		name="description"
		content="With VERT you can convert images to PNG, JPG, WEBP, GIF, AVIF, and more. No ads, no tracking, open source, and all processing is done on your device."
	/>
	<meta property="og:type" content="website" />
	<meta
		property="og:title"
		content="VERT.sh — Free, fast, and awesome file convert"
	/>
	<meta
		property="og:description"
		content="With VERT you can convert images to PNG, JPG, WEBP, GIF, AVIF, and more. No ads, no tracking, open source, and all processing is done on your device."
	/>
	<meta property="twitter:card" content="summary_large_image" />
	<meta
		property="twitter:title"
		content="VERT.sh — Free, fast, and awesome file convert"
	/>
	<meta
		property="twitter:description"
		content="With VERT you can convert images to PNG, JPG, WEBP, GIF, AVIF, and more. No ads, no tracking, open source, and all processing is done on your device."
	/>
</svelte:head>

{#snippet sellingPoint(text: string)}
	<li
		class="grid items-center gap-4"
		style="grid-template-columns: 2rem auto"
	>
		<div
			class="h-8 w-8 bg-accent-background text-accent-foreground rounded-full flex items-center justify-center"
		>
			<Check />
		</div>
		<span class="text-lg">{text}</span>
	</li>
{/snippet}

<div class="[@media(max-height:768px)]:block mt-10 picker-fly">
	<Uploader
		isMobile={data.isMobile || false}
		bind:files={ourFiles}
		onupload={runUpload}
		acceptedFormats={[
			...new Set(converters.flatMap((c) => c.supportedFormats)),
		]}
	/>
</div>

<div class="mt-20">
	<h1 class="text-3xl text-center font-display header-fly-in">
		Free, fast, and awesome file converting <span
			class="px-2 py-1 text-xl bg-accent-background text-accent-foreground rounded-lg"
			>BETA</span
		>
	</h1>
	<div class="flex justify-center mt-10">
		<div class="grid gap-4">
			<!-- {@render sellingPoint("Very fast, all processing done on device")}
			{@render sellingPoint("No ads, and open source")}
			{@render sellingPoint("Beautiful and straightforward UI")} -->
			{#each ["Very fast, all processing done on device", "No file or size limit", "No ads, and open source", "Beautiful and straightforward UI"] as text, i}
				<div class="fly-in" style="--delay: {i * 50}ms;">
					{@render sellingPoint(text)}
				</div>
			{/each}
		</div>
	</div>
</div>

<style>
	/* for this page specifically */
	:global(html, body) {
		height: 100%;
	}

	@keyframes fly-in {
		from {
			opacity: 0;
			transform: translateY(50px);
			filter: blur(18px);
		}
		to {
			opacity: 1;
			transform: translateY(0);
			filter: blur(0);
		}
	}

	@keyframes picker-fly {
		from {
			opacity: 0;
			transform: translateY(48px);
			filter: blur(18px);
		}
		to {
			opacity: 1;
			transform: translateY(0);
			filter: blur(0);
		}
	}

	@keyframes header-fly-in {
		from {
			opacity: 0;
			transform: translateY(30px) scale(0.9);
			filter: blur(18px);
		}
		to {
			opacity: 1;
			transform: translateY(0) scale(1);
			filter: blur(0);
		}
	}

	.header-fly-in {
		animation: header-fly-in var(--transition) 750ms forwards;
		opacity: 0;
	}

	.fly-in {
		animation: fly-in var(--transition) 750ms var(--delay) forwards;
		opacity: 0;
	}

	.picker-fly {
		animation: picker-fly var(--transition) 750ms forwards;
		opacity: 0;
	}
</style>
