import { MXValueComponent, AXValuableComponent, AXComponent } from '@acorex/cdk/common';
import { AXPlatform } from '@acorex/core/platform';
import { isPlatformBrowser, CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { InjectionToken, inject, Injectable, input, output, viewChild, PLATFORM_ID, DestroyRef, signal, computed, afterNextRender, effect, forwardRef, Component, NgModule } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';

class PrettierFormatterPlugin {
    constructor() {
        this.id = 'prettier';
        this.name = 'Prettier';
        this.version = '1.0.0';
        this.languages = ['javascript', 'js', 'typescript', 'ts', 'json', 'html', 'css', 'markdown'];
    }
    async format(text, language) {
        try {
            const prettier = await import('prettier/standalone');
            let parser = null;
            const plugins = [];
            switch (language) {
                case 'javascript':
                case 'js': {
                    const [babel, estree] = await Promise.all([
                        import('prettier/plugins/babel'),
                        import('prettier/plugins/estree'),
                    ]);
                    plugins.push(babel, estree);
                    parser = 'babel';
                    break;
                }
                case 'typescript':
                case 'ts': {
                    const [typescript, estree] = await Promise.all([
                        import('prettier/plugins/typescript'),
                        import('prettier/plugins/estree'),
                    ]);
                    plugins.push(typescript, estree);
                    parser = 'typescript';
                    break;
                }
                case 'json': {
                    const [babel, estree] = await Promise.all([
                        import('prettier/plugins/babel'),
                        import('prettier/plugins/estree'),
                    ]);
                    plugins.push(babel, estree);
                    parser = 'json';
                    break;
                }
                case 'html': {
                    const html = await import('prettier/plugins/html');
                    plugins.push(html);
                    parser = 'html';
                    break;
                }
                case 'css': {
                    const postcss = await import('prettier/plugins/postcss');
                    plugins.push(postcss);
                    parser = 'css';
                    break;
                }
                case 'markdown': {
                    const markdown = await import('prettier/plugins/markdown');
                    plugins.push(markdown);
                    parser = 'markdown';
                    break;
                }
                default:
                    return null;
            }
            if (!parser)
                return null;
            const formatted = await prettier.format(text, {
                parser,
                plugins,
            });
            return formatted;
        }
        catch {
            return null;
        }
    }
}

class CSSLanguagePlugin {
    constructor() {
        this.id = 'css';
        this.name = 'CSS';
        this.version = '1.0.0';
        this.languages = ['css'];
    }
    async getExtension() {
        const { css } = await import('@codemirror/lang-css');
        return css();
    }
}

class HTMLLanguagePlugin {
    constructor() {
        this.id = 'html';
        this.name = 'HTML';
        this.version = '1.0.0';
        this.languages = ['html'];
    }
    async getExtension() {
        const { html } = await import('@codemirror/lang-html');
        return html();
    }
}

class JavaScriptLanguagePlugin {
    constructor() {
        this.id = 'javascript';
        this.name = 'JavaScript';
        this.version = '1.0.0';
        this.languages = ['javascript', 'js'];
    }
    async getExtension() {
        const { javascript } = await import('@codemirror/lang-javascript');
        return javascript();
    }
}

class JSONLanguagePlugin {
    constructor() {
        this.id = 'json';
        this.name = 'JSON';
        this.version = '1.0.0';
        this.languages = ['json'];
    }
    async getExtension() {
        const { json } = await import('@codemirror/lang-json');
        return json();
    }
}

class MarkdownLanguagePlugin {
    constructor() {
        this.id = 'markdown';
        this.name = 'Markdown';
        this.version = '1.0.0';
        this.languages = ['markdown'];
    }
    async getExtension() {
        const { markdown } = await import('@codemirror/lang-markdown');
        return markdown();
    }
}

class SassLanguagePlugin {
    constructor() {
        this.id = 'sass';
        this.name = 'Sass/SCSS';
        this.version = '1.0.0';
        this.languages = ['sass', 'scss'];
    }
    async getExtension() {
        const { sass } = await import('@codemirror/lang-sass');
        return sass();
    }
}

class SQLLanguagePlugin {
    constructor() {
        this.id = 'sql';
        this.name = 'SQL';
        this.version = '1.0.0';
        this.languages = ['sql'];
    }
    async getExtension() {
        const { sql } = await import('@codemirror/lang-sql');
        return sql();
    }
}

class TypeScriptLanguagePlugin {
    constructor() {
        this.id = 'typescript';
        this.name = 'TypeScript';
        this.version = '1.0.0';
        this.languages = ['typescript', 'ts'];
    }
    async getExtension() {
        const { javascript } = await import('@codemirror/lang-javascript');
        return javascript({ typescript: true });
    }
}

class XMLLanguagePlugin {
    constructor() {
        this.id = 'xml';
        this.name = 'XML';
        this.version = '1.0.0';
        this.languages = ['xml'];
    }
    async getExtension() {
        const { xml } = await import('@codemirror/lang-xml');
        return xml();
    }
}

class GitHubDarkThemePlugin {
    constructor() {
        this.id = 'github-dark';
        this.name = 'GitHub Dark';
        this.version = '1.0.0';
        this.dark = true;
    }
    async getExtension() {
        const [{ githubDark }, { EditorView }] = await Promise.all([
            import('@uiw/codemirror-theme-github'),
            import('@codemirror/view'),
        ]);
        return [
            githubDark,
            EditorView.theme({
            // '&': { backgroundColor: 'transparent !important' },
            // '.cm-gutters': { backgroundColor: 'transparent !important' },
            }, { dark: true }),
        ];
    }
}

class GitHubLightThemePlugin {
    constructor() {
        this.id = 'github-light';
        this.name = 'GitHub Light';
        this.version = '1.0.0';
        this.dark = false;
    }
    async getExtension() {
        const [{ githubLight }, { EditorView }] = await Promise.all([
            import('@uiw/codemirror-theme-github'),
            import('@codemirror/view'),
        ]);
        return [
            githubLight,
            EditorView.theme({
            // '&': { backgroundColor: 'transparent !important' },
            // '.cm-gutters': { backgroundColor: 'transparent !important' },
            }, { dark: false }),
        ];
    }
}

class LightThemePlugin {
    constructor() {
        this.id = 'light';
        this.name = 'Light';
        this.version = '1.0.0';
        this.dark = false;
    }
    async getExtension() {
        const { EditorView } = await import('@codemirror/view');
        return EditorView.theme({
            // '&': { backgroundColor: 'transparent !important' },
            '.cm-gutters': {},
        }, { dark: false });
    }
}

class OneDarkThemePlugin {
    constructor() {
        this.id = 'one-dark';
        this.name = 'One Dark';
        this.version = '1.0.0';
        this.dark = true;
    }
    async getExtension() {
        const { EditorView } = await import('@codemirror/view');
        try {
            const { oneDark } = await import('@codemirror/theme-one-dark');
            return [
                oneDark,
                EditorView.theme({
                    // '&': { backgroundColor: 'transparent !important' },
                    '.cm-gutters': {},
                }, { dark: true }),
            ];
        }
        catch {
            return EditorView.theme({
                // '&': { backgroundColor: 'transparent !important' },
                '.cm-gutters': {},
            }, { dark: true });
        }
    }
}

/**
 * Default plugin configuration with all built-in plugins
 */
function provideDefaultCodeEditorPlugins() {
    return {
        languages: [
            new JavaScriptLanguagePlugin(),
            new TypeScriptLanguagePlugin(),
            new JSONLanguagePlugin(),
            new HTMLLanguagePlugin(),
            new CSSLanguagePlugin(),
            new SassLanguagePlugin(),
            new SQLLanguagePlugin(),
            new XMLLanguagePlugin(),
            new MarkdownLanguagePlugin(),
        ],
        themes: [
            new OneDarkThemePlugin(),
            new LightThemePlugin(),
            new GitHubLightThemePlugin(),
            new GitHubDarkThemePlugin(),
        ],
        formatters: [new PrettierFormatterPlugin()],
        extensions: [],
    };
}

/**
 * Injection token for providing code editor plugin configuration
 */
const AX_CODE_EDITOR_PLUGIN_CONFIG = new InjectionToken('AX_CODE_EDITOR_PLUGIN_CONFIG', {
    providedIn: 'root',
    factory: () => provideDefaultCodeEditorPlugins(),
});

/**
 * Registry service for managing code editor plugins
 */
class AXCodeEditorPluginRegistry {
    constructor() {
        this.config = inject(AX_CODE_EDITOR_PLUGIN_CONFIG, { optional: true });
        this.languagePlugins = new Map();
        this.themePlugins = new Map();
        this.formatterPlugins = new Map();
        this.extensionPlugins = new Map();
        this.initializePlugins();
    }
    initializePlugins() {
        if (!this.config)
            return;
        // Register language plugins
        this.config.languages?.forEach((plugin) => {
            plugin.languages.forEach((lang) => {
                this.languagePlugins.set(lang, plugin);
            });
        });
        // Register theme plugins
        this.config.themes?.forEach((plugin) => {
            this.themePlugins.set(plugin.id, plugin);
        });
        // Register formatter plugins
        this.config.formatters?.forEach((plugin) => {
            plugin.languages.forEach((lang) => {
                this.formatterPlugins.set(lang, plugin);
            });
        });
        // Register extension plugins
        this.config.extensions?.forEach((plugin) => {
            this.extensionPlugins.set(plugin.id, plugin);
        });
    }
    /**
     * Get language extension for the specified language
     */
    async getLanguageExtension(language) {
        const plugin = this.languagePlugins.get(language);
        if (!plugin) {
            console.warn(`No language plugin found for: ${language}`);
            return [];
        }
        return plugin.getExtension();
    }
    /**
     * Get theme extension by theme ID
     */
    async getThemeExtension(themeId) {
        const plugin = this.themePlugins.get(themeId);
        if (!plugin) {
            console.warn(`No theme plugin found for: ${themeId}`);
            return [];
        }
        return plugin.getExtension();
    }
    /**
     * Format text using the appropriate formatter for the language
     */
    async format(text, language) {
        const plugin = this.formatterPlugins.get(language);
        if (!plugin) {
            return null;
        }
        return plugin.format(text, language);
    }
    /**
     * Get all registered extension plugins
     */
    async getExtensionPlugins() {
        const extensions = await Promise.all(Array.from(this.extensionPlugins.values()).map((plugin) => plugin.getExtension()));
        return extensions;
    }
    /**
     * Check if a language is supported
     */
    hasLanguage(language) {
        return this.languagePlugins.has(language);
    }
    /**
     * Check if a theme is available
     */
    hasTheme(themeId) {
        return this.themePlugins.has(themeId);
    }
    /**
     * Check if a formatter is available for a language
     */
    hasFormatter(language) {
        return this.formatterPlugins.has(language);
    }
    /**
     * Get all available language identifiers
     */
    getAvailableLanguages() {
        return Array.from(this.languagePlugins.keys());
    }
    /**
     * Get all available theme identifiers
     */
    getAvailableThemes() {
        return Array.from(this.themePlugins.keys());
    }
    /**
     * Register a language plugin at runtime
     */
    registerLanguagePlugin(plugin) {
        plugin.languages.forEach((lang) => {
            this.languagePlugins.set(lang, plugin);
        });
    }
    /**
     * Register a theme plugin at runtime
     */
    registerThemePlugin(plugin) {
        this.themePlugins.set(plugin.id, plugin);
    }
    /**
     * Register a formatter plugin at runtime
     */
    registerFormatterPlugin(plugin) {
        plugin.languages.forEach((lang) => {
            this.formatterPlugins.set(lang, plugin);
        });
    }
    /**
     * Register an extension plugin at runtime
     */
    registerExtensionPlugin(plugin) {
        this.extensionPlugins.set(plugin.id, plugin);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXCodeEditorPluginRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXCodeEditorPluginRegistry, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXCodeEditorPluginRegistry, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [] });

class AXCodeEditorComponent extends MXValueComponent {
    /** Computed minimum height based on minRow (excluding gutter/line numbers). */
    getMinHeight() {
        const rows = this.minRow();
        if (!rows || rows <= 0)
            return null;
        // CodeMirror default line height is typically 1.5em, but we use rem for consistency
        // This calculates height without accounting for gutter since gutter is separate
        return `calc(${rows} * 1.5rem)`;
    }
    constructor() {
        super();
        // Inputs (signals)
        // value = input<string>('');
        /** Active language identifier from default plugins. Default: 'javascript'. */
        this.language = input('javascript', ...(ngDevMode ? [{ debugName: "language" }] : []));
        /** When true, the editor becomes readonly (non-editable). */
        this.editorReadonly = input(false, ...(ngDevMode ? [{ debugName: "editorReadonly", alias: 'readonly' }] : [{ alias: 'readonly' }]));
        /** Placeholder text shown when the document is empty. */
        this.placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
        /** Toggle rendering of line numbers in the gutter. */
        this.lineNumbers = input(true, ...(ngDevMode ? [{ debugName: "lineNumbers" }] : []));
        /** Soft-wrap long lines when true. */
        this.lineWrapping = input(false, ...(ngDevMode ? [{ debugName: "lineWrapping" }] : []));
        /** Tab size (spaces per indent level). */
        this.tabSize = input(2, ...(ngDevMode ? [{ debugName: "tabSize" }] : []));
        /** When true, the Tab key indents instead of moving focus. */
        this.indentWithTab = input(true, ...(ngDevMode ? [{ debugName: "indentWithTab" }] : []));
        /** Theme identifier. If null, uses platform theme mode (dark/light). */
        this.theme = input(null, ...(ngDevMode ? [{ debugName: "theme" }] : []));
        /** Additional CodeMirror extensions to apply. Reconfigures at runtime. */
        this.extensions = input([], ...(ngDevMode ? [{ debugName: "extensions" }] : []));
        /** ARIA label for accessibility. */
        this.ariaLabel = input(null, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
        /** Focus the editor after first render. */
        this.focusOnReady = input(false, ...(ngDevMode ? [{ debugName: "focusOnReady" }] : []));
        /** If true, format the document via Prettier before emitting save. */
        this.formatOnSave = input(false, ...(ngDevMode ? [{ debugName: "formatOnSave" }] : []));
        /** Minimum number of rows (lines) to display. Controls the minimum height of the editor. */
        this.minRow = input(null, ...(ngDevMode ? [{ debugName: "minRow" }] : []));
        /**
         * Custom autocompletion options: either a static array of Completion items
         * or a CodeMirror CompletionSource function.
         */
        this.customCompletions = input(null, ...(ngDevMode ? [{ debugName: "customCompletions" }] : []));
        // Outputs (signals)
        // valueChange = output<string>();
        /** Emits when the editor is fully initialized and ready. */
        this.ready = output();
        /** Emits when the user triggers save (Ctrl/Cmd+S). Payload is the current text. */
        this.save = output();
        // View container
        this.host = viewChild('host', ...(ngDevMode ? [{ debugName: "host" }] : []));
        // Runtime state
        this.platformId = inject(PLATFORM_ID);
        this.destroyRef = inject(DestroyRef);
        this.platformService = inject(AXPlatform);
        this.pluginRegistry = inject(AXCodeEditorPluginRegistry);
        this.editorViewSig = signal(null, ...(ngDevMode ? [{ debugName: "editorViewSig" }] : []));
        // Compartments to reconfigure editor without recreating it
        this.languageCompartment = null;
        this.readonlyCompartment = null;
        this.themeCompartment = null;
        this.placeholderCompartment = null;
        this.wrappingCompartment = null;
        this.keymapExtrasCompartment = null;
        this.tabSizeCompartment = null;
        this.lineNumbersCompartment = null;
        // Cached CodeMirror modules after initialization
        this.cm = { view: null, state: null, language: null, autocomplete: null, commands: null, search: null, lint: null };
        this.isBrowser = computed(() => isPlatformBrowser(this.platformId), ...(ngDevMode ? [{ debugName: "isBrowser" }] : []));
        afterNextRender(() => {
            if (!this.isBrowser())
                return;
            this.initializeEditor();
        });
        // Keep model in sync when external value changes
        effect(() => {
            const view = this.editorViewSig();
            if (!view)
                return;
            const newDoc = this.value ?? '';
            const current = view.state.doc.toString();
            if (newDoc !== current) {
                view.dispatch({
                    changes: { from: 0, to: view.state.doc.length, insert: newDoc },
                });
            }
        });
        // React to dynamic configuration changes
        effect(() => {
            const view = this.editorViewSig();
            if (!view || !this.languageCompartment)
                return;
            const lang = this.language();
            this.pluginRegistry.getLanguageExtension(lang).then((ext) => {
                if (!view || !this.languageCompartment)
                    return;
                view.dispatch({ effects: this.languageCompartment.reconfigure(ext) });
            });
        });
        effect(() => {
            const view = this.editorViewSig();
            if (!view || !this.readonlyCompartment)
                return;
            const editable = !this.editorReadonly();
            import('@codemirror/view').then(({ EditorView }) => {
                if (!view || !this.readonlyCompartment)
                    return;
                view.dispatch({ effects: this.readonlyCompartment.reconfigure(EditorView.editable.of(editable)) });
            });
        });
        effect(() => {
            const view = this.editorViewSig();
            // Establish reactive dependency on theme and platform theme
            const customTheme = this.theme();
            const platformTheme = this.platformService.themeMode();
            if (!view || !this.themeCompartment)
                return;
            this.resolveThemeExtension(customTheme, platformTheme).then((themeExt) => {
                if (!view || !this.themeCompartment)
                    return;
                view.dispatch({ effects: this.themeCompartment.reconfigure(themeExt) });
            });
        });
        effect(() => {
            this.placeholder();
            const view = this.editorViewSig();
            if (!view || !this.placeholderCompartment)
                return;
            import('@codemirror/view').then(({ placeholder }) => {
                if (!view || !this.placeholderCompartment)
                    return;
                view.dispatch({ effects: this.placeholderCompartment.reconfigure(placeholder(this.placeholder() ?? '')) });
            });
        });
        effect(() => {
            const view = this.editorViewSig();
            if (!view || !this.wrappingCompartment)
                return;
            const EditorView = this.cm.view?.EditorView;
            if (!EditorView)
                return;
            const nextExt = this.lineWrapping() ? EditorView.lineWrapping : [];
            this.reconfigure(this.wrappingCompartment, nextExt);
        });
        effect(() => {
            const view = this.editorViewSig();
            if (!view || !this.tabSizeCompartment)
                return;
            const EditorState = this.cm.state?.EditorState;
            if (!EditorState)
                return;
            this.reconfigure(this.tabSizeCompartment, EditorState.tabSize.of(this.tabSize() ?? 2));
        });
        effect(() => {
            const view = this.editorViewSig();
            if (!view || !this.keymapExtrasCompartment)
                return;
            const keymap = this.cm.view?.keymap;
            const commands = this.cm.commands;
            if (!keymap || !commands)
                return;
            this.reconfigure(this.keymapExtrasCompartment, keymap.of(this.indentWithTab() ? [commands.indentWithTab] : []));
        });
        effect(() => {
            const view = this.editorViewSig();
            if (!view || !this.lineNumbersCompartment)
                return;
            const lineNumbers = this.cm.view?.lineNumbers;
            if (!lineNumbers)
                return;
            this.reconfigure(this.lineNumbersCompartment, this.lineNumbers() ? lineNumbers() : []);
        });
    }
    async initializeEditor() {
        const hostEl = this.host()?.nativeElement;
        if (!hostEl)
            return;
        await this.loadCodeMirrorModules();
        this.createCompartments();
        const keymaps = this.buildKeymaps();
        const viewMod = this.cm.view;
        const stateMod = this.cm.state;
        const languageMod = this.cm.language;
        const autoMod = this.cm.autocomplete;
        const commandsMod = this.cm.commands;
        const searchMod = this.cm.search;
        const lintMod = this.cm.lint;
        if (!viewMod || !stateMod || !languageMod || !autoMod || !commandsMod || !searchMod || !lintMod)
            return;
        const languageExt = await this.pluginRegistry.getLanguageExtension(this.language());
        const themeExt = await this.resolveThemeExtension(this.theme(), this.platformService.themeMode());
        const placeholderExt = viewMod.placeholder(this.placeholder() ?? '');
        const editableExt = viewMod.EditorView.editable.of(!this.editorReadonly());
        const wrappingExt = this.lineWrapping() ? viewMod.EditorView.lineWrapping : [];
        const tabSizeExt = stateMod.EditorState.tabSize.of(this.tabSize() ?? 2);
        const lineNumbersExt = this.lineNumbers() ? viewMod.lineNumbers() : [];
        const autoCompleteExt = autoMod.autocompletion({
            override: this.buildCustomCompletionSources(),
        });
        const baseExtensions = [
            this.lineNumbersCompartment.of(lineNumbersExt),
            viewMod.highlightActiveLine(),
            viewMod.highlightActiveLineGutter(),
            viewMod.drawSelection(),
            viewMod.dropCursor(),
            viewMod.rectangularSelection(),
            viewMod.crosshairCursor(),
            viewMod.highlightSpecialChars(),
            languageMod.syntaxHighlighting(languageMod.defaultHighlightStyle, { fallback: true }),
            languageMod.bracketMatching(),
            languageMod.foldGutter(),
            commandsMod.history(),
            searchMod.highlightSelectionMatches(),
            viewMod.keymap.of(keymaps),
            autoCompleteExt,
            this.languageCompartment.of(languageExt),
            this.readonlyCompartment.of(editableExt),
            this.themeCompartment.of(themeExt),
            this.placeholderCompartment.of(placeholderExt),
            this.wrappingCompartment.of(wrappingExt),
            this.tabSizeCompartment.of(tabSizeExt),
            this.keymapExtrasCompartment.of(viewMod.keymap.of(this.indentWithTab() ? [commandsMod.indentWithTab] : [])),
            ...this.extensions(),
        ];
        const updateListener = viewMod.EditorView.updateListener.of((vu) => {
            if (vu.docChanged) {
                const text = vu.state.doc.toString();
                // this.writeValue(text);
                this.value = text;
            }
        });
        const state = stateMod.EditorState.create({
            doc: this.value ?? '',
            extensions: [...baseExtensions, updateListener],
        });
        const view = new viewMod.EditorView({ state, parent: hostEl });
        // Update listener for external changes (selection, viewport, etc.) if needed later
        view.dispatch({ effects: [] });
        this.editorViewSig.set(view);
        this.destroyRef.onDestroy(() => {
            view.destroy();
            this.editorViewSig.set(null);
        });
        if (this.focusOnReady()) {
            view.focus();
        }
        this.ready.emit();
    }
    reconfigure(comp, ext) {
        const view = this.editorViewSig();
        if (!view || !comp)
            return;
        view.dispatch({ effects: comp.reconfigure(ext) });
    }
    /**
     * Handles Ctrl/Cmd+S on the host. If formatOnSave is enabled, attempts
     * to format the document first, then emits the saved text.
     */
    async onSaveShortcut(event) {
        event.preventDefault();
        const view = this.editorViewSig();
        const current = view?.state.doc.toString() ?? this.value ?? '';
        const payload = current;
        if (this.formatOnSave()) {
            await this.format(true);
        }
        this.save.emit(payload);
    }
    async loadCodeMirrorModules() {
        const [viewMod, stateMod, langMod, autoMod, cmdMod, searchMod, lintMod] = await Promise.all([
            import('@codemirror/view'),
            import('@codemirror/state'),
            import('@codemirror/language'),
            import('@codemirror/autocomplete'),
            import('@codemirror/commands'),
            import('@codemirror/search'),
            import('@codemirror/lint'),
        ]);
        this.cm.view = viewMod;
        this.cm.state = stateMod;
        this.cm.language = langMod;
        this.cm.autocomplete = autoMod;
        this.cm.commands = cmdMod;
        this.cm.search = searchMod;
        this.cm.lint = lintMod;
    }
    createCompartments() {
        const stateMod = this.cm.state;
        if (!stateMod)
            return;
        this.languageCompartment = new stateMod.Compartment();
        this.readonlyCompartment = new stateMod.Compartment();
        this.themeCompartment = new stateMod.Compartment();
        this.placeholderCompartment = new stateMod.Compartment();
        this.wrappingCompartment = new stateMod.Compartment();
        this.tabSizeCompartment = new stateMod.Compartment();
        this.keymapExtrasCompartment = new stateMod.Compartment();
        this.lineNumbersCompartment = new stateMod.Compartment();
    }
    buildKeymaps() {
        const cmdMod = this.cm.commands;
        const searchMod = this.cm.search;
        const autoMod = this.cm.autocomplete;
        const lintMod = this.cm.lint;
        if (!cmdMod || !searchMod || !autoMod || !lintMod)
            return [];
        return [
            ...cmdMod.defaultKeymap,
            ...cmdMod.historyKeymap,
            ...searchMod.searchKeymap,
            ...autoMod.completionKeymap,
            ...lintMod.lintKeymap,
        ];
    }
    async resolveThemeExtension(customTheme, platformTheme) {
        // If custom theme is specified, use it
        if (customTheme) {
            return this.pluginRegistry.getThemeExtension(customTheme);
        }
        // Otherwise, use platform theme (handle 'system' by defaulting to 'github-light')
        const themeId = platformTheme === 'dark' ? 'github-dark' : 'github-light';
        return this.pluginRegistry.getThemeExtension(themeId);
    }
    buildCustomCompletionSources() {
        const provided = this.customCompletions();
        if (!provided)
            return undefined;
        if (typeof provided === 'function') {
            return [provided];
        }
        // Treat array as a static completion list
        const staticSource = (context) => {
            const from = context.pos;
            return { from, options: provided };
        };
        return [staticSource];
    }
    // Public API
    /** Programmatically focus the editor. */
    focus() {
        const view = this.editorViewSig();
        if (view)
            view.focus();
    }
    /** Select all text in the current document. */
    selectAll() {
        const view = this.editorViewSig();
        if (!view)
            return;
        const length = view.state.doc.length;
        view.dispatch({ selection: { anchor: 0, head: length } });
    }
    // Formats the current document using the registered formatter plugin (if available for the active language).
    // Returns the formatted text or null if unchanged/unsupported.
    async format(affect = true) {
        const view = this.editorViewSig();
        if (!view)
            return null;
        const source = view.state.doc.toString();
        if (!source)
            return null;
        const formatted = await this.pluginRegistry.format(source, this.language());
        if (!formatted || formatted === source)
            return null;
        if (affect) {
            view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: formatted } });
        }
        return formatted;
    }
    /** Returns the total number of characters in the current document. */
    getTotalCharacters() {
        const view = this.editorViewSig();
        if (view)
            return view.state.doc.length ?? 0;
        const text = this.value ?? '';
        return text.length;
    }
    /** Returns the total number of lines in the current document. */
    getTotalLines() {
        const view = this.editorViewSig();
        if (view) {
            const doc = view.state.doc;
            return typeof doc?.lines === 'number' ? doc.lines : doc.toString().split(/\r?\n/).length;
        }
        const text = this.value ?? '';
        return text ? text.split(/\r?\n/).length : 1;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXCodeEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.16", type: AXCodeEditorComponent, isStandalone: true, selector: "ax-code-editor", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: false, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: false, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: false, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: false, isRequired: false, transformFunction: null }, language: { classPropertyName: "language", publicName: "language", isSignal: true, isRequired: false, transformFunction: null }, editorReadonly: { classPropertyName: "editorReadonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, lineNumbers: { classPropertyName: "lineNumbers", publicName: "lineNumbers", isSignal: true, isRequired: false, transformFunction: null }, lineWrapping: { classPropertyName: "lineWrapping", publicName: "lineWrapping", isSignal: true, isRequired: false, transformFunction: null }, tabSize: { classPropertyName: "tabSize", publicName: "tabSize", isSignal: true, isRequired: false, transformFunction: null }, indentWithTab: { classPropertyName: "indentWithTab", publicName: "indentWithTab", isSignal: true, isRequired: false, transformFunction: null }, theme: { classPropertyName: "theme", publicName: "theme", isSignal: true, isRequired: false, transformFunction: null }, extensions: { classPropertyName: "extensions", publicName: "extensions", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, focusOnReady: { classPropertyName: "focusOnReady", publicName: "focusOnReady", isSignal: true, isRequired: false, transformFunction: null }, formatOnSave: { classPropertyName: "formatOnSave", publicName: "formatOnSave", isSignal: true, isRequired: false, transformFunction: null }, minRow: { classPropertyName: "minRow", publicName: "minRow", isSignal: true, isRequired: false, transformFunction: null }, customCompletions: { classPropertyName: "customCompletions", publicName: "customCompletions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onValueChanged: "onValueChanged", valueChange: "valueChange", stateChange: "stateChange", readonlyChange: "readonlyChange", disabledChange: "disabledChange", ready: "ready", save: "save" }, host: { listeners: { "keydown.control.s": "onSaveShortcut($event)" }, classAttribute: "ax-code-editor block" }, providers: [
            { provide: AXValuableComponent, useExisting: AXCodeEditorComponent },
            {
                provide: NG_VALUE_ACCESSOR,
                useExisting: forwardRef(() => AXCodeEditorComponent),
                multi: true,
            },
            { provide: AXComponent, useExisting: AXCodeEditorComponent },
        ], viewQueries: [{ propertyName: "host", first: true, predicate: ["host"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
    <div class="ax-editor-container" [style.min-height]="getMinHeight()">
      <div class="ax-code-editor-container">
        <div
          #host
          class="cm-editor"
          [attr.aria-label]="ariaLabel() ?? null"
          [attr.aria-readonly]="editorReadonly() ? 'true' : 'false'"
          [attr.data-placeholder]="placeholder() ?? null"
        ></div>
      </div>
      <ng-content select="ax-validation-rule"> </ng-content>
    </div>
    <div class="ax-error-container"></div>
  `, isInline: true, styles: [":host{display:block;width:100%;height:100%}:host.ax-disable{opacity:.5;cursor:not-allowed}:host>.ax-editor-container{height:100%;width:100%;align-items:start;--ax-comp-editor-space-start-size: 0;--ax-comp-editor-space-end-size: 0;--ax-comp-editor-border-width: 1px}:host .ax-code-editor-container{display:flex;flex-direction:column;height:100%;width:100%}:host .cm-editor{width:100%;max-width:100%;overflow:auto}:host .cm-editor.cm-focused{outline:none}:host .ax-error-message{padding-inline:.5rem}\n"] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXCodeEditorComponent, decorators: [{
            type: Component,
            args: [{ selector: 'ax-code-editor', host: {
                        '(keydown.control.s)': 'onSaveShortcut($event)',
                        class: 'ax-code-editor block',
                    }, inputs: ['disabled', 'value', 'state', 'name', 'id'], outputs: ['onValueChanged', 'valueChange', 'stateChange', 'readonlyChange', 'disabledChange'], providers: [
                        { provide: AXValuableComponent, useExisting: AXCodeEditorComponent },
                        {
                            provide: NG_VALUE_ACCESSOR,
                            useExisting: forwardRef(() => AXCodeEditorComponent),
                            multi: true,
                        },
                        { provide: AXComponent, useExisting: AXCodeEditorComponent },
                    ], template: `
    <div class="ax-editor-container" [style.min-height]="getMinHeight()">
      <div class="ax-code-editor-container">
        <div
          #host
          class="cm-editor"
          [attr.aria-label]="ariaLabel() ?? null"
          [attr.aria-readonly]="editorReadonly() ? 'true' : 'false'"
          [attr.data-placeholder]="placeholder() ?? null"
        ></div>
      </div>
      <ng-content select="ax-validation-rule"> </ng-content>
    </div>
    <div class="ax-error-container"></div>
  `, styles: [":host{display:block;width:100%;height:100%}:host.ax-disable{opacity:.5;cursor:not-allowed}:host>.ax-editor-container{height:100%;width:100%;align-items:start;--ax-comp-editor-space-start-size: 0;--ax-comp-editor-space-end-size: 0;--ax-comp-editor-border-width: 1px}:host .ax-code-editor-container{display:flex;flex-direction:column;height:100%;width:100%}:host .cm-editor{width:100%;max-width:100%;overflow:auto}:host .cm-editor.cm-focused{outline:none}:host .ax-error-message{padding-inline:.5rem}\n"] }]
        }], ctorParameters: () => [], propDecorators: { language: [{ type: i0.Input, args: [{ isSignal: true, alias: "language", required: false }] }], editorReadonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], lineNumbers: [{ type: i0.Input, args: [{ isSignal: true, alias: "lineNumbers", required: false }] }], lineWrapping: [{ type: i0.Input, args: [{ isSignal: true, alias: "lineWrapping", required: false }] }], tabSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabSize", required: false }] }], indentWithTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "indentWithTab", required: false }] }], theme: [{ type: i0.Input, args: [{ isSignal: true, alias: "theme", required: false }] }], extensions: [{ type: i0.Input, args: [{ isSignal: true, alias: "extensions", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], focusOnReady: [{ type: i0.Input, args: [{ isSignal: true, alias: "focusOnReady", required: false }] }], formatOnSave: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatOnSave", required: false }] }], minRow: [{ type: i0.Input, args: [{ isSignal: true, alias: "minRow", required: false }] }], customCompletions: [{ type: i0.Input, args: [{ isSignal: true, alias: "customCompletions", required: false }] }], ready: [{ type: i0.Output, args: ["ready"] }], save: [{ type: i0.Output, args: ["save"] }], host: [{ type: i0.ViewChild, args: ['host', { isSignal: true }] }] } });

class AXCodeEditorModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXCodeEditorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: AXCodeEditorModule, imports: [CommonModule, AXCodeEditorComponent], exports: [AXCodeEditorComponent] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXCodeEditorModule, imports: [CommonModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXCodeEditorModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [CommonModule, AXCodeEditorComponent],
                    exports: [AXCodeEditorComponent],
                }]
        }] });

// Language plugins

// Language plugins

// Component & Module

/**
 * Generated bundle index. Do not edit.
 */

export { AXCodeEditorComponent, AXCodeEditorModule, AXCodeEditorPluginRegistry, AX_CODE_EDITOR_PLUGIN_CONFIG, CSSLanguagePlugin, GitHubDarkThemePlugin, GitHubLightThemePlugin, HTMLLanguagePlugin, JSONLanguagePlugin, JavaScriptLanguagePlugin, LightThemePlugin, MarkdownLanguagePlugin, OneDarkThemePlugin, PrettierFormatterPlugin, SQLLanguagePlugin, SassLanguagePlugin, TypeScriptLanguagePlugin, XMLLanguagePlugin, provideDefaultCodeEditorPlugins };
//# sourceMappingURL=acorex-components-code-editor.mjs.map
