<script lang="ts" module>
	const getTimeZonePart = (
		timeZone: string,
		timeZoneName: Intl.DateTimeFormatOptions['timeZoneName']
	) => {
		return new Intl.DateTimeFormat('en', {
			timeZone,
			timeZoneName
		})
			.formatToParts()
			.find((part) => part.type === 'timeZoneName')?.value;
	};

	// wbr takes a string and adds a <wbr> tag after each forward slash
	const wbr = (str: string): string => {
		return str.replace(/\//g, '/<wbr />');
	};
</script>

<script lang="ts">
	import ExpandableCombobox, { type ComboboxItem } from './Combobox.svelte';

	let {
		label,
		name,
		value = $bindable(''),
		invalidMessage,
		required
	}: {
		label?: string;
		name: string;
		value?: string;
		invalidMessage?: string;
		required?: boolean;
	} = $props();

	const sortedTimeZones = Intl.supportedValuesOf('timeZone')
		.map((timeZone) => {
			// get short offset (e.g. GMT+1) for the timezone
			const offset = getTimeZonePart(timeZone, 'shortOffset');
			// if (!offset) return null;

			// get long representation (e.g. Pacific Standard Time) for the timezone
			const long = getTimeZonePart(timeZone, 'long');

			// get short representation (e.g. PST) for the timezone
			const short = getTimeZonePart(timeZone, 'short');

			return {
				timeZone,
				offset,
				long,
				short
			};
		})
		.filter((timeZone) => timeZone !== null)
		.sort((a, b) => {
			return a.timeZone.localeCompare(b.timeZone);
		});

	const options: ComboboxItem[] = sortedTimeZones.map((timeZone) => {
		const infotext = [...new Set([timeZone.short, timeZone.offset])]
			.filter((item) => item !== undefined)
			.join(' · ');

		return {
			value: timeZone.timeZone,
			label: `${timeZone.timeZone.replaceAll('_', ' ')}`,
			preview: timeZone.long,
			infotext: infotext,
			render: timezoneLabel
		};
	});
	const optionsMap = options.reduce(
		(acc, option) => {
			acc[option.value] = option;
			return acc;
		},
		{} as Record<string, ComboboxItem>
	);

	let timezone = $state<ComboboxItem | undefined>(
		optionsMap[Intl.DateTimeFormat().resolvedOptions().timeZone]
	);

	$effect(() => {
		console.log(`timezone="${timezone?.value}"`);
	});
</script>

<ExpandableCombobox
	{label}
	{name}
	{invalidMessage}
	{required}
	bind:value={timezone}
	items={options}
	matchWidth
	placeholder="Select a timezone"
/>

{#snippet timezoneLabel(item: ComboboxItem)}
	{@html wbr(item.label ?? 'Missing label')}
{/snippet}
