import {Component, ElementRef, HostListener, Input, OnInit, ViewChild} from '@angular/core';
import {EditorNodeContract} from '../EditorNode.contract';
import {EditorService} from '../../../service/editor.service';
import {v4} from 'uuid';
import {EditorComponent} from 'ngx-monaco-editor';

@Component({
    selector: 'editor-markdown',
    templateUrl: './markdown.component.html',
    styleUrls: ['./markdown.component.scss'],
})
export class MarkdownComponent extends EditorNodeContract implements OnInit {
    // @ViewChild('editable') editable;
    @Input() nodeId: string;
    @Input() editorUUID?: string;
    @ViewChild('editor') editor: EditorComponent;
    @ViewChild('editorContainer') editorContainer: ElementRef;

    // public isFocused = false;
    public initialValue = 'Double-click to edit...';
    protected savedValue = 'Double-click to edit...';
    public contents = '';
    private dirtyOverride = false;
    public showEditor = false;
    protected hadOneFocusOut = false;
    public singleColumn = false;
    public containerHeight = 540;

    public editorOptions = {
        theme: this.isDark() ? 'vs-dark' : 'vs',
        language: 'markdown',
        uri: v4(),
        readOnly: false,
        automaticLayout: true,
        wordWrap: 'on',
        scrollBeyondLastLine: false,
        scrollbar: {
            alwaysConsumeMouseWheel: false,
        },
    };

    constructor(
        public editorService: EditorService,
    ) {
        super();
        this.contents = this.initialValue;
        this.savedValue = this.initialValue;
    }

    public isDark() {
        return document.body.classList.contains('dark');
    }

    ngOnInit() {
        this.editorService = this.editorService.getEditor(this.editorUUID);
        this.editorService.registerNodeEditor(this.nodeId, this).then(() => {
            if ( !this.node.Value ) {
                this.node.Value = {};
            }

            if ( this.node.Value.Value ) {
                this.initialValue = this.node.Value.Value;
                this.savedValue = this.node.Value.Value;
            }

            this.contents = this.initialValue;
        });
    }

    onMonacoEditorInit(editor) {
        let ignoreEvent = false;
        const updateHeight = () => {
            const contentHeight = Math.max(540, editor.getContentHeight());
            this.containerHeight = contentHeight;

            try {
                ignoreEvent = true;
                editor.layout({ width: this.editorContainer.nativeElement.offsetWidth, height: contentHeight });
            } finally {
                ignoreEvent = false;
            }
        };

        editor.onDidContentSizeChange(updateHeight);
        updateHeight();
    }

    public isDirty(): boolean | Promise<boolean> {
        return this.dirtyOverride || this.contents !== this.savedValue;
    }

    public writeChangesToNode(): void | Promise<void> {
        this.node.Value.Mode = 'markdown';
        this.node.Value.Value = this.contents;
        this.node.value = this.contents;
        this.savedValue = this.contents;
    }

    onContentsChanged(event) {
        if ( event !== this.savedValue ) {
            this.editorService.triggerSave();
        }
    }

    onFocusIn() {
        this.showEditor = this.editorService.canEdit();
    }

    @HostListener('document:keyup.escape', ['$event'])
    onFocusOut(event) {
        if ( !this.hadOneFocusOut ) {
            this.hadOneFocusOut = true;
            setTimeout(() => {
                this.hadOneFocusOut = false;
            }, 500);
        } else {
            this.hadOneFocusOut = false;
            this.showEditor = false;
        }
    }

    onEditorHostResize($event) {
        if ( $event.newWidth < 700 && !this.singleColumn ) {
            this.singleColumn = true;
        } else if ( $event.newWidth > 700 && this.singleColumn ) {
            this.singleColumn = false;
        }
    }
}
