import { Component, ChangeDetectionStrategy, ElementRef, Input, EventEmitter, Output } from '@angular/core';
import { isBlank, isPresent, nameof } from '@jscrpt/common';
import { editor, KeyCode, KeyMod, Uri } from 'monaco-editor';
import { monacoInit } from './monaco.init';
import * as i0 from "@angular/core";
/**
 * Component used for editing code
 */
export class CodeEditorComponent {
    //######################### constructor #########################
    constructor(element) {
        this.element = element;
        //######################### protected fields #########################
        /**
         * Instance of code editor
         */
        this.codeEditor = null;
        /**
         * Opened file in editor
         */
        this.openedFile = null;
        /**
         * Handler for event of change of model
         */
        this.changeEvent = null;
        //######################### public properties - outputs #########################
        /**
         * Occurs when content of editor is saved
         */
        this.save = new EventEmitter();
        /**
         * Occurs when content of editor changes, new value passed down
         */
        this.contentChange = new EventEmitter();
    }
    //######################### public methods - implementation of OnChanges #########################
    /**
     * Called when input value changes
     */
    ngOnChanges(changes) {
        if (nameof('languageModel') in changes && this.languageModel &&
            nameof('content') in changes && isPresent(this.content)) {
            this.updateContent();
        }
    }
    //######################### public methods - implementation of AfterViewInit #########################
    /**
     * Called when view was initialized
     */
    ngAfterViewInit() {
        this.createEditor();
    }
    //######################### public methods #########################
    /**
     * Saves currently opened document
     */
    async saveContent() {
        if (this.openedFile && this.codeEditor && this.languageModel) {
            this.save.emit({
                content: this.openedFile.getValue(),
                code: await this.languageModel.compiledCode(this.codeEditor)
            });
        }
    }
    //######################### public methods - implementation of OnDestroy #########################
    /**
     * Called when component is destroyed
     */
    ngOnDestroy() {
        this.changeEvent?.dispose();
        this.changeEvent = null;
        this.openedFile?.dispose();
        this.openedFile = null;
        this.codeEditor?.dispose();
        this.codeEditor = null;
    }
    //######################### protected methods #########################
    /**
     * Creates editor
     */
    createEditor() {
        this.codeEditor = editor.create(this.element.nativeElement, {
            theme: 'vs-dark',
            model: this.openedFile,
            lightbulb: {
                enabled: true
            },
            bracketPairColorization: {
                enabled: true,
            },
            minimap: {
                enabled: true
            },
        });
        this.codeEditor.addCommand(KeyMod.CtrlCmd | KeyCode.KeyS, () => {
            this.saveContent();
        });
        this.changeEvent = this.codeEditor.onDidChangeModelContent(async () => {
            if (this.openedFile && this.languageModel && this.codeEditor) {
                this.contentChange.emit({
                    content: this.openedFile.getValue(),
                    code: await this.languageModel.compiledCode(this.codeEditor)
                });
            }
        });
    }
    /**
     * Updates content of code editor
     */
    updateContent() {
        this.openedFile?.dispose();
        this.openedFile = null;
        if (!this.languageModel || isBlank(this.content)) {
            return;
        }
        this.openedFile = editor.createModel((this.content || this.languageModel.initialData) ?? '', this.languageModel.language, Uri.file(`file:///index.${this.languageModel.extension}`));
        this.codeEditor?.setModel(this.openedFile);
    }
}
//######################### public static properties #########################
/**
 * Indication whether was monaco init called
 */
CodeEditorComponent.monacoInit = monacoInit;
CodeEditorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.4", ngImport: i0, type: CodeEditorComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
CodeEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.4", type: CodeEditorComponent, selector: "code-editor", inputs: { content: "content", languageModel: "languageModel" }, outputs: { save: "save", contentChange: "contentChange" }, usesOnChanges: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.4", ngImport: i0, type: CodeEditorComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'code-editor',
                    template: '',
                    changeDetection: ChangeDetectionStrategy.OnPush
                }]
        }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { content: [{
                type: Input
            }], languageModel: [{
                type: Input
            }], save: [{
                type: Output
            }], contentChange: [{
                type: Output
            }] } });
//# sourceMappingURL=codeEditor.component.js.map