var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { CodeEditorTheme, UmbCodeEditorLoadedEvent, } from '../models/index.js';
import { UMB_THEME_CONTEXT } from '../../core/themes/index.js';
import { createRef, css, customElement, html, property, ref, state, unsafeCSS, when, } from '../../../external/lit/index.js';
import { UmbLitElement } from '../../core/lit-element/index.js';
const elementName = 'umb-code-editor';
/**
 * A custom element that renders a code editor. Code editor is based on the Monaco Editor library.
 * The element will listen to the theme context and update the theme accordingly.
 * Parts of the monaco Api is exposed through the `editor` property. You can access the monaco editor instance through `editor.monacoEditor`.
 * @element umb-code-editor
 * @class UmbCodeEditorElement
 * @augments {UmbLitElement}
 * @implements {UmbCodeEditorHost}
 * @fires input - Fired when the value of the editor changes.
 * @fires change - Fired when the entire model of editor is replaced.
 * @fires loaded - Fired when the editor is loaded and ready to use.
 */
let UmbCodeEditorElement = class UmbCodeEditorElement extends UmbLitElement {
    #containerRef;
    get container() {
        if (!this.#containerRef?.value)
            throw new Error('Container not found');
        return this.#containerRef.value;
    }
    #editor;
    get editor() {
        return this.#editor;
    }
    //TODO - this should be called a value
    #code;
    /**
     * Value of the editor. Default is empty string.
     * @readonly
     * @memberof UmbCodeEditorElement
     */
    get code() {
        return this.#code;
    }
    set code(value) {
        const oldValue = this.#code;
        this.#code = value;
        if (this.#editor) {
            this.#editor.value = value;
        }
        this.requestUpdate('code', oldValue);
    }
    constructor() {
        super();
        this.#containerRef = createRef();
        /**
         * Theme of the editor. Default is light. Element will listen to the theme context and update the theme accordingly.
         * @type {CodeEditorTheme}
         * @memberof UmbCodeEditorElement
         */
        this.theme = CodeEditorTheme.Light;
        /**
         * Language of the editor. Default is javascript.
         * @type {CodeEditorLanguage}
         * @memberof UmbCodeEditorElement
         */
        this.language = 'javascript';
        //TODO - this should be called a value
        this.#code = '';
        /**
         * Whether the editor is readonly.
         * @memberof UmbCodeEditorElement
         */
        this.readonly = false;
        /**
         * Whether to show line numbers.
         * @memberof UmbCodeEditorElement
         */
        this.disableLineNumbers = false;
        /**
         * Whether to show minimap.
         * @memberof UmbCodeEditorElement
         */
        this.disableMinimap = false;
        /**
         * Whether to enable word wrap. Default is false.
         * @memberof UmbCodeEditorElement
         */
        this.wordWrap = false;
        /**
         * Whether to enable folding. Default is true.
         * @memberof UmbCodeEditorElement
         */
        this.disableFolding = false;
        this._loading = true;
        this.consumeContext(UMB_THEME_CONTEXT, (instance) => {
            this.observe(instance?.theme, (themeAlias) => {
                this.theme = themeAlias ? this.#translateTheme(themeAlias) : CodeEditorTheme.Light;
            }, '_observeTheme');
        });
    }
    async firstUpdated() {
        const { styles } = await import('../../../external/monaco-editor/index.js');
        this._styles = styles;
        const { UmbCodeEditorController } = await import('../code-editor.controller.js');
        // Options
        this.#editor = new UmbCodeEditorController(this, this.#constructorOptions());
        this._loading = false;
        this.dispatchEvent(new UmbCodeEditorLoadedEvent());
    }
    updated(_changedProperties) {
        if (_changedProperties.has('theme') ||
            _changedProperties.has('language') ||
            _changedProperties.has('disableLineNumbers') ||
            _changedProperties.has('disableMinimap') ||
            _changedProperties.has('wordWrap') ||
            _changedProperties.has('readonly') ||
            _changedProperties.has('code') ||
            _changedProperties.has('label') ||
            _changedProperties.has('disableFolding')) {
            this.#editor?.updateOptions(this.#constructorOptions());
        }
    }
    #constructorOptions() {
        return {
            language: this.language,
            theme: this.theme,
            ariaLabel: this.label ?? this.localize.term('codeEditor_label'),
            lineNumbers: !this.disableLineNumbers,
            minimap: !this.disableMinimap,
            wordWrap: this.wordWrap ? 'on' : 'off',
            readOnly: this.readonly,
            folding: !this.disableFolding,
            value: this.code,
        };
    }
    #translateTheme(theme) {
        switch (theme) {
            case 'umb-light-theme':
                return CodeEditorTheme.Light;
            case 'umb-dark-theme':
                return CodeEditorTheme.Dark;
            case 'umb-high-contrast-theme':
                return CodeEditorTheme.HighContrastLight;
            default:
                return CodeEditorTheme.Light;
        }
    }
    /**
     * Inserts text at the current cursor position.
     * @param {string} text
     * @memberof UmbCodeEditorElement
     */
    insert(text) {
        this.#editor?.insert(text);
    }
    /**
     * Finds all occurrence of the given string or matches the given regular expression.
     * @param {string} text
     * @param searchOptions
     * @returns {*}
     * @memberof UmbCodeEditorElement
     */
    find(text, searchOptions = {}) {
        return this.#editor?.find(text, searchOptions);
    }
    render() {
        return html `
			${this.#renderStyles()}
			${when(this._loading, () => html `<div id="loader-container"><uui-loader></uui-loader></div>`)}
			<div id="editor-container" ${ref(this.#containerRef)}></div>
		`;
    }
    #renderStyles() {
        if (!this._styles)
            return;
        return html `
			<style>
				${unsafeCSS(this._styles)}
			</style>
		`;
    }
    static { this.styles = [
        css `
			:host {
				display: block;
			}

			#loader-container {
				display: grid;
				place-items: center;
				min-height: calc(100dvh - 260px);
			}

			#editor-container {
				width: var(--editor-width);
				height: var(--editor-height, 100%);

				--vscode-scrollbar-shadow: #dddddd;
				--vscode-scrollbarSlider-background: var(--uui-color-disabled-contrast);
				--vscode-scrollbarSlider-hoverBackground: rgba(100, 100, 100, 0.7);
				--vscode-scrollbarSlider-activeBackground: rgba(0, 0, 0, 0.6);

				/* a hacky workaround this issue: https://github.com/microsoft/monaco-editor/issues/3217
			   should probably be removed when the issue is fixed */
				.view-lines {
					font-feature-settings: revert !important;
				}
			}
		`,
    ]; }
};
__decorate([
    property()
], UmbCodeEditorElement.prototype, "theme", void 0);
__decorate([
    property()
], UmbCodeEditorElement.prototype, "language", void 0);
__decorate([
    property()
], UmbCodeEditorElement.prototype, "label", void 0);
__decorate([
    property()
], UmbCodeEditorElement.prototype, "code", null);
__decorate([
    property({ type: Boolean, attribute: 'readonly' })
], UmbCodeEditorElement.prototype, "readonly", void 0);
__decorate([
    property({ type: Boolean, attribute: 'disable-line-numbers' })
], UmbCodeEditorElement.prototype, "disableLineNumbers", void 0);
__decorate([
    property({ type: Boolean, attribute: 'disable-minimap' })
], UmbCodeEditorElement.prototype, "disableMinimap", void 0);
__decorate([
    property({ type: Boolean, attribute: 'word-wrap' })
], UmbCodeEditorElement.prototype, "wordWrap", void 0);
__decorate([
    property({ type: Boolean, attribute: 'disable-folding' })
], UmbCodeEditorElement.prototype, "disableFolding", void 0);
__decorate([
    state()
], UmbCodeEditorElement.prototype, "_loading", void 0);
__decorate([
    state()
], UmbCodeEditorElement.prototype, "_styles", void 0);
UmbCodeEditorElement = __decorate([
    customElement(elementName)
], UmbCodeEditorElement);
export { UmbCodeEditorElement };
