import { CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { inject, EventEmitter, forwardRef, Component, Input, Output, ViewChild, NgModule } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { ReplaySubject, Subject } from 'rxjs';
import { take, takeUntil } from 'rxjs/operators';
import { setDiagnostics } from '@codemirror/lint';
import { StateField, StateEffect, EditorState } from '@codemirror/state';
import { EditorView } from '@codemirror/view';
import { LRLanguage, LanguageSupport } from '@codemirror/language';
import { buildParser } from '@lezer/generator';
import { styleTags, tags, HighlightStyle } from '@codemirror/highlight';
import { autocompletion, startCompletion, pickedCompletion } from '@codemirror/autocomplete';
import { service, user } from '@seniorsistemas/senior-platform-data';
import { TranslateService } from '@ngx-translate/core';
import { HostProjectConfigsInjectionToken } from '@seniorsistemas/angular-components/common';
import { showTooltip } from '@codemirror/tooltip';
import { lineNumbers } from '@codemirror/gutter';

var Languages;
(function (Languages) {
    Languages["TaxCalculation"] = "TaxCalculation";
    Languages["Json"] = "Json";
})(Languages || (Languages = {}));

var Themes;
(function (Themes) {
    Themes["SDSLight"] = "SDSLight";
})(Themes || (Themes = {}));

/* Interfaces */

class CoreLinters {
    static _LINTERS = new Map([]);
    static getLinter(language) {
        const languageLinterFactory = CoreLinters._LINTERS.get(language);
        if (languageLinterFactory) {
            return languageLinterFactory();
        }
        return undefined;
    }
}

class CoreFacade {
    $onCoreFinishLoad = new ReplaySubject(1);
    $onCodeChange = new Subject();
    $onCodeValidityChange = new Subject();
    _completionItems = [];
    _lastCodeEmitted = '';
    _lastCodeValidityEmitted;
    _linter;
    changeEditorOptions(options) {
        if (options) {
            if (typeof options !== 'object') {
                throw new Error("Editor's options must be an EditorOptions object");
            }
            this.validateLanguage(options.language);
            this.validateTheme(options.theme);
            this.setLinter(options.language);
            this.setCoreEditorOptions(options);
        }
    }
    changeCode(code) {
        const safeCode = this.getSafeCode(code);
        if (safeCode !== this._lastCodeEmitted) {
            this.setCode(safeCode);
        }
    }
    setPayload(payload) {
        const safeCode = this.getSafeCode(payload);
        // Força a atualização sem verificar _lastCodeEmitted,
        // mas preserva o cursor verificando no nível do editor
        this.setCodeWithCursorPreservation(safeCode);
    }
    getOnCoreFinishLoadObservable() {
        return this.$onCoreFinishLoad.asObservable();
    }
    getOnCodeChangeObservable() {
        return this.$onCodeChange.asObservable();
    }
    getOnCodeValidityChangeObservable() {
        return this.$onCodeValidityChange.asObservable();
    }
    notifyCoreFinishLoad() {
        this.$onCoreFinishLoad.next();
    }
    notifyCodeChange(code) {
        const safeCode = this.getSafeCode(code);
        if (safeCode !== this._lastCodeEmitted) {
            this._lastCodeEmitted = safeCode;
            this.$onCodeChange.next(safeCode);
            this.validateCode(safeCode);
        }
    }
    updateCompletionItems(items) {
        this._completionItems = items || [];
        this.validateCode(this._lastCodeEmitted);
    }
    setLinter(language) {
        this._linter = CoreLinters.getLinter(language);
    }
    async validateCode(code) {
        if (this._linter) {
            const markers = await this._linter.lint(code, this._completionItems);
            this.highlightCode(markers);
            this.notifyCodeValidityChange(!markers.length);
        }
    }
    notifyCodeValidityChange(validity) {
        if (validity !== this._lastCodeValidityEmitted) {
            this._lastCodeValidityEmitted = validity;
            this.$onCodeValidityChange.next(validity);
        }
    }
    validateLanguage(language) {
        const languages = Object.values(Languages);
        if (language && !languages.includes(language)) {
            throw new Error(`The informed language "${language}" is not supported`);
        }
    }
    validateTheme(theme) {
        const themes = Object.values(Themes);
        if (theme && !themes.includes(theme)) {
            throw new Error(`The informed theme "${theme}" is not supported`);
        }
    }
    getSafeCode(code) {
        return typeof code === 'string' ? code : '';
    }
}

/* eslint-disable @angular-eslint/no-output-on-prefix */
/**
 * @description Componente de editor de código com syntax highlighting, construído sobre
 * um editor Monaco/CodeMirror. Implementa {@link ControlValueAccessor} para integração
 * com formulários Angular e suporta configuração de linguagem, tema e opções avançadas
 * do editor via `editorOptions`.
 *
 * @example
 * ```html
 * <s-code-editor
 *   formControlName="script"
 *   [editorOptions]="{ language: 'javascript', theme: 'vs-dark' }"
 *   (codeChange)="onCodeChange($event)" />
 * ```
 *
 * @category Inputs
 */
class CodeEditorComponent {
    coreFacade = inject(CoreFacade);
    /**
     * @description Opções de configuração do editor (linguagem, tema, readonly, etc.).
     * Ao atribuir um novo valor, as opções são aplicadas imediatamente ao editor.
     */
    set editorOptions(options) {
        if (options) {
            this.coreFacade.changeEditorOptions(options);
        }
    }
    /**
     * @description Conteúdo textual do editor. Ao atribuir, o código é propagado ao núcleo do editor.
     */
    set code(code) {
        this.coreFacade.changeCode(code);
    }
    /**
     * @description Indica se o código atual é válido segundo as regras do editor.
     * Pode ser usado para exibir indicadores visuais de erro.
     *
     * @default false
     */
    isCodeValid = false;
    /**
     * @description Payload adicional passado ao núcleo do editor, utilizado para
     * contexto de autocompletar ou validações específicas da linguagem.
     */
    set payload(payload) {
        this.coreFacade.setPayload(payload);
    }
    /** @description Emitido sempre que o conteúdo do editor é alterado. Emite o código atual como string. */
    codeChange = new EventEmitter();
    /** @description Emitido quando o estado de validade do código muda. */
    isCodeValidChange = new EventEmitter();
    /**
     * @deprecated Use `codeChange` ao invés deste output.
     * @description Emitido sempre que o conteúdo do editor é alterado.
     */
    onCodeChange = new EventEmitter();
    /** @description Emitido quando o componente finaliza o carregamento e o editor está pronto para uso. */
    onComponentFinishLoad = new EventEmitter();
    coreWrapperElement = null;
    _ngUnsubscribe = new Subject();
    _onChange = () => { };
    _onTouched = () => { };
    writeValue(value) {
        this.code = value;
    }
    registerOnChange(onChange) {
        this._onChange = onChange;
    }
    registerOnTouched(onTouched) {
        this._onTouched = onTouched;
    }
    ngOnInit() {
        this.coreFacade.initCore();
        this.setupCoreListeners();
    }
    ngAfterViewInit() {
        this.setCoreWrapperElement();
    }
    ngOnDestroy() {
        this.coreFacade.destroyCore();
        this._ngUnsubscribe.next();
        this._ngUnsubscribe.complete();
    }
    setCoreWrapperElement() {
        this.coreFacade.setCoreWrapperElement(this.coreWrapperElement?.nativeElement);
    }
    setupCoreListeners() {
        this.coreFacade
            .getOnCoreFinishLoadObservable()
            .pipe(take(1))
            .subscribe(() => this.onComponentFinishLoad.emit());
        this.coreFacade
            .getOnCodeChangeObservable()
            .pipe(takeUntil(this._ngUnsubscribe))
            .subscribe((code) => {
            this.codeChange.emit(code);
            this.onCodeChange.emit(code);
            this._onTouched();
            this._onChange(code);
        });
        this.coreFacade
            .getOnCodeValidityChangeObservable()
            .pipe(takeUntil(this._ngUnsubscribe))
            .subscribe((validity) => {
            this.isCodeValidChange.emit(validity);
        });
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CodeEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: CodeEditorComponent, selector: "s-code-editor", inputs: { editorOptions: "editorOptions", code: "code", isCodeValid: "isCodeValid", payload: "payload" }, outputs: { codeChange: "codeChange", isCodeValidChange: "isCodeValidChange", onCodeChange: "onCodeChange", onComponentFinishLoad: "onComponentFinishLoad" }, providers: [
            {
                provide: NG_VALUE_ACCESSOR,
                useExisting: forwardRef(() => CodeEditorComponent),
                multi: true,
            },
        ], viewQueries: [{ propertyName: "coreWrapperElement", first: true, predicate: ["coreWrapper"], descendants: true }], ngImport: i0, template: "<div #coreWrapper class=\"core-wrapper\"></div>", styles: [".core-wrapper{height:100%;border:1px solid #c1c1cc;border-radius:3px}\n"] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CodeEditorComponent, decorators: [{
            type: Component,
            args: [{ selector: 's-code-editor', providers: [
                        {
                            provide: NG_VALUE_ACCESSOR,
                            useExisting: forwardRef(() => CodeEditorComponent),
                            multi: true,
                        },
                    ], template: "<div #coreWrapper class=\"core-wrapper\"></div>", styles: [".core-wrapper{height:100%;border:1px solid #c1c1cc;border-radius:3px}\n"] }]
        }], propDecorators: { editorOptions: [{
                type: Input
            }], code: [{
                type: Input
            }], isCodeValid: [{
                type: Input
            }], payload: [{
                type: Input
            }], codeChange: [{
                type: Output
            }], isCodeValidChange: [{
                type: Output
            }], onCodeChange: [{
                type: Output
            }], onComponentFinishLoad: [{
                type: Output
            }], coreWrapperElement: [{
                type: ViewChild,
                args: ['coreWrapper']
            }] } });

var parserGrammar = `
@top Script { statement+ }

statement[@isGroup=Statement] {
    Keyword |
    String |
    Number
}

@tokens {
    String { '"' (![\\n"])* '"'? }

    Number { std.digit+ }

    identifierChar { std.asciiLetter | $[_$\u{a1}-\u{10ffff}] }

    word { identifierChar (identifierChar | std.digit)* }

    identifier { word }
}

Keyword {
    kw<"SE">
    kw<"ENTAO">
    kw<"FIM_SE">
    kw<"SENAO">
    kw<"NAO">
    kw<"CONTENHA">
    kw<"OU">
    kw<"E">
}

kw<term> { @specialize[@name={term}]<identifier, term> }

@detectDelim
`;

var EnumTypeOrder;
(function (EnumTypeOrder) {
    // Tipo de ordenação - Crescente
    EnumTypeOrder["ASC"] = "ASC";
    // Tipo de ordenação - Decrescente
    EnumTypeOrder["DESC"] = "DESC";
})(EnumTypeOrder || (EnumTypeOrder = {}));

var MetaType;
(function (MetaType) {
    // Entity
    MetaType["ENTITY"] = "ENTITY";
    // String
    MetaType["STRING"] = "STRING";
    // Integer
    MetaType["INTEGER"] = "INTEGER";
    // Double
    MetaType["DOUBLE"] = "DOUBLE";
    // Long
    MetaType["LONG"] = "LONG";
    // BigDecimal
    MetaType["BIGDECIMAL"] = "BIGDECIMAL";
    // UUID
    MetaType["UUID"] = "UUID";
    // Date
    MetaType["DATE"] = "DATE";
    // DateTime
    MetaType["DATETIME"] = "DATETIME";
    // DateTime
    MetaType["LOCALDATETIME"] = "LOCALDATETIME";
    // Time
    MetaType["TIME"] = "TIME";
    // Boolean
    MetaType["BOOLEAN"] = "BOOLEAN";
    // List
    MetaType["LIST"] = "LIST";
    // Enum
    MetaType["ENUM"] = "ENUM";
    // CustomExpression
    MetaType["CUSTOM_EXPRESSION"] = "CUSTOM_EXPRESSION";
    // PublicExpression
    MetaType["PUBLIC_EXPRESSION"] = "PUBLIC_EXPRESSION";
})(MetaType || (MetaType = {}));

var RequestTypes;
(function (RequestTypes) {
    RequestTypes[RequestTypes["ListContextMetadataById"] = 0] = "ListContextMetadataById";
    RequestTypes[RequestTypes["ListBlobMetadata"] = 1] = "ListBlobMetadata";
    RequestTypes[RequestTypes["ListExpressionMetadata"] = 2] = "ListExpressionMetadata";
    RequestTypes[RequestTypes["ListFacadeMetadataNames"] = 3] = "ListFacadeMetadataNames";
    RequestTypes[RequestTypes["GetFacadeMetadataByPath"] = 4] = "GetFacadeMetadataByPath";
})(RequestTypes || (RequestTypes = {}));

var CompletionTypes;
(function (CompletionTypes) {
    CompletionTypes["Keyword"] = "keyword";
    CompletionTypes["Context"] = "context";
    CompletionTypes["Expression"] = "expression";
    CompletionTypes["UserExpression"] = "userExpression";
    CompletionTypes["Entity"] = "entity";
    CompletionTypes["FinalValue"] = "finalValue";
})(CompletionTypes || (CompletionTypes = {}));

var Keywords;
(function (Keywords) {
    Keywords["SE"] = "SE";
    Keywords["SENAO"] = "SENAO";
    Keywords["CONTENHA"] = "CONTENHA";
    Keywords["ENTAO"] = "ENTAO";
    Keywords["FIM_SE"] = "FIM_SE";
    Keywords["NAO"] = "NAO";
    Keywords["E"] = "E";
    Keywords["OU"] = "OU";
})(Keywords || (Keywords = {}));

/* Interfaces */

const baseConfigs = LRLanguage.define({
    parser: buildParser(parserGrammar)
        .configure({
        props: [
            styleTags({
                [Object.values(Keywords).join(" ")]: tags.keyword,
                "String": tags.string,
                "Number": tags.number,
            })
        ]
    })
});

/**
 * Formats a JSON response to a JS object
 * @param response The response to format
 * @returns A JS object based on the response's body
 */
async function formatJsonResponse(response) {
    return response.json();
}

/**
 * Formats a Blob response to a JS object
 * @param response The response to format
 * @returns A JS object based on the response's body
 */
async function formatBlobResponse(response) {
    const textResponse = await (await response.blob()).text();
    return JSON.parse(textResponse);
}

/**
 * Custom HttpClient for cases when is not possible to use the Angular's HttpClient
 */
class CustomHttpClient {
    static _responseFormatterMap = new Map([
        ["application/json", formatJsonResponse],
        ["application/octet-stream", formatBlobResponse]
    ]);
    /**
     * Executes a Http Get
     * @param url Url to execute the Get on
     * @param init Optional additional configs
     * @returns Whether a Promise<T> on request success or an error in request fail
     */
    static async GET(url, init = {}) {
        const response = await this.interceptRequest(url, {
            ...init,
            method: "GET"
        });
        return this.formatResponse(response);
    }
    /**
     * Executes a Http Post
     * @param url Url to execute the Post on
     * @param body Info to send to server on Post
     * @param init Optional additional configs
     * @returns Whether a Promise<T> on request success or an error in request fail
     */
    static async POST(url, body, init = {}) {
        const headers = new Headers(init.headers);
        headers.append("Content-Type", "application/json");
        headers.append("Accept", "application/json");
        const response = await this.interceptRequest(url, {
            ...init,
            method: "POST",
            body: JSON.stringify(body),
            headers,
        });
        return this.formatResponse(response);
    }
    /**
     * Intercepts the original request to add a required header for Senior in case of a internal request
     * @param url Url from the original request
     * @param originalReq Configs from the original request
     * @returns Whether a Promise<Response> if the request was made successfully or an error
     */
    static async interceptRequest(url, originalReq = {}) {
        try {
            if (!url.includes("://")) {
                const restUrl = await service.getRestUrl();
                const authHeader = await user.getAuthHeader();
                const headers = new Headers(originalReq.headers);
                headers.append("Authorization", authHeader);
                const request = new Request(restUrl + url, {
                    ...originalReq,
                    headers
                });
                return fetch(request);
            }
            return fetch(url, originalReq);
        }
        catch (err) {
            throw new Error(`Error fetching requested URL: ${err}`);
        }
    }
    /**
     * Formats the request response to an object<T> or {}
     * @param response The response to be formatted
     * @returns Whether a Promise<T> if the response status is in the range 200-299 an error
     */
    static async formatResponse(response) {
        const contentType = response.headers.get("content-type");
        const formatter = CustomHttpClient._responseFormatterMap.get(contentType);
        const formattedContentType = formatter ? await formatter(response) : {};
        if (response.ok)
            return formattedContentType;
        throw new Error(JSON.stringify(formattedContentType));
    }
}

/**
 * Custom translator for cases when is not possible to use the "TranslateService" from "@ngx-translate/core"
 */
class CustomTranslationsService {
    static _translations = {};
    static _TRANSLATION_PREFIX = "";
    /**
     * Method used to get the translation for an key based on the host project's translations. Always use the first available language
     * @param key Key used to search the translation
     * @returns The translation for the informed key or the key in case there is no translation
     */
    static translate(key) {
        if (key === undefined || key === null) {
            return '';
        }
        const translationKey = `${CustomTranslationsService._TRANSLATION_PREFIX}${key}`;
        const firstLanguageTranslations = Object.values(CustomTranslationsService._translations)[0] ?? {};
        return firstLanguageTranslations[translationKey] ?? translationKey;
    }
    /**
     * Method used to set the translations that will be used as base when calling the "translate" method
     * @param translations Translations to use as base
     */
    static setTranslations(translations) {
        CustomTranslationsService._translations = translations ?? {};
    }
    /**
     * Method used to set the prefix that will be used when calling the "translate" method
     * @param hostProjectConfigs The host project's configs used to create the prefix
     */
    static setTranslationsPrefix(hostProjectConfigs) {
        const { domain, service } = hostProjectConfigs ?? {};
        const prefix = `${domain}.${service}.`;
        CustomTranslationsService._TRANSLATION_PREFIX = prefix;
    }
}

/**
 * Responsible for setting up the translations that will be used by the "CustomTranslationsService".
 * Uses the host project's translations set by using the "TranslationsModule" from "@seniorsistemas/platform-components"
 */
class CustomTranslationsModule {
    translate = inject(TranslateService);
    hostProjectConfigs = inject(HostProjectConfigsInjectionToken);
    constructor() {
        this.factoryTranslations(this.translate, this.hostProjectConfigs);
    }
    factoryTranslations(translate, hostProjectConfigs) {
        CustomTranslationsService.setTranslations(translate.translations);
        CustomTranslationsService.setTranslationsPrefix(hostProjectConfigs);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CustomTranslationsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
    static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: CustomTranslationsModule });
    static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CustomTranslationsModule });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CustomTranslationsModule, decorators: [{
            type: NgModule
        }], ctorParameters: () => [] });

