<script context="module" lang="ts">
	import mitt from 'mitt';

	export type AddEvents = {
		choose: void;
		files: File[];
		urls: string[];
	};
	export const addEmitter = mitt<AddEvents>();
</script>

<script lang="ts">
	import Icon from './utils/Icon.svelte';
	import IconButton from './utils/IconButton.svelte';
	import ProgressBar from './utils/ProgressBar.svelte';
	import api from '$lib/api';
	import { goto } from '$app/navigation';
	import { i18n } from '$lib/i18n';
	import { selected } from '$lib/components/EntitySelect.svelte';

	let files: File[] = [];
	let URLs: string[] = [];
	let uploading = false;

	let progress: Record<string, number> = {};
	let totalProgress: number | undefined;

	$: visible = files.length + URLs.length > 0;

	addEmitter.on('files', (ev) => {
		ev.forEach((file) => {
			if (!files.map((f) => `${f.name}${f.size}`).includes(`${file.name}${file.size}`)) {
				files.push(file);
			}
			files = files;
		});
	});

	async function upload() {
		uploading = true;

		try {
			const addresses: string[] = [];
			for (const file of files) {
				const address = await api.putBlob(file, {
					onProgress: (p) => {
						progress[file.name] = (p.loaded / p.total) * 100;
						totalProgress = Object.values(progress).reduce((a, b) => a + b, 0) / files.length;
					},
					timeout: -1
				});
				addresses.push(address);
			}

			if (addresses.length == 1) {
				goto(`/browse/${addresses[0]}`);
			} else {
				$selected = addresses;
				goto(`/browse/selected`);
			}
		} catch (error) {
			alert(error);
		}

		uploading = false;
		reset();
	}

	function reset() {
		if (!uploading) {
			files = [];
			URLs = [];
			progress = {};
		}
	}

	function onKeydown(event: KeyboardEvent) {
		if (!files.length) return;
		if (event.key === 'Enter') {
			event.preventDefault();
			upload();
		}
		if (event.key === 'Escape') {
			reset();
		}
	}
</script>

<svelte:body on:keydown={onKeydown} />

<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-static-element-interactions -->
<div class="addmodal-container" class:visible class:uploading on:click={reset}>
	<div class="addmodal" on:click|stopPropagation>
		<div class="files">
			{#each files as file}
				<div class="entry">
					<div class="row">
						<div class="file">
							<div class="icon">
								<Icon name="file" />
							</div>
							<div class="label">{file.name}</div>
							{#if file.type.startsWith('image')}
								<img src={URL.createObjectURL(file)} alt="To be uploaded." />
							{/if}
						</div>
						{#if !uploading}
							<IconButton
								small
								subdued
								color="#dc322f"
								name="x-circle"
								on:click={() => (files = files.filter((f) => f !== file))}
							/>
						{/if}
					</div>
					{#if uploading && files.length > 1}
						<div class="progress">
							<ProgressBar value={progress[file.name] || 0} />
						</div>
					{/if}
				</div>
			{/each}
			{#if !uploading}
				<div class="entry add">
					<IconButton outline name="plus-circle" on:click={() => addEmitter.emit('choose')} />
				</div>
			{/if}
		</div>
		<div class="controls">
			<IconButton small disabled={uploading} name="upload" on:click={upload}>
				{$i18n.t('Upload')}
			</IconButton>
		</div>
		{#if uploading}
			<div class="progress">
				<ProgressBar value={totalProgress} />
			</div>
		{/if}
	</div>
</div>

<style lang="scss">
	.addmodal-container {
		position: absolute;
		left: 0;
		top: 0;
		width: 100vw;
		height: 100vh;
		background: rgba(0, 0, 0, 0.5);
		color: var(--foreground);

		display: none;

		&.visible {
			display: unset;
		}

		&.uploading {
			cursor: progress;

			.addmodal {
				filter: brightness(0.85);
			}
		}
	}

	.addmodal {
		position: absolute;
		left: 50%;
		top: 50%;
		transform: translate(-50%, -50%);

		background: var(--background);

		color: var(--foreground);
		border: solid 2px var(--foreground);
		border-radius: 8px;
		padding: 1rem;
		min-width: 33vw;
	}

	.files {
		display: flex;
		flex-direction: column;
		gap: 1em;

		padding: 0.5em;

		overflow-y: auto;
		max-height: 66vh;
		width: 80vw;
	}

	.entry .row {
		display: flex;
		align-items: center;
		gap: 0.5rem;
	}

	.file {
		flex-grow: 1;
		display: flex;
		align-items: center;
		gap: 1rem;

		border: 1px solid var(--foreground);
		border-radius: 4px;
		background: var(--background-lighter);
		padding: 0.5em;

		img {
			max-height: 12em;
			max-width: 12em;
		}

		.icon {
			font-size: 24px;
		}

		.label {
			flex-grow: 1;
		}
	}

	.entry.add {
		display: flex;
		flex-direction: column;
		font-size: 1.5em;
	}

	.controls {
		display: flex;
		justify-content: center;
		font-size: 3em;
		margin-top: 0.5rem;
	}

	.progress {
		margin-top: 0.5rem;
		margin-bottom: 0.5rem;
	}
</style>
