<script lang="ts">
	import { onMount } from 'svelte';
	import { FormGroup, Label, Input } from '@sveltestrap/sveltestrap';
	import type { SavedPoint } from '$domain';
	import { pointsApi } from '$api';
	import { addToast, ListEditor } from '$ui';
	import type { ListEditorApi, ListEditorConfig } from '$ui';
	import { t } from '$i18n';
	import { pointsStore } from './pointsStore';

	interface Props {
		isOpen?: boolean;
		onClose?: () => void;
		onSave?: (p: SavedPoint) => void;
		onSelectPoint?: (p: SavedPoint | null) => void;
		point?: SavedPoint | null;
	}

	let {
		isOpen = $bindable(false),
		onClose = () => {},
		onSave = (_: SavedPoint) => {},
		onSelectPoint = (_: SavedPoint | null) => {},
		point = null,
	}: Props = $props();

	let editorRef: ListEditor<SavedPoint> | null = $state(null);

	onMount(async () => {
		if ($pointsStore.length === 0) {
			try {
				pointsStore.set(await pointsApi.list());
			} catch (err: unknown) {
				addToast({
					header: $t('common.error'),
					body: (err as Error).message,
					color: 'danger',
				});
			}
		}
	});

	$effect(() => {
		if (point && editorRef) editorRef.open(point);
	});

	const config: ListEditorConfig = {
		showTable: true,
		closeOnSave: false,
		closeOnDelete: false,
		searchBy: ['name'],
		labels: {
			item: 'Point',
			itemGenitive: 'point',
			items: 'Points',
			add: 'Add',
			edit: 'Edit',
			save: 'Save',
			update: 'Update',
			delete: 'Delete',
			cancel: 'Cancel',
			close: 'Close',
			searchPlaceholder: 'Search by name...',
		},
	};

	const api: ListEditorApi<SavedPoint> = {
		save: (p) => pointsApi.create(p),
		update: (p) => pointsApi.update(p),
		delete: (p) => pointsApi.delete(p.id),
	};

	const factory = (): SavedPoint => ({ id: 0, name: '', lat: 0, lon: 0, alt: 0 });

	let items = $state<SavedPoint[]>($pointsStore);

	$effect(() => {
		items = $pointsStore;
	});

	$effect(() => {
		pointsStore.set(items);
	});

	export function open(p: SavedPoint | null = null, showTable: boolean = config.showTable ?? true) {
		editorRef?.open(p, showTable);
	}
</script>

<ListEditor
	bind:this={editorRef}
	bind:isOpen
	bind:items
	{api}
	{config}
	itemFactory={factory}
	onClose={() => onClose()}
	onSave={(p) => onSave(p)}
	onSelect={(p) => onSelectPoint(p)}>
	{#snippet tableHeader()}
		<tr>
			<th>{$t('points.name')}</th>
			<th>{$t('points.lat')}</th>
			<th>{$t('points.lon')}</th>
			<th>{$t('points.alt')}</th>
			<th class="fit"></th>
		</tr>
	{/snippet}

	{#snippet tableRow({ row })}
		<td>{row.name}</td>
		<td>{row.lat.toFixed(5)} °</td>
		<td>{row.lon.toFixed(5)} °</td>
		<td>{row.alt} м</td>
	{/snippet}

	{#snippet formFields({ item })}
		<div class="mb-2">
			<Label class="small">{$t('points.name')}</Label>
			<Input class="form-control-sm" type="text" bind:value={item.name} required />
		</div>
		<div class="d-flex gap-2">
			<FormGroup class="flex-grow-1">
				<Label class="small">{$t('points.lat')}</Label>
				<Input class="form-control-sm" type="number" step="any" bind:value={item.lat} required />
				<span class="form-text">{$t('points.degrees')}</span>
			</FormGroup>
			<FormGroup class="flex-grow-1">
				<Label class="small">{$t('points.lon')}</Label>
				<Input class="form-control-sm" type="number" step="any" bind:value={item.lon} required />
				<span class="form-text">{$t('points.degrees')}</span>
			</FormGroup>
			<FormGroup class="flex-grow-1">
				<Label class="small">{$t('points.alt')}</Label>
				<Input class="form-control-sm" type="number" step="any" bind:value={item.alt} required />
				<span class="form-text">{$t('points.metersAsl')}</span>
			</FormGroup>
		</div>
	{/snippet}
</ListEditor>