var MarkerSeverity;
(function (MarkerSeverity) {
    MarkerSeverity[MarkerSeverity["Error"] = 0] = "Error";
    MarkerSeverity[MarkerSeverity["Info"] = 1] = "Info";
    MarkerSeverity[MarkerSeverity["Warning"] = 2] = "Warning";
})(MarkerSeverity || (MarkerSeverity = {}));

/* Interfaces */

const diagnosticSeverityInMarkerSeverityMap = new Map([
    [MarkerSeverity.Error, "error"],
    [MarkerSeverity.Info, "info"],
    [MarkerSeverity.Warning, "warning"]
]);
function convertMarkersToDiagnostics(markers, textLength) {
    return markers.map(marker => ({
        from: marker.start || 0,
        to: marker.end || textLength,
        message: marker.message ?? "",
        severity: diagnosticSeverityInMarkerSeverityMap.get(marker.severity) ?? "error"
    }));
}

function isCurrentPositionInsideString(stringBeforeCurrentPosition) {
    const doubleQuotesQuantity = stringBeforeCurrentPosition.match(/"/g)?.length || 0;
    return doubleQuotesQuantity % 2 !== 0;
}

class AutocompleteService {
    static BASE_URL = "platform/rule_metadata";
    static async listContextMetadataById(request, abortSignal) {
        return CustomHttpClient.POST(`${AutocompleteService.BASE_URL}/queries/listContextMetadataById`, request, {
            signal: abortSignal
        });
    }
    static async listExpressionMetadata(request, abortSignal) {
        return CustomHttpClient.POST(`${AutocompleteService.BASE_URL}/queries/listExpressionMetadata`, request, {
            signal: abortSignal
        });
    }
    static async listFacadeMetadataNames(request, abortSignal) {
        return CustomHttpClient.POST(`${AutocompleteService.BASE_URL}/queries/listFacadeMetadataNames`, request, {
            signal: abortSignal
        });
    }
    static async getFacadeMetadataByPath(request, abortSignal) {
        return CustomHttpClient.POST(`${AutocompleteService.BASE_URL}/queries/getFacadeMetadataByPath`, request, {
            signal: abortSignal
        });
    }
}

/**
 * Adds style to autocomplete's state-wrapper
 * @returns An extension containing the style
 */
function style$6() {
    return EditorView.theme({
        ".s-code-editor-taxCalculation-autocomplete-ul": {
            "padding": ".75rem !important",
        },
        ".s-code-editor-taxCalculation-autocomplete-li": {
            cursor: "default !important",
            "line-height": "1.375em !important",
        },
    });
}

let htmlElementToBeWrapped = null;
/**
 * Adds a view updates's listener that creates an state over the autocomplete
 * @returns An extension containing everything needed to listen the updates and create the autocomplete's state
 */
function autocompleteStateWrapper() {
    return [
        autocompleteStateWrapperStateField(),
        style$6()
    ];
}
/**
 * Shows a state on a non-clickable autocomplete item's format with an HTMLElement inside
 * @param element The HTMLElement to show inside the state
 */
function showAutocompleteStateWrapper(element) {
    htmlElementToBeWrapped = element;
    CodeMirror6Core.updateEditorView();
}
/**
 * Removes a possible showed autocomplete state
 */
function hideAutocompleteStateWrapper() {
    htmlElementToBeWrapped = null;
    CodeMirror6Core.updateEditorView();
}
/*
 * Creates and returns a StateField responsible for listening the view's change and to add the autocomplete
 * state's wrapper
 */
function autocompleteStateWrapperStateField() {
    return StateField.define({
        create: getAutocompleteStateWrapper,
        update(_, transaction) {
            return getAutocompleteStateWrapper(transaction.state);
        },
        provide(field) {
            return showTooltip.compute([field], state => state.field(field));
        }
    });
}
/*
 * Function responsible for creating the state's wrapper and returning the same as a Tooltip from "@codemirror/tooltip";
 * Only creates the Tooltip if the theres is element on the "htmlElementToBeWrapped" variable;
 * The same will also be removed when any view update is emitted;
 */
function getAutocompleteStateWrapper(state) {
    if (!htmlElementToBeWrapped) {
        return undefined;
    }
    const htmlElementToBeWrappedString = htmlElementToBeWrapped.outerHTML;
    const stateWrapper = {
        pos: state.selection.ranges[0].head,
        create: () => ({ dom: getAutocompleteStateWrapperDomElement(htmlElementToBeWrappedString) })
    };
    htmlElementToBeWrapped = null;
    return stateWrapper;
}
function getAutocompleteStateWrapperDomElement(elementToBeWrappedString) {
    const wrapperDiv = document.createElement('div');
    wrapperDiv.className = 'cm-tooltip-autocomplete cm-tooltip';
    wrapperDiv.innerHTML =
        `
        <ul class="s-code-editor-taxCalculation-autocomplete-ul">
            <li class="s-code-editor-taxCalculation-autocomplete-li">
                ${elementToBeWrappedString}
            </li>
        </ul>

    `;
    return wrapperDiv;
}

let autocompleteLoadingStateHTMLElement;
/**
 * Adds a loading-state over the autocomplete
 * @returns An extension containing everything needed to add the loading-state
 */
function autocompleteLoadingState() {
    return [autocompleteStateWrapper()];
}
/**
 * Activates the loading state on the autocomplete
 */
/*
 * Must set the "autocompleteLoadingStateHTMLElement" here for when the document is loaded we do not have
 * yet the "CustomTranslationsService" ready
 */
function showAutocompleteLoadingState() {
    if (!autocompleteLoadingStateHTMLElement) {
        autocompleteLoadingStateHTMLElement = getAutocompleteLoadingStateHTMLElement();
    }
    showAutocompleteStateWrapper(autocompleteLoadingStateHTMLElement);
}
function getAutocompleteLoadingStateHTMLElement() {
    const loadingStateSpanWrapper = document.createElement("span");
    loadingStateSpanWrapper.innerText = CustomTranslationsService.translate("core_language_tax_calculation_fetching_suggestions");
    return loadingStateSpanWrapper;
}

let autocompleteEmptyStateHTMLElement;
/**
 * Adds an empty-state over the autocomplete
 * @returns An extension containing everything needed to add the empty-state
 */
function autocompleteEmptyState() {
    return [autocompleteStateWrapper()];
}
/**
 * Activates the empty-state on the autocomplete
 */
/*
 * Must set the "autocompleteEmptyStateHTMLElement" here for when the document is loaded we do not have
 * yet the "CustomTranslationsService" ready
 */
function showAutocompleteEmptyState() {
    if (!autocompleteEmptyStateHTMLElement) {
        autocompleteEmptyStateHTMLElement = getAutocompleteEmptyStateHTMLElement();
    }
    showAutocompleteStateWrapper(autocompleteEmptyStateHTMLElement);
}
function getAutocompleteEmptyStateHTMLElement() {
    const emptyStateSpanWrapper = document.createElement("span");
    emptyStateSpanWrapper.innerText = CustomTranslationsService.translate("core_language_tax_calculation_no_suggestions");
    return emptyStateSpanWrapper;
}

class TaxCalculationLanguageConfigs {
    static CONFIGS = { contexts: [] };
    static setConfigs(configs) {
        TaxCalculationLanguageConfigs.CONFIGS = JSON.parse(JSON.stringify(configs));
    }
    static getConfigs() {
        return TaxCalculationLanguageConfigs.CONFIGS;
    }
}

/**
 * Gets the configs for the TaxCalculationLanguage
 * @returns The configs
 */
function getLanguageConfigs() {
    const configs = TaxCalculationLanguageConfigs.getConfigs();
    if (!configs.contexts?.length)
        throw new Error("In order to use the TaxCalculation Language's autocomplete, "
            + "one must inform at least one context by using the "
            + "'TaxCalculationLanguageConfigs.setConfigs()'");
    return configs;
}

/**
 * Wraps the request to return the same with an identification or undefined in case of error, so the promise will
 * always trigger the "then"
 * @param request Request to wrap
 * @returns The typed request's response
 */
async function getSafeResponse(request) {
    try {
        return {
            ...request,
            response: await request.request
        };
    }
    catch (_) {
        return undefined;
    }
}

/**
 * Adds style to the autocomplete
 * @returns An extension containing the style
 */
function style$5() {
    return EditorView.theme({
        ".cm-completionIcon": {
            "font-family": "'Font Awesome 5 Pro'",
            "font-weight": "900",
        },
        ".cm-completionIcon-keyword::after": {
            "content": getIconBasedOnUnicode("f084"),
        },
        ".cm-completionIcon-context::after": {
            "content": getIconBasedOnUnicode("f466"),
        },
        ".cm-completionIcon-expression::after": {
            "content": getIconBasedOnUnicode("f505"),
        },
        ".cm-completionIcon-userExpression::after": {
            "content": getIconBasedOnUnicode("f4ff"),
        },
        ".cm-completionIcon-entity::after": {
            "content": getIconBasedOnUnicode("f126"),
        },
        ".cm-completionIcon-finalValue::after": {
            "content": getIconBasedOnUnicode("f192"),
        },
    });
}
function getIconBasedOnUnicode(unicode) {
    return `"\\${unicode}"`;
}

/**
 * Adds an autocomplete to the editor
 * @returns An extension containing everything needed to create the autocomplete
 */
function autocomplete() {
    return [
        autocompletion({ override: [getCompletionResults] }),
        autocompleteLoadingState(),
        autocompleteEmptyState(),
        style$5(),
    ];
}
const TRANSLATION_PREFIX = 'core_language_tax_calculation';
let completionResults;
/*
 * A function to be called when a key is pressed, the ctrl+space is triggered or when the search for
 * completionResults is done.
 * If there is a completionResult, returns it, otherwise starts a new async search.
 * Will only execute the autocompletion if the current cursor position is not inside a string
 */
function getCompletionResults(context) {
    const isCursorInsideString = isCurrentPositionInsideString(context.state.doc.toString().substring(0, context.pos));
    if (isCursorInsideString) {
        return null;
    }
    ;
    if (completionResults) {
        const finalCompletionResults = { ...completionResults };
        const codeLength = context.state.doc.toString().length;
        finalCompletionResults.from = finalCompletionResults.from > codeLength ? codeLength : finalCompletionResults.from;
        completionResults = null;
        return finalCompletionResults;
    }
    startCompletionResultsSearch(context);
    return null;
}
let cancelLastCompletionSearch = () => { };
let codeMirrorViewElement;
/*
 * Starts a new completionResults's async search.
 * Avoids the last search to be finished by calling the "cancelLastCompletionSearch" callback function
 */
function startCompletionResultsSearch(context) {
    const token = new AbortController();
    setTimeout(() => {
        if (!token.signal.aborted) {
            showAutocompleteLoadingState();
            searchCompletionResults(context, token);
        }
    }, 500);
    /*
     * IMPORTANT: The following lines MUST be the way they are!
     * Here is being add the listener to any keydown/click event so when any key is downed or mouse clicked, we cancel
     * the last request.
     * We do this to not show to the user a completionItem in an incorrect place of text, that can be done by either
     * pressing the * arrows, home, end, backspace and etc. The flow is:
     * 1. We add an eventListener to keydown/click when the autocompletion's request is triggered;
     * 2. When any key/click is pressed, we remove the listener and cancel the last request by changing the
     * isSearchCanceled on token object to true;
     * 3. If any key that requires autocompletion is triggered, the flow repeats;
     */
    codeMirrorViewElement = CodeMirror6Core.getEditorView().contentDOM;
    cancelLastCompletionSearch = () => {
        codeMirrorViewElement.removeEventListener('keydown', cancelLastCompletionSearch);
        codeMirrorViewElement.removeEventListener('click', cancelLastCompletionSearch);
        token.abort();
    };
    codeMirrorViewElement.addEventListener('keydown', cancelLastCompletionSearch);
    codeMirrorViewElement.addEventListener('click', cancelLastCompletionSearch);
}
/*
 * Requests the necessary items to fill the completionResults, although it only really opens the autocomplete
 * box (by calling the "startCompletion()", that calls the "getCompletionResults") if the current search
 * was not cancelled by a new one
 */
async function searchCompletionResults(context, token) {
    const codeBeforeCursor = context?.state?.doc?.toString().substring(0, context?.pos ?? 0) ?? '';
    const filter = getFilter(codeBeforeCursor);
    const path = getPath(codeBeforeCursor, filter.length);
    const requests = getRequestsBasedOnPath(path, filter, token.signal);
    Promise.all(requests).then((responses) => {
        if (!token.signal.aborted) {
            const completions = [].concat(getKeywordsCompletions(path), getContextsCompletions(responses), getExpressionsCompletions(responses), getEntitiesCompletions(responses));
            const filteredCompletions = getFilteredCompletions(completions, filter);
            if (filteredCompletions.length) {
                const formattedCompletions = getFormattedCompletions(filteredCompletions, filter);
                const sortedCompletions = getSortedCompletions(formattedCompletions);
                completionResults = {
                    from: context.pos,
                    filter: false,
                    options: sortedCompletions,
                };
                startCompletion(CodeMirror6Core.getEditorView());
            }
            else {
                showAutocompleteEmptyState();
            }
        }
    });
}
/*
 * Returns the filter in the code written.
 * For example in the code "controladoria.empresa", "empresa" would be the filter
 * and in "controladoria", "controladoria" would be the filter.
 * Allows only alphanumerics, underscore and hashtag on filter's start.
 * Does not allow spaces
 */
function getFilter(string) {
    if (string === undefined || string === null) {
        return '';
    }
    const regex = /(#|\.|)\w*$/;
    const match = regex.exec(string);
    const filter = match ? match[0] : '';
    return filter.replace('.', '').trim();
}
/*
 * Returns the path in the code written based on filter.
 * For example in the code "controladoria.empresa", "controladoria" would be the path
 * and in "controladoria", "" would be the path.
 * Does not allow spaces
 */
function getPath(string, filterLength) {
    if (string === undefined || string === null) {
        return '';
    }
    const stringWithoutPath = string.substring(0, string.length - filterLength);
    const regex = /(\w*\.)*$/;
    const match = regex.exec(stringWithoutPath);
    const path = match ? match[0] : '';
    return path.replace(/\.$/, '');
}
function getRequestsBasedOnPath(path, filter, abortSignal) {
    const languageConfigs = getLanguageConfigs();
    const requests = [];
    if (path === '') {
        requests.push({
            requestType: RequestTypes.ListContextMetadataById,
            request: AutocompleteService.listContextMetadataById({
                id: languageConfigs.contexts,
            }, abortSignal),
        });
        requests.push({
            requestType: RequestTypes.ListExpressionMetadata,
            request: AutocompleteService.listExpressionMetadata({
                context: languageConfigs.contexts,
                subcontext: languageConfigs.subContexts ?? [],
                name: filter,
                pageRequest: {
                    offset: 0,
                    size: 20,
                },
            }, abortSignal),
        });
    }
    else if (path.includes('.')) {
        const splittedPath = path.split('.');
        requests.push({
            requestType: RequestTypes.GetFacadeMetadataByPath,
            request: AutocompleteService.getFacadeMetadataByPath({
                context: splittedPath[0],
                entityName: splittedPath[1],
                fields: splittedPath[2] === undefined ? undefined : splittedPath.slice(2),
            }, abortSignal),
        });
    }
    else {
        requests.push({
            requestType: RequestTypes.ListFacadeMetadataNames,
            request: AutocompleteService.listFacadeMetadataNames({
                context: [path],
                name: filter,
                pageRequest: {
                    offset: 0,
                    size: 30,
                },
            }, abortSignal),
        });
    }
    return requests.map((request) => getSafeResponse(request));
}
function getKeywordsCompletions(path) {
    if (path !== '') {
        return [];
    }
    const completions = [
        {
            label: Keywords.SE,
            apply: 'SE ()\nENTAO\n\tacao\nFIM_SE',
        },
        {
            label: Keywords.SENAO,
            apply: 'SENAO\n\tacao',
        },
        {
            label: Keywords.CONTENHA,
            apply: 'CONTENHA(condicao)',
        },
        {
            label: Keywords.ENTAO,
            apply: 'ENTAO\n\tacao',
        },
        {
            label: Keywords.FIM_SE,
            apply: 'FIM_SE ',
        },
        {
            label: Keywords.NAO,
            apply: 'NAO ',
        },
        {
            label: Keywords.E,
            apply: 'E ',
        },
        {
            label: Keywords.OU,
            apply: 'OU ',
        },
    ];
    return completions.map((completionItem) => ({
        ...completionItem,
        detail: CustomTranslationsService.translate(`${TRANSLATION_PREFIX}_keyword`),
        type: CompletionTypes.Keyword,
    }));
}
function getContextsCompletions(responses = []) {
    const contextsResponse = responses.find((response) => response?.requestType === RequestTypes.ListContextMetadataById);
    if (contextsResponse) {
        return (contextsResponse.response?.contextMetadata ?? []).map((contextMetadata) => ({
            label: contextMetadata.name,
            detail: CustomTranslationsService.translate(`${TRANSLATION_PREFIX}_context`),
            apply: contextMetadata.name,
            type: CompletionTypes.Context,
        }));
    }
    return [];
}
function getExpressionsCompletions(responses = []) {
    const expressionsResponse = responses.find((response) => response?.requestType === RequestTypes.ListExpressionMetadata);
    if (expressionsResponse) {
        return (expressionsResponse.response?.expressionMetadata ?? []).map((expressionMetadata) => ({
            label: expressionMetadata.name,
            detail: CustomTranslationsService.translate(`${TRANSLATION_PREFIX}_${expressionMetadata.type === MetaType.PUBLIC_EXPRESSION ? 'senior_expression' : 'user_expression'}`),
            apply: expressionMetadata.name,
            info: expressionMetadata.description,
            type: expressionMetadata.type === MetaType.PUBLIC_EXPRESSION
                ? CompletionTypes.Expression
                : CompletionTypes.UserExpression,
        }));
    }
    return [];
}
function getEntitiesCompletions(responses = []) {
    const facadesResponseFromList = responses.find((response) => response?.requestType === RequestTypes.ListFacadeMetadataNames);
    if (facadesResponseFromList) {
        return (facadesResponseFromList.response?.facadeMetadataNames ?? []).map((facade) => ({
            label: facade.name,
            detail: CustomTranslationsService.translate(`${TRANSLATION_PREFIX}_entity`),
            apply: facade.name,
            type: CompletionTypes.Entity,
        }));
    }
    const facadesResponseFromGet = responses.find((response) => response?.requestType === RequestTypes.GetFacadeMetadataByPath);
    if (facadesResponseFromGet) {
        return (facadesResponseFromGet.response?.facadeMetadata?.fields ?? []).map((facade) => ({
            label: facade.name,
            detail: CustomTranslationsService.translate(`${TRANSLATION_PREFIX}_${facade.type === MetaType.ENTITY ? 'entity' : 'field'}`),
            apply: facade.name,
            type: facade.type === MetaType.ENTITY ? CompletionTypes.Entity : CompletionTypes.FinalValue,
        }));
    }
    return [];
}
/*
 * Filtering the completions to only deal with the necessary items
 */
function getFilteredCompletions(completions, filter) {
    return completions.filter((completionItem) => completionItem.label.toLowerCase().startsWith(filter.toLowerCase()));
}
/*
 * Overwriting the completions's apply to remove the entire current written value and apply the the entire
 * completion's apply
 */
function getFormattedCompletions(completions, filter) {
    return completions.map((completionItem) => ({
        ...completionItem,
        apply: getCompletionApply(filter, `${completionItem.apply}`),
    }));
}
function getCompletionApply(filter, oldApplyText) {
    return (view, completion, from, to) => {
        const newFrom = from - filter.length;
        view.dispatch({
            changes: {
                to,
                from: newFrom,
                insert: oldApplyText,
            },
            selection: {
                anchor: newFrom + oldApplyText.length,
            },
            userEvent: 'input.complete',
            annotations: pickedCompletion.of(completion),
        });
    };
}
const completionsSortOrder = [
    CompletionTypes.Keyword,
    CompletionTypes.Context,
    CompletionTypes.UserExpression,
    CompletionTypes.Expression,
    CompletionTypes.Entity,
    CompletionTypes.FinalValue,
];
/*
 * Sorts the completions following the "completionsSortOrder" priority order
 */
function getSortedCompletions(completions) {
    return completions.sort((x, y) => {
        const xPriority = completionsSortOrder.indexOf(x.type);
        const yPriority = completionsSortOrder.indexOf(y.type);
        return xPriority - yPriority;
    });
}

function TaxCalculation() {
    return new LanguageSupport(baseConfigs, [
        autocomplete(),
    ]);
}

const jsonGrammar = `
@top JsonDocument { JsonValue }

JsonValue {
    JsonObject |
    JsonArray |
    JsonString |
    JsonNumber |
    JsonBoolean |
    JsonNull
}

JsonObject {
    "{" (JsonPair ("," JsonPair)*)? "}"
}

JsonPair {
    JsonString ":" JsonValue
}

JsonArray {
    "[" (JsonValue ("," JsonValue)*)? "]"
}

@tokens {
    JsonString { '"' (![\\n"])* '"'? }
    JsonNumber {
        '-'? std.digit+
        ('.' std.digit+)?
        (("e" | "E") ("+" | "-")? std.digit+)?
    }
    JsonBoolean { "true" | "false" }
    JsonNull { "null" }
    space { $[ \t\n\r]+ }
    "{" "}"
    "[" "]"
    ":" ","
}

@skip { space }

@detectDelim
`;
const jsonLanguage = LRLanguage.define({
    parser: buildParser(jsonGrammar).configure({
        props: [
            styleTags({
                JsonString: tags.string,
                JsonNumber: tags.number,
                "JsonBoolean JsonNull": tags.keyword,
                '"{"': tags.brace,
                '"}"': tags.brace,
                '"["': tags.brace,
                '"]"': tags.brace,
                '":"': tags.operator,
                '","': tags.punctuation,
            }),
        ],
    }),
});
function Json() {
    return new LanguageSupport(jsonLanguage);
}

class EditorLanguages {
    static _LANGUAGES = new Map([
        [Languages.TaxCalculation, TaxCalculation],
        [Languages.Json, Json]
    ]);
    static getLanguage(language) {
        const languageSupportFactory = EditorLanguages._LANGUAGES.get(language);
        if (languageSupportFactory)
            return languageSupportFactory();
        return [];
    }
}

/**
 * Adds style to the editor in general
 * @returns An extension containing the style
 */
function style$4() {
    return EditorView.theme({
        "&.cm-editor.cm-focused": {
            outline: "none",
        },
    });
}

const SDSLightHighlightStyle = HighlightStyle.define([
    {
        tag: tags.keyword,
        color: "#008080",
    },
    {
        tag: tags.string,
        color: "#9C3A3A",
    },
    {
        tag: tags.number,
        color: "#400753",
    },
]);

/**
 * Adds a vertical scrollbar when the editor's height overflows the parent's height
 * @returns An extension containing everything needed to add the scrollbar
 */
function scrollbars() {
    return [
        style$3()
    ];
}
function style$3() {
    return EditorView.baseTheme({
        "&.cm-editor": {
            "height": "100%"
        },
    });
}

/**
 * Adds style to editor'font
 * @returns An extension containing everything needed to add the font style
 */
function fontStyle() {
    return [style$2()];
}
const generalFontStyle = {
    "font-family": "'Noto Sans Mono', 'sans-serif'",
    "font-style": "normal",
    "font-size": "1rem",
};
function style$2() {
    return EditorView.theme({
        ".cm-scroller": {
            ...generalFontStyle,
            "letter-spacing": "0",
            "line-height": "1.5em",
            "font-variation-settings": "'wght' 400",
            "color": "#333333",
        },
        ".cm-tooltip.cm-tooltip-autocomplete > ul": {
            ...generalFontStyle,
            "font-variation-settings": "'wght' 300",
            "color": "#697882",
        },
        ".cm-tooltip.cm-tooltip-autocomplete > ul .cm-completionLabel": {
            "line-height": "1.5em",
            "font-variation-settings": "'wght' 500",
        },
        ".cm-tooltip.cm-tooltip-autocomplete > ul .cm-completionDetail": {
            "font-size": "0.875em",
            "font-style": "normal",
            "margin-left": "0.75rem",
        },
    });
}

/**
 * Adds a line counter
 * @returns An extension containing everything needed to add the line counter
 */
function lineCounter() {
    return [
        lineNumbers(),
        style$1()
    ];
}
function style$1() {
    return EditorView.theme({
        ".cm-gutters": {
            "background-color": "#fff",
            "color": "#428BCA",
            "border-right": "none"
        },
        ".cm-gutter": {
            "padding": "0 2rem 0 2rem"
        }
    });
}

/**
 * Adds styles to the autocomplete's tooltip
 * @returns An extension containing everything needed to add the style
 */
function autocompleteTooltip() {
    return [style()];
}
function style() {
    return EditorView.baseTheme({
        ".cm-tooltip": {
            "border": "none !important",
            "border-radius": "4px",
            "background-color": "#E5EAEA !important",
        },
        ".cm-tooltip.cm-tooltip-autocomplete > ul[role='listbox']": {
            "padding": "1rem",
        },
        ".cm-tooltip.cm-tooltip-autocomplete > ul .cm-completionDetail": {
            "margin-left": ".75rem",
        },
        ".cm-tooltip.cm-tooltip-autocomplete > ul .cm-completionDetail::before": {
            "content": "'[ '",
        },
        ".cm-tooltip.cm-tooltip-autocomplete > ul .cm-completionDetail::after": {
            "content": "' ]'",
        },
        ".cm-tooltip.cm-tooltip-autocomplete > ul .cm-completionIcon": {
            "padding-right": 0,
            "margin-right": ".475rem",
            "width": "1rem",
        },
        ".cm-tooltip-autocomplete ul li[aria-selected]": {
            "border-radius": "4px",
            "background-color": "#5D96A2 !important",
            "color": "#fff !important",
        },
        ".cm-tooltip.cm-completionInfo.cm-completionInfo-right": {
            "border-radius": "3px",
            "box-shadow": "0 2px 4px -1px rgb(0 0 0 / 20%), 0 4px 5px 0 rgb(0 0 0 / 14%), 0 1px 10px 0 rgb(0 0 0 / 12%)",
            "background": "#495057 !important",
            "color": "#fff",
            "padding": ".5rem",
            "left": "101.6%",
        },
        ".cm-tooltip.cm-completionInfo.cm-completionInfo-right::before": {
            "content": "''",
            "position": "absolute",
            "width": 0,
            "height": 0,
            "top": ".8125rem",
            "left": "-.25rem",
            "margin-top": "-.25rem",
            "border-color": "transparent",
            "border-style": "solid",
            "border-right-color": "#495057",
            "border-width": ".25rem .25rem .25rem 0",
        },
    });
}

/* General Style */
function SDSLight() {
    return [
        [
            style$4(),
            scrollbars(),
            fontStyle(),
            lineCounter(),
            autocompleteTooltip()
        ],
        SDSLightHighlightStyle
    ];
}

class EditorThemes {
    static _THEMES = new Map([
        [Themes.SDSLight, SDSLight]
    ]);
    static getTheme(theme) {
        const EditorThemeFactory = EditorThemes._THEMES.get(theme);
        if (EditorThemeFactory)
            return EditorThemeFactory();
        return [];
    }
}

class CodeMirror6Core extends CoreFacade {
    static $onCompletionItemsUpdate = new Subject();
    static _ngUnsubscribe = new Subject();
    static _editorView = null;
    /* These are necessary for the setCode and setEditorOptions can be called before view has been created */
    _codeReceivedBeforeViewCreation = '';
    _editorOptionsReceivedBeforeViewCreation = [];
    constructor() {
        super();
    }
    static getEditorView() {
        return CodeMirror6Core._editorView;
    }
    static updateEditorView(...transactionSpecs) {
        CodeMirror6Core._editorView?.dispatch(...transactionSpecs);
    }
    setCoreWrapperElement(element) {
        this.createEditorView(element);
    }
    setCode(code) {
        this.changeEditorContent(code);
    }
    initCore() {
        this.setObservablesListeners();
    }
    destroyCore() {
        this._codeReceivedBeforeViewCreation = '';
        CodeMirror6Core._editorView = null;
        CodeMirror6Core._ngUnsubscribe.next();
        CodeMirror6Core._ngUnsubscribe.complete();
    }
    setCoreEditorOptions(options) {
        const language = EditorLanguages.getLanguage(options.language);
        const theme = EditorThemes.getTheme(options.theme);
        if (CodeMirror6Core._editorView) {
            CodeMirror6Core.updateEditorView({
                effects: StateEffect.reconfigure.of([language, theme, this.getCodeChangeListenerExtension()]),
            });
        }
        else {
            this._editorOptionsReceivedBeforeViewCreation = [language, theme];
        }
    }
    highlightCode(markers) {
        const diagnostics = convertMarkersToDiagnostics(markers, CodeMirror6Core._editorView?.state.doc.length);
        CodeMirror6Core.updateEditorView(setDiagnostics(CodeMirror6Core._editorView?.state, diagnostics));
    }
    setObservablesListeners() {
        CodeMirror6Core.$onCompletionItemsUpdate
            .pipe(takeUntil(CodeMirror6Core._ngUnsubscribe))
            .subscribe((items) => this.updateCompletionItems(items));
    }
    createEditorView(parentElement) {
        CodeMirror6Core._editorView = new EditorView({
            parent: parentElement,
            state: EditorState.create({
                doc: this._codeReceivedBeforeViewCreation,
                extensions: [this._editorOptionsReceivedBeforeViewCreation, this.getCodeChangeListenerExtension()],
            }),
        });
        this.notifyCoreFinishLoad();
    }
    getCodeChangeListenerExtension() {
        return EditorView.updateListener.of((update) => update.docChanged && this.notifyCodeChange(update.state.doc.toString()));
    }
    changeEditorContent(code) {
        if (CodeMirror6Core._editorView) {
            CodeMirror6Core.updateEditorView({
                changes: {
                    from: 0,
                    to: CodeMirror6Core._editorView.state.doc.length,
                    insert: code,
                },
            });
        }
        else {
            this._codeReceivedBeforeViewCreation = code;
        }
    }
    setCodeWithCursorPreservation(code) {
        if (CodeMirror6Core._editorView) {
            const currentCode = CodeMirror6Core._editorView.state.doc.toString();
            // Só atualiza se o conteúdo for realmente diferente
            if (currentCode !== code) {
                const currentSelection = CodeMirror6Core._editorView.state.selection.main;
                CodeMirror6Core.updateEditorView({
                    changes: {
                        from: 0,
                        to: CodeMirror6Core._editorView.state.doc.length,
                        insert: code,
                    },
                    selection: {
                        anchor: Math.min(currentSelection.anchor, code.length),
                        head: Math.min(currentSelection.head, code.length),
                    },
                });
            }
        }
        else {
            this._codeReceivedBeforeViewCreation = code;
        }
    }
}

class CodeEditorModule {
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CodeEditorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
    static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: CodeEditorModule, declarations: [CodeEditorComponent], imports: [CommonModule, CustomTranslationsModule], exports: [CodeEditorComponent] });
    static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CodeEditorModule, providers: [
            {
                provide: CoreFacade,
                useClass: CodeMirror6Core,
            },
        ], imports: [CommonModule, CustomTranslationsModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CodeEditorModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [CommonModule, CustomTranslationsModule],
                    declarations: [CodeEditorComponent],
                    exports: [CodeEditorComponent],
                    providers: [
                        {
                            provide: CoreFacade,
                            useClass: CodeMirror6Core,
                        },
                    ],
                }]
        }] });

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

export { CodeEditorComponent, CodeEditorModule, Languages, TaxCalculationLanguageConfigs, Themes };
//# sourceMappingURL=seniorsistemas-angular-components-code-editor.mjs.map
