import { CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { inject, signal, computed, EventEmitter, Directive, Input, Output, NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatTooltipModule } from '@angular/material/tooltip';
import { ResizerModule } from '@metad/ocap-angular/common';
import { ThemesEnum, NgmThemeService, OcapCoreModule } from '@metad/ocap-angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { MonacoEditorModule } from 'ngx-monaco-editor';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { BehaviorSubject, Subject, Observable, Subscription } from 'rxjs';
import { filter, switchMap, debounceTime } from 'rxjs/operators';

const EditorThemeMap = {
    [ThemesEnum.light]: 'vs',
    [ThemesEnum.dark]: 'vs-dark'
};

class NgmBaseEditorDirective {
    constructor() {
        this.themeService = inject(NgmThemeService);
        this.editor$ = new BehaviorSubject(null);
        this.theme = '';
        this._options = signal({});
        this.actions = [];
        this.keyDown = this.editor$.pipe(filter(Boolean), switchMap(monacoKeydown));
        this.defaultOptions = {
            theme: 'vs',
            automaticLayout: true
        };
        this.editorOptions = computed(() => {
            return {
                language: this.languageId,
                ...this.defaultOptions,
                ...(this.options ?? {}),
                theme: EditorThemeMap[this.themeService.themeClass()]
            };
        });
        this.code = '';
        this._modelChange$ = new Subject();
        this.modelChange = this._modelChange$.pipe(debounceTime(500));
        // @Output() textSelectionChange = new EventEmitter<string>()
        this.selectionChange = new EventEmitter();
        this.cursorSelection$ = new Subject();
        this._providers = [];
        this.valueSub = this.modelChange.pipe(takeUntilDestroyed()).subscribe(() => {
            this.onChange(this.code);
        });
        this.cursorSelectionSub = this.cursorSelection$.pipe(debounceTime(300), takeUntilDestroyed()).subscribe((e) => {
            this.selectionChange.emit({ range: this.editor.getSelection(), text: this.getSelectText() });
        });
    }
    // CodeEditor
    get editor() {
        return this.editor$.value;
    }
    // CodeEditor options
    get options() {
        return this._options();
    }
    set options(value) {
        this._options.set(value);
    }
    onModelChange(event) {
        this._modelChange$.next(event);
    }
    onChange(event) {
        this._onChange?.(this.code);
    }
    writeValue(obj) {
        this.code = obj;
    }
    registerOnChange(fn) {
        this._onChange = fn;
    }
    registerOnTouched(fn) {
        //
    }
    setDisabledState(isDisabled) {
        isDisabled ? this.editor?.updateOptions({ readOnly: true }) : this.editor?.updateOptions({ readOnly: false });
    }
    onInit(editor) {
        this.editor$.next(editor);
        this.editor.onDidChangeCursorSelection((e) => {
            this.cursorSelection$.next(e);
        });
        // 用于控制切换该菜单键的显示
        const shouldShowSqlRunnerAction = editor.createContextKey('shouldShowSqlRunnerAction', true);
        this.actions?.forEach((action) => {
            const { id, label, action: runFn } = action;
            editor.addAction({
                id,
                label: label(),
                // 控制该菜单键显示
                precondition: 'shouldShowSqlRunnerAction',
                // 该菜单键位置
                contextMenuGroupId: 'navigation',
                contextMenuOrder: 1.5,
                // 点击该菜单键后运行
                run: (event) => {
                    const selectedText = editor.getModel()?.getValueInRange(editor.getSelection()) || '';
                    runFn(selectedText, { selection: editor.getSelection() });
                }
            });
        });
    }
    onResized(event) {
        this.editor?.layout();
    }
    dispose() {
        this._providers.forEach((provider) => provider.dispose());
    }
    formatDocument() {
        this.editor?.getAction('editor.action.formatDocument').run();
        // this.editor?.trigger("editor", "editor.action.formatDocument", "")
    }
    formatSelection() {
        this.editor?.getAction('editor.action.formatSelection').run();
        // this.editor?.trigger("editor", "editor.action.formatSelection", "")
    }
    compressDocument() {
        this.code = this.code.replace(/\r\n/g, ' ');
        this.code = this.code
            .split(' ')
            .filter((value) => !!value)
            .join(' ');
    }
    clearDocument() {
        this.code = '';
    }
    startFindAction() {
        this.editor.getAction('actions.find').run();
    }
    startFindReplaceAction() {
        this.editor.getAction('editor.action.startFindReplaceAction').run();
    }
    insert(text, position) {
        if (position) {
            this.editor.setPosition(position);
        }
        this.editor?.trigger('keyboard', 'type', { text: text });
    }
    undo() {
        this.editor.trigger('myeditor', 'undo');
    }
    redo() {
        this.editor.trigger('myeditor', 'redo');
    }
    getSelectText() {
        return this.editor?.getModel()?.getValueInRange(this.editor.getSelection());
    }
    appendText(text) {
        const lastLine = this.editor.getModel().getLineCount();
        const lastLineText = this.editor.getModel().getLineContent(lastLine);
        const lastLineLength = lastLineText.length;
        this.editor.getModel().pushEditOperations([], [
            {
                range: new monaco.Range(lastLine, lastLineLength + 1, lastLine, lastLineLength + 1),
                text
            }
        ], () => null);
    }
    applyEdits(edits) {
        // Apply the edit to the editor's model
        this.editor.getModel().applyEdits(edits);
    }
    ngOnDestroy() {
        this.dispose();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.10", ngImport: i0, type: NgmBaseEditorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.10", type: NgmBaseEditorDirective, selector: "[ngmEditor]", inputs: { theme: "theme", options: "options", textSelection: "textSelection", actions: "actions" }, outputs: { keyDown: "keyDown", modelChange: "modelChange", selectionChange: "selectionChange" }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.10", ngImport: i0, type: NgmBaseEditorDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngmEditor]'
                }]
        }], propDecorators: { theme: [{
                type: Input
            }], options: [{
                type: Input
            }], textSelection: [{
                type: Input
            }], actions: [{
                type: Input
            }], keyDown: [{
                type: Output
            }], modelChange: [{
                type: Output
            }], selectionChange: [{
                type: Output
            }] } });
