<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(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))); }



// 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>