<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 {
		EditorView,
		keymap,
		highlightSpecialChars,
		drawSelection,
		highlightActiveLine,
		dropCursor,
		rectangularSelection,
		crosshairCursor,
		gutter,
		GutterMarker,
		highlightActiveLineGutter,
		lineNumbers,
		placeholder as placeholderExt
	} from '@codemirror/view';
	import { EditorState, RangeSet, StateEffect, type Extension, Text } from '@codemirror/state';
	import { defaultKeymap, history, historyKeymap, indentWithTab } from '@codemirror/commands';
	import { indentUnit } from '@codemirror/language';
	import { languages } from '@codemirror/language-data';
	// import {
	//     defaultHighlightStyle, syntaxHighlighting, indentOnInput,
	//     bracketMatching, foldGutter, foldKeymap
	//     } from "@codemirror/language"
	// import {
	//     defaultHighlightStyle, syntaxHighlighting, indentOnInput,
	//     bracketMatching, foldGutter, foldKeymap
	//     } from "@codemirror/language"
	// import {
	//     searchKeymap, highlightSelectionMatches
	//     } from "@codemirror/search"
	// import {
	//     autocompletion, completionKeymap, closeBrackets,
	//     closeBracketsKeymap
	//     } from "@codemirror/autocomplete"
	// import {lintKeymap} from "@codemirror/lint"

	// import { } from '@codemirror/gutter'; // Merged into @codemirror/view
	import { basicSetup } from 'codemirror';
	import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
	// import { css } from '@codemirror/lang-css';
	// import { javascript } from '@codemirror/lang-javascript';
	// import { json } from '@codemirror/lang-json';
	// import { html } from '@codemirror/lang-html';
	import { oneDark } from '@codemirror/theme-one-dark';

	// 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 theme: Extension = EditorView.baseTheme(); // EditorView.baseTheme(); // oneDark

	export let extensions: Extension[] = [];

	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: EditorView;

	// theme = [
	//     // baseTheme,
	//     theme,
	// ];
	// console.log(`Theme:`, theme);

	if (theme_mode == 'dark') {
		theme = oneDark;
	} else {
		// theme = EditorView.baseTheme({
		//     "&": {
		//         color: "black",
		//         backgroundColor: "white"
		//     },
		//     ".cm-cursor, .cm-dropCursor": { borderLeftColor: "#000" },
		//     "&.cm-focused .cm-selectionBackground, ::selection": {
		//         backgroundColor: "#B7D5FF"
		//     },
		//     "&.cm-focused .cm-selectionForeground": { color: "black" }
		// });
	}

	if (editable) {
		extensions.push(EditorView.editable.of(true));
	} else {
		// extensions.push(EditorState.editable.of(false));
	}
	if (readonly) {
		extensions.push(EditorState.readOnly.of(true));
	} else {
		// extensions.push(EditorState.readOnly.of(false));
	}

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

	if (show_line_numbers) {
		// extensions.push(lineNumbers({ class: "line-numbers" }));
	} else {
		// extensions.push(gutter({ class: "hidden-gutter" }));
		// extensions.push(lineNumbers(false));
		// extensions.push(gutter(false));
		// extensions.pop();
		// extensions.slice(extensions.indexOf(lineNumbers), 1);
	}

	if (wrap_lines) {
		extensions.push(EditorView.lineWrapping);
	}

	if (use_tab) {
		extensions.push(keymap.of([indentWithTab]));
	}
	if (tab_size) {
		extensions.push(indentUnit.of(' '.repeat(tab_size)));
	}

	// Enable spell check
	extensions.push(EditorView.contentAttributes.of({ spellcheck: 'true' }));

	// let languages = [
	//     { name: 'CSS', mode: 'css' },
	//     { name: 'HTML', mode: 'html' },
	//     { name: 'JavaScript', mode: 'javascript' },
	//     { name: 'Markdown', mode: 'markdown' },
	//     { name: 'Python', mode: 'python' },
	// ];

	// Reactive declaration for extensions
	$: editor_extensions = [
		basicSetup,
		// gutter({class: "hidden-gutter"}),
		// A line number gutter
		lineNumbers(false),
		// A gutter with code folding markers
		// foldGutter(false),
		// lineWrapping(false),
		// EditorView.lineWrapping, // Enable line wrapping

		// EditorView.indentUnit.of(" ".repeat(tab_size)),
		// EditorView.tabSize.of(tab_size),
		// indentUnit.of(" ".repeat(tab_size)),

		// EditorView.editable.of(editable),
		// EditorState.readOnly.of(readonly),

		// EditorState.tabSize.of(tab_size),
		// keymap.of([indentWithTab]),
		// placeholderExt(placeholder),
		// language,
		markdown({ base: markdownLanguage, codeLanguages: languages }),
		// javascript({typescript: true}),
		// json(),
		// css(),
		// html(),
		theme,

		...extensions
	];

	// baseTheme = {
	//     ".cm-o-replacement": {
	//         display: "inline-block",
	//         width: ".5em",
	//         height: ".5em",
	//         borderRadius: ".25em"
	//     },
	//     "&light .cm-o-replacement": {
	//         backgroundColor: "#04c"
	//     },
	//     "&dark .cm-o-replacement": {
	//         backgroundColor: "#5bf"
	//     }
	// },
	// let dimensions = {
	//         width: '100%',
	//         height: 'calc(100vh - 48px)' // Adjust for header and other elements
	//     };
	// editorView.setSize(dimensions.width, dimensions.height);

	// Initialize CodeMirror on mount
	onMount(() => {
		editorView = new EditorView({
			state: EditorState.create({
				doc: content,
				extensions: editor_extensions
			}),
			parent: editor_element, // document.body
			dispatch: (transaction) => {
				editorView.update([transaction]);
				if (transaction.docChanged) {
					new_content = editorView.state.doc.toString();
					const newContent = editorView.state.doc.toString();
					// dispatch('change', newContent);
				}
			}
		});
	});

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

	// Update editor content when `content` prop changes
	$: if (editorView && editorView.state.doc.toString() !== content) {
		editorView.setState(
			EditorState.create({
				doc: content,
				extensions: editor_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>