function monacoKeydown(editor /* monaco.editor.IStandaloneCodeEditor */) {
    return new Observable((observer) => {
        const listener = editor.onKeyDown((event) => {
            observer.next(event);
        });
        return new Subscription(() => listener.dispose());
    });
}

class NgmFormulaModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.10", ngImport: i0, type: NgmFormulaModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.10", ngImport: i0, type: NgmFormulaModule, declarations: [NgmBaseEditorDirective], imports: [CommonModule,
            FormsModule,
            ReactiveFormsModule,
            MatMenuModule,
            MatSidenavModule,
            MatIconModule,
            MatButtonModule,
            MatTooltipModule,
            TranslateModule,
            MonacoEditorModule,
            OcapCoreModule,
            ResizerModule], exports: [NgmBaseEditorDirective] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.10", ngImport: i0, type: NgmFormulaModule, imports: [CommonModule,
            FormsModule,
            ReactiveFormsModule,
            MatMenuModule,
            MatSidenavModule,
            MatIconModule,
            MatButtonModule,
            MatTooltipModule,
            TranslateModule,
            MonacoEditorModule,
            OcapCoreModule,
            ResizerModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.10", ngImport: i0, type: NgmFormulaModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [
                        CommonModule,
                        FormsModule,
                        ReactiveFormsModule,
                        MatMenuModule,
                        MatSidenavModule,
                        MatIconModule,
                        MatButtonModule,
                        MatTooltipModule,
                        TranslateModule,
                        MonacoEditorModule,
                        OcapCoreModule,
                        ResizerModule,
                    ],
                    exports: [NgmBaseEditorDirective],
                    declarations: [NgmBaseEditorDirective],
                    providers: []
                }]
        }] });

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

export { EditorThemeMap, NgmBaseEditorDirective, NgmFormulaModule };
//# sourceMappingURL=metad-ocap-angular-formula.mjs.map
