<script lang="ts">
	import { json } from '@codemirror/lang-json';
	import { markdown } from '@codemirror/lang-markdown';
	import {
		compileTemplate,
		getTemplate,
		listTemplates,
		parseMarkdown,
		parseMarkdownWithTemplate,
		wasmReady,
		type ParseResultSuccess
	} from '../wasm';
	import EditorPanel from './EditorPanel.svelte';

	let templates = $state([] as string[]);

	const DEFAULT_MARKDOWN_VALUE = `---
_type: Recipe
author.name: Max Richter
---

# Baguette

My favourite baguette recipe

## Ingredients
- Flour
- Water
- Salt

## Steps
1. Mix Flour Water and Salt
2. Bake the bread`;

	const DEFAULT_TEMPLATE_VALUE = '';

	let templateValue = $state(
		typeof window !== 'undefined'
			? localStorage.getItem('templateValue') || DEFAULT_TEMPLATE_VALUE
			: DEFAULT_TEMPLATE_VALUE
	);
	let markdownValue = $state(
		typeof window !== 'undefined'
			? localStorage.getItem('markdownValue') || DEFAULT_MARKDOWN_VALUE
			: DEFAULT_MARKDOWN_VALUE
	);

	let jsonOutput = $state('');
	let detectedSchemaName = $derived.by(() => {
		try {
			return JSON.parse(jsonOutput)['_schema'];
		} catch {
			return undefined;
		}
	});

	let timings = $state<ParseResultSuccess['timings'] | null>(null);
	let templateStatus = $state<'success' | 'error' | 'indeterminate' | undefined>(undefined);
	let dataStatus = $state<'success' | 'error' | 'indeterminate' | undefined>(undefined);
	let templateError = $state<string | undefined>();

	$effect(() => {
		if (typeof window !== 'undefined') {
			localStorage.setItem('templateValue', templateValue);
		}
	});

	$effect(() => {
		if (typeof window !== 'undefined') {
			localStorage.setItem('markdownValue', markdownValue);
		}
	});

	$effect(() => {
		if ($wasmReady) {
			try {
				templates = listTemplates();
			} catch (e) {
				console.error(e);
			}
		}
		if (!$wasmReady) {
			jsonOutput = 'Loading wasm...';
			timings = null;
			templateStatus = undefined;
			dataStatus = undefined;
			return;
		}
		try {
			const compiledTemplate = compileTemplate(templateValue);
			console.log({ compiledTemplate, templateValue });

			const result = templateValue
				? parseMarkdownWithTemplate(markdownValue, templateValue)
				: parseMarkdown(markdownValue);

			if ('error' in result) {
				jsonOutput = '';
				if (result.error.startsWith('failed to compile template')) {
					templateError = result.error.replaceAll(' -> ', '\n ⟶ ');
					templateStatus = 'error';
					dataStatus = 'indeterminate';
				} else {
					templateError = undefined;
					templateStatus = undefined;
					dataStatus = 'error';
				}
			} else {
				templateError = undefined;
				jsonOutput = JSON.stringify(result, null, 2);
				timings = result.timings;
				templateStatus = 'success';
				dataStatus = 'success';
			}
		} catch (e: unknown) {
			console.log({ e });
			jsonOutput = (e as Error).message;
			timings = null;
			if (jsonOutput.startsWith('failed to compile template')) {
				templateStatus = 'error';
				dataStatus = 'indeterminate';
			} else {
				templateStatus = undefined;
				dataStatus = 'error';
			}
		}
	});

	function loadTemplate(name: string) {
		if (!name) return;
		try {
			templateValue = getTemplate(name);
		} catch (e) {
			console.error(e);
		}
	}

	function resetMarkdown() {
		markdownValue = DEFAULT_MARKDOWN_VALUE;
	}
</script>

<div class="flex flex-1 overflow-hidden">
	<div class="grid flex-1 grid-cols-1 overflow-hidden lg:grid-cols-3">
		<EditorPanel
			title="Markdown"
			bind:value={markdownValue}
			placeholder="Enter your markdown content here..."
			timing={timings?.markdown_parsing}
			subtitle="Your source content"
			langExtension={markdown()}
		>
			{#snippet headerActions()}
				<button
					onclick={resetMarkdown}
					class="rounded border border-gray-300 bg-white px-2 py-1 text-xs text-gray-700 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500"
				>
					Reset
				</button>
			{/snippet}
		</EditorPanel>

		<EditorPanel
			title="Template"
			bind:value={templateValue}
			placeholder="Enter your Marka template here..."
			error={templateError}
			status={templateStatus}
			timing={timings?.template_compilation}
			subtitle="Define your mapping schema"
			langExtension={markdown()}
		>
			{#snippet headerActions()}
				<select
					onchange={(e) => loadTemplate(e.currentTarget.value)}
					class="rounded border border-gray-300 bg-white px-2 py-1 text-xs text-gray-700 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500"
				>
					<option value="">Load a template</option>
					{#each templates as template (template)}
						<option value={template}>{template}</option>
					{/each}
				</select>
			{/snippet}
		</EditorPanel>

		<EditorPanel
			title="Data"
			value={jsonOutput}
			readonly={true}
			status={dataStatus}
			subtitle="Parsed JSON output"
			pillText={!templateValue && detectedSchemaName
				? `Detected Template: ${detectedSchemaName}`
				: undefined}
			langExtension={json()}
		/>
	</div>
</div>
