import {EditorState, Compartment} from "@codemirror/state"
import {javascriptLanguage} from "@codemirror/lang-javascript"
import {htmlLanguage, html} from "@codemirror/lang-html"
import {css} from "@codemirror/lang-css"
import {markdown} from "@codemirror/lang-markdown"
import {xml} from "@codemirror/lang-xml"
import {oneDark} from "./theme-tf-dark.js"
import {EditorView, lineNumbers, highlightActiveLineGutter, highlightSpecialChars, highlightTrailingWhitespace, drawSelection, dropCursor, rectangularSelection, crosshairCursor, highlightActiveLine, keymap, highlightWhitespace} from '@codemirror/view';
import {language, foldGutter, indentUnit, indentOnInput, syntaxHighlighting, defaultHighlightStyle, bracketMatching, foldKeymap} from '@codemirror/language';
import {history, defaultKeymap, historyKeymap, indentWithTab} from '@codemirror/commands';
import {highlightSelectionMatches, search, searchKeymap} from '@codemirror/search';
import {autocompletion, closeBracketsKeymap, completionKeymap} from '@codemirror/autocomplete';
import {lintKeymap} from '@codemirror/lint';

let updateListenerExtension = EditorView.updateListener.of((update) => {
	if (update.docChanged && update.view.onDocChange) {
		update.view.onDocChange();
	}
});

/* https://codemirror.net/examples/config/ */
const languageConfig = new Compartment();

const extensions = [
	lineNumbers(),
	highlightActiveLineGutter(),
	highlightSpecialChars(),
	highlightWhitespace(),
	history(),
	foldGutter(),
	drawSelection(),
	dropCursor(),
	EditorState.allowMultipleSelections.of(true),
	indentOnInput(),
	indentUnit.of('\t'),
	syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
	bracketMatching(),
	autocompletion(),
	rectangularSelection(),
	crosshairCursor(),
	highlightActiveLine(),
	highlightSelectionMatches(),
	highlightTrailingWhitespace(),
	keymap.of([
		...defaultKeymap,
		...searchKeymap,
		...historyKeymap,
		...foldKeymap,
		...completionKeymap,
		...lintKeymap,
		indentWithTab,
	]),
	languageConfig.of(javascriptLanguage),
	search(),
	oneDark,
	updateListenerExtension,
];

function TildeFriendsEditorView(parent) {
	return new EditorView({
		extensions: extensions,
		parent: parent,
	});
}

function setEditorMode(view, mode) {
	const k_modes = {
		'css': css(),
		'html': html(),
		'javascript': javascriptLanguage,
		'markdown': markdown(),
		'xml': xml(),
	};
	view.dispatch({
		effects: languageConfig.reconfigure(k_modes[mode])
	});
}

export {
	TildeFriendsEditorView,
	EditorState,
	EditorView,
	extensions,
	setEditorMode,
};
