<script lang="ts">
	import { onMount } from 'svelte';
	import { EditorView, placeholder as cmPlaceholder } from '@codemirror/view';
	import { EditorState } from '@codemirror/state';
	import { StreamLanguage } from '@codemirror/language';
	import { oneDark } from '@codemirror/theme-one-dark';
	import { getTheme } from '$lib/theme.svelte';

	let { value = '', onchange, rows = 6, placeholder = '' } = $props<{
		value: string;
		onchange: (val: string) => void;
		rows?: number;
		placeholder?: string;
	}>();

	let container: HTMLDivElement;
	let view: EditorView;
	const theme = getTheme();

	// Simple Jinja2 stream parser for syntax highlighting
	const jinjaLang = StreamLanguage.define({
		token(stream) {
			// Jinja2 comment {# ... #}
			if (stream.match('{#')) {
				stream.skipTo('#}') && stream.match('#}');
				return 'comment';
			}
			// Jinja2 expression {{ ... }}
			if (stream.match('{{')) {
				while (!stream.eol()) {
					if (stream.match('}}')) return 'variableName';
					stream.next();
				}
				return 'variableName';
			}
			// Jinja2 statement {% ... %}
			if (stream.match('{%')) {
				while (!stream.eol()) {
					if (stream.match('%}')) return 'keyword';
					stream.next();
				}
				return 'keyword';
			}
			// Regular text
			while (stream.next()) {
				if (stream.peek() === '{') break;
			}
			return null;
		},
	});

	onMount(() => {
		const extensions = [
			jinjaLang,
			EditorView.updateListener.of((update) => {
				if (update.docChanged) {
					onchange(update.state.doc.toString());
				}
			}),
			EditorView.lineWrapping,
			EditorView.theme({
				'&': { fontSize: '13px', fontFamily: "'Consolas', 'Monaco', 'Courier New', monospace" },
				'.cm-content': { minHeight: `${rows * 1.5}em`, padding: '8px' },
				'.cm-editor': { borderRadius: '0.375rem', border: '1px solid var(--color-border)' },
				'.cm-focused': { outline: '2px solid var(--color-primary)', outlineOffset: '0px' },
				// Jinja2 syntax colors
				'.ͼc': { color: '#e879f9' },  // keyword ({% %}) - purple
				'.ͼd': { color: '#38bdf8' },  // variableName ({{ }}) - blue
				'.ͼ5': { color: '#6b7280' },  // comment ({# #}) - gray
			}),
		];

		if (theme.isDark) {
			extensions.push(oneDark);
		}

		if (placeholder) {
			extensions.push(cmPlaceholder(placeholder));
		}

		view = new EditorView({
			state: EditorState.create({ doc: value, extensions }),
			parent: container,
		});

		return () => view.destroy();
	});

	$effect(() => {
		if (view && view.state.doc.toString() !== value) {
			view.dispatch({
				changes: { from: 0, to: view.state.doc.length, insert: value },
			});
		}
	});
</script>

<div bind:this={container}></div>
