<script lang="ts">
	// This will be the wrapper for the CodeMirror editor. It should hide most of the configuration requirements.
	// WARNING: This has not been fully updated to Svelte version 5. It is a work in progress.
	// *** Import Svelte version 5 specific
	import { browser } from '$app/environment';

	import { onMount, onDestroy } from 'svelte';
	import { ensureCodeMirrorModules } from '../elements/codemirror_modules';

	// Props
	export let content: string = 'test test test test';
	export let new_content: string = '';

	// export let language: Extension = markdown(); // javascript()
	export let theme_mode: string = 'light'; // 'dark' | 'light'
	export let extensions: any[] = []; // Changed to any[] because Extension type is not directly available here

	export let editable: boolean = true;
	export let readonly: boolean = false;

	export let placeholder: string = 'Start typing...';

	export let show_line_numbers: boolean = false;
	export let wrap_lines: boolean = true;
	export let use_tab: boolean = true;
	export let tab_size: number = 4;
	let classes = '';
	export { classes as class };

	let editor_element: HTMLDivElement;
	let editorView: any; // Changed to any

	let cm_modules: any; // To hold the dynamically loaded CodeMirror modules

	async function initializeCodeMirror() {
		if (!browser) return;

		cm_modules = await ensureCodeMirrorModules();
		if (!cm_modules) return;

		// Reactive declaration for extensions
		let editor_extensions = [
			// Core extensions
			cm_modules.highlightSpecialChars(),
			cm_modules.history(),
			cm_modules.foldGutter(),
			cm_modules.drawSelection(),
			cm_modules.dropCursor(),
			cm_modules.EditorState_allowMultipleSelections.of(true),
			cm_modules.indentOnInput(),
			cm_modules.bracketMatching(),
			cm_modules.closeBrackets(),
			cm_modules.autocompletion(),
			cm_modules.rectangularSelection(),
			cm_modules.crosshairCursor(),
			cm_modules.highlightActiveLine(),
			cm_modules.highlightActiveLineGutter(),
			cm_modules.keymap.of([
				...cm_modules.defaultKeymap,
				...cm_modules.searchKeymap,
				...cm_modules.historyKeymap,
				...cm_modules.foldKeymap,
				...cm_modules.completionKeymap,
				...cm_modules.lintKeymap
			]),
			cm_modules.markdown({
				base: cm_modules.markdownLanguage,
				codeLanguages: cm_modules.languages
			}),
			theme_mode == 'dark' ? cm_modules.oneDark : cm_modules.EditorView.baseTheme(),
			cm_modules.EditorView.contentAttributes.of({ spellcheck: 'true' }), // Enable spell check

			// Conditional extensions based on props
			editable ? cm_modules.EditorView.editable.of(true) : null,
			readonly ? cm_modules.EditorState.readOnly.of(true) : null,
			placeholder ? cm_modules.placeholderExt(placeholder) : null,
			show_line_numbers ? cm_modules.lineNumbers() : null,
			wrap_lines ? cm_modules.EditorView_lineWrapping : null,
			use_tab ? cm_modules.keymap.of([cm_modules.indentWithTab]) : null,
			tab_size ? cm_modules.indentUnit.of(' '.repeat(tab_size)) : null,

			...extensions // Add any custom extensions passed in props
		].filter(Boolean);

		editorView = new cm_modules.EditorView({
			state: cm_modules.EditorState.create({
				doc: content,
				extensions: editor_extensions
			}),
			parent: editor_element,
			dispatch: (transaction: any) => {
				editorView.update([transaction]);
				if (transaction.docChanged) {
					new_content = editorView.state.doc.toString();
				}
			}
		});
	}

	// Initialize CodeMirror on mount
	onMount(async () => {
		await initializeCodeMirror();
	});

	// Clean up on destroy
	onDestroy(() => {
		editorView?.destroy();
	});

	// Update editor content when `content` prop changes
	$: if (cm_modules && editorView && editorView.state.doc.toString() !== content) {
		editorView.setState(
			cm_modules.EditorState.create({
				doc: content,
				extensions: editor_extensions // Use the reactive extensions
			})
		);
	}
</script>

{#if browser}
	<!-- flex flex-col flex-wrap items-center justify-center -->
	<div
		bind:this={editor_element}
		class="codemirror-wrapper h-100 max-h-full w-100 max-w-6xl {classes}"
	></div>
{:else}
	<div class="scm-waiting {classes}">
		<div class="scm-waiting__loading scm-loading">
			<p class="scm-loading__text">Loading editor...</p>
		</div>

		<pre class="scm-pre cm-editor">{content}</pre>
	</div>
{/if}

<style>
	/* .codemirror-wrapper :global(.cm-focused) {
    outline: none;
} */

	.codemirror-wrapper {
		flex-grow: 1;
		/* flex-shrink: 1; */
		/* flex-basis: 100%; */

		/* font-size: 1rem; */
		width: 100%;
		max-width: 100%;
		height: 100%;
		max-height: 100%;
		/* overflow: auto; */
		/* background-color: var(--cm-background); */

		/* text-wrap: normal; */
		/* text-wrap: balance; */
		/* text-wrap: wrap; */
		/* text-wrap: break-word; */
	}
	.codemirror-wrapper :global(.cm-editor) {
		/* font-size: .8rem; */
		/* text-wrap: normal; */
		/* text-wrap: balance; */
		/* text-wrap: wrap; */
		/* text-wrap: break-word; */

		/* max-width: 100%; */
		/* max-height: 100%; */

		/* overflow: auto; */

		/* width: 100%; */
		/* height: 100%; */

		/* background-color: var(--cm-background); */
		/* color: var(--cm-text); */
	}

	/* .codemirror-wrapper :global(.cm-gutters) {
    background-color: var(--cm-gutter-background);
    color: var(--cm-gutter-text);
}
.codemirror-wrapper :global(.cm-gutter) {
    background-color: var(--cm-gutter-background);
    color: var(--cm-gutter-text);
}
.codemirror-wrapper :global(.cm-gutterElement) {
    background-color: var(--cm-gutter-background);
    color: var(--cm-gutter-text);
} */
</style>
