<script lang="ts">
	import { version } from '../../../package.json';
	import { i18n } from '$lib/i18n';
	import type { Snapshot } from '@sveltejs/kit';

	let search = '';

	type Entry = {
		id: string;
		label: string;
		icon: string;
	};

	type Test = Entry & {
		categories: Array<Category>;
		disabled?: boolean;
	};

	type Category = (typeof categories)[number]['id'] | (typeof superCategories)[number]['id'];

	let superCategories = [
		{
			id: 'inputs',
			label: 'Inputs',
			icon: 'ti-arrow-down-to-arc'
		},
		{
			id: 'outputs',
			label: 'Outputs',
			icon: 'ti-arrow-down-from-arc'
		}
	] as const satisfies Entry[];

	let categories = [
		{
			id: 'audio',
			label: 'Audio',
			icon: 'ti-volume'
		},
		{
			id: 'video',
			label: 'Video',
			icon: 'ti-video'
		},
		{
			id: 'control',
			label: 'Control',
			icon: 'ti-hand-finger'
		},
		{
			id: 'misc',
			label: 'Miscellaneous',
			icon: 'ti-circle-plus'
		}
	] as const satisfies Entry[];

	const tests: Test[] = [
		{
			id: 'card',
			label: 'Test Card',
			icon: 'ti-device-desktop',
			categories: ['outputs', 'video']
		},
		{
			id: 'audio',
			label: 'Audio',
			icon: 'ti-volume',
			categories: ['outputs', 'audio']
		},
		{
			id: 'av-sync',
			label: 'AV Sync',
			icon: 'ti-time-duration-off',
			categories: ['outputs', 'video', 'audio']
		},
		{
			id: 'keyboard',
			label: 'Keyboard',
			icon: 'ti-keyboard',
			categories: ['inputs', 'control']
		},
		{
			id: 'mouse',
			label: 'Mouse',
			icon: 'ti-mouse',
			categories: ['inputs', 'control']
		},
		{
			id: 'gamepad',
			label: 'Gamepad',
			icon: 'ti-device-gamepad',
			categories: ['inputs', 'control']
		},
		{
			id: 'camera',
			label: 'Camera',
			icon: 'ti-camera',
			categories: ['inputs', 'video']
		},
		{
			id: 'microphone',
			label: 'Microphone',
			icon: 'ti-microphone',
			categories: ['inputs', 'audio'],
			disabled: true
		},
		{
			id: 'sensors',
			label: 'Sensors',
			icon: 'ti-cpu-2',
			categories: ['inputs', 'misc'],
			disabled: true
		},
		{
			id: 'internet',
			label: 'Internet speed',
			icon: 'ti-world',
			categories: ['inputs', 'outputs', 'misc']
		},
		{
			id: 'timer',
			label: 'High resolution timer',
			icon: 'ti-alarm',
			categories: ['video']
		}
	];

	let filteredTests: Test[] = tests;
	let filteredCategories: Category[] = [];

	function doSearch(search: string) {
		filteredTests = tests.filter((test) => {
			if (!search) return true;

			const searchValue = search.toLocaleLowerCase();
			return (
				test.label.includes(searchValue) ||
				test.id.includes(searchValue) ||
				$i18n.t(`tests.${test.id}.description`).includes(searchValue)
			);
		});
	}
	$: doSearch(search);

	function setFilter(category: Category) {
		if (filteredCategories.includes(category)) {
			filteredCategories = filteredCategories.filter((c) => c !== category);
		} else {
			filteredCategories = [...filteredCategories, category];
		}
	}

	$: nonEmptyCategories = categories.filter((category) => {
		const categoryTests = filteredTests.filter((test) => test.categories.includes(category.id));
		return categoryTests.some(
			(test) =>
				!filteredCategories.length || filteredCategories.every((f) => test.categories.includes(f))
		);
	});

	export const snapshot: Snapshot<string> = {
		capture: () => JSON.stringify({ filtered: filteredCategories, search }),
		restore: (value) => {
			const { filtered: restoredFiltered, search: restoredSearch } = JSON.parse(value);
			filteredCategories = restoredFiltered;
			search = restoredSearch;
		}
	};
</script>

<h1>Total Tech Test</h1>

<nav>
	<!-- svelte-ignore a11y-autofocus -->
	<input type="search" placeholder={$i18n.t('Search')} bind:value={search} autofocus />

	<div class="options">
		{#each superCategories as category}
			<button
				on:click={() => setFilter(category.id)}
				class:active={!filteredCategories.length || filteredCategories.includes(category.id)}
				class="super"
			>
				<i class="ti {category.icon}"></i>
				{$i18n.t(category.label)}
			</button>
		{/each}
		<div class="separator"></div>
		{#each categories as category}
			<button
				on:click={() => setFilter(category.id)}
				class:active={!filteredCategories.length || filteredCategories.includes(category.id)}
			>
				<i class="ti {category.icon}"></i>
				{$i18n.t(category.label)}
			</button>
		{/each}
	</div>
	<div class="tests">
		{#each nonEmptyCategories as category}
			{#if tests.filter((test) => test.categories.includes(category.id)).length > 0}
				<h2>{$i18n.t(category.label)}</h2>
				{#each filteredTests.filter((test) => test.categories.includes(category.id) && filteredCategories.every( (f) => test.categories.includes(f) )) as test}
					<div class="test" class:disabled={test.disabled}>
						<a class="test" href={test.id}>
							<span class="label">
								<i class="ti {test.icon}"></i>
								{$i18n.t(test.label)}
							</span>
							<span class="description">
								{$i18n.t(`tests.${test.id}.description`)}
							</span>
						</a>
					</div>
				{/each}
			{/if}
		{:else}
			<p>
				{$i18n.t('No tests found.')}
			</p>
		{/each}
	</div>
</nav>
<footer><a href="https://git.thm.place/thm/test-card">testcard v{version}</a></footer>

<style>
	nav {
		display: flex;
		flex-direction: column;
		gap: 1rem;
		flex-grow: 1;
		padding: 0 4rem;
		overflow: auto;

		& input[type='search'] {
			padding: 0.5em;
			width: 100%;
		}
	}

	h1 {
		text-align: center;
		font-size: 3rem;
		margin: 1rem;
		text-transform: uppercase;
	}

	h2 {
		margin: 0.25em 0;
	}

	.options {
		display: flex;
		justify-content: space-evenly;
		align-items: center;
		gap: 2em;

		& button {
			border: none;
			background: none;
			display: flex;
			flex-direction: column;

			opacity: 0.66;

			&.active {
				opacity: 1;
			}
		}

		& .separator {
			border-left: 1px solid currentColor;
			height: 3rem;
			opacity: 0.8;
		}

		& a {
			text-align: center;
			text-decoration: none;
			white-space: nowrap;

			&.disabled {
				pointer-events: none;
				opacity: 0.5;
			}
		}

		& .ti {
			display: block;
			font-size: 3rem;
		}
	}

	.test {
		display: flex;
		gap: 0.5em;
		margin-bottom: 0.25em;

		& .label {
			white-space: nowrap;
		}

		& .description {
			opacity: 0.85;
		}

		& a {
			text-decoration: none;
			color: inherit;
		}

		&.disabled {
			opacity: 0.5;
			pointer-events: none;
		}
	}

	footer {
		text-align: center;
		opacity: 0.6;
		margin-top: 1rem;

		& a {
			text-decoration: none;
		}
	}
</style>
