<script lang="ts">
	import { onMount, onDestroy } from 'svelte';
	import { Map as MapView, plotAnimatedMarker, plotPrediction, type IMap } from '$map';
	import { Navbar } from '$features/auth';
	import { PanelContainer, CollapsibleCard } from '$ui';
	import { TelemetryPanel, DeviationChart, telemetryStore } from '$features/tracking';
	import { workspacesStore } from '$features/workspaces';
	import { t } from '$i18n';
	import { requireAuthenticated } from '$auth';
	import { parseTelemetry } from '$domain';
	import type { Prediction } from '$domain';

	let selectedId = $state('');
	const workspacesWithResult = $derived($workspacesStore.items.filter((w) => w.result !== null));
	const selectedPrediction = $derived<Prediction | null>(
		workspacesWithResult.find((w) => w.id === selectedId)?.result ?? null,
	);

	let map = $state<IMap | null>(null);
	// Tracks whether we've already fitted the map to the initial history load.
	// Not reactive — written as a side effect inside $effect to avoid re-triggering.
	let fittedBounds = false;

	onMount(() => {
		requireAuthenticated('/login');
	});

	onDestroy(() => {
		map?.disposeScene('telemetry');
		map?.disposeScene('prediction');
	});

	$effect(() => {
		if (!map) return;
		const scene = map.scene('prediction');
		if (selectedPrediction) {
			plotPrediction(scene, selectedPrediction, { color: '#1565C0', opacity: 0.7 });
		} else {
			scene.clear();
		}
	});

	function onMapReady(m: IMap) {
		map = m;
	}

	$effect(() => {
		if (!map) return;

		const points = telemetryStore.points;
		const scene = map.scene('telemetry');

		if (points.length === 0) {
			scene.clear();
			fittedBounds = false;
			return;
		}

		let telemetry;
		try {
			telemetry = parseTelemetry(points);
		} catch {
			return;
		}

		const latest = points[points.length - 1];

		scene.clear();

		scene.addLine('path', {
			coords: telemetry.flight_path,
			color: '#FF1744',
			width: 3,
		});

		scene.addMarker('launch', {
			lngLat: [telemetry.launch.latlng.lng, telemetry.launch.latlng.lat],
			iconUrl: '/target-blue.png',
			iconSize: [12, 12],
			popupHtml: `<b>Launch</b><br>${telemetry.launch.latlng.lat.toFixed(6)}, ${telemetry.launch.latlng.lng.toFixed(6)}`,
		});

		plotAnimatedMarker(scene, latest.longitude, latest.latitude);

		if (!fittedBounds && telemetry.flight_path.length > 0) {
			map.fitBounds(telemetry.flight_path, 50);
			fittedBounds = true;
		}
	});
</script>

<main>
	<Navbar />
	<div style="height: var(--navbar-height);"></div>
	<MapView onReady={onMapReady}>
		<PanelContainer position="left">
			<TelemetryPanel />
		</PanelContainer>
		<PanelContainer position="right">
			<CollapsibleCard title={$t('tracking.deviation')}>
				<div class="mb-2">
					<label for="forecast-select" class="form-label small mb-1">{$t('tracking.selectForecast')}</label>
					<select
						id="forecast-select"
						class="form-select form-select-sm"
						bind:value={selectedId}
						disabled={workspacesWithResult.length === 0}
					>
						<option value="">{$t('tracking.noForecast')}</option>
						{#each workspacesWithResult as w (w.id)}
							<option value={w.id}>{w.name}</option>
						{/each}
					</select>
				</div>
				<DeviationChart points={telemetryStore.points} prediction={selectedPrediction} />
			</CollapsibleCard>
		</PanelContainer>
	</MapView>
</main>
