import { t } from "../../services/i18n.js";
import NoteContextAwareWidget from "../note_context_aware_widget.js";
import noteAutocompleteService from "../../services/note_autocomplete.js";
import server from "../../services/server.js";
import contextMenuService from "../../menus/context_menu.js";
import attributeParser from "../../services/attribute_parser.js";
import libraryLoader from "../../services/library_loader.js";
import froca from "../../services/froca.js";
import attributeRenderer from "../../services/attribute_renderer.js";
import noteCreateService from "../../services/note_create.js";
import attributeService from "../../services/attributes.js";
import linkService from "../../services/link.js";
const HELP_TEXT = `
]+href="(#[A-Za-z0-9_/]*)"[^>]*>[^<]*<\/a>/g, "$1")
            .replace(/ /g, " "); // otherwise .text() below outputs non-breaking space in unicode
        return $("").html(str).text();
    }
    async initEditor() {
        await libraryLoader.requireLibrary(libraryLoader.CKEDITOR);
        this.$widget.show();
        this.$editor.on("click", e => this.handleEditorClick(e));
        /** @property {BalloonEditor} */
        this.textEditor = await BalloonEditor.create(this.$editor[0], editorConfig);
        this.textEditor.model.document.on('change:data', () => this.dataChanged());
        this.textEditor.editing.view.document.on('enter', (event, data) => {
            // disable entering new line - see https://github.com/ckeditor/ckeditor5/issues/9422
            data.preventDefault();
            event.stop();
        }, {priority: 'high'});
        // disable spellcheck for attribute editor
        this.textEditor.editing.view.change(writer => writer.setAttribute('spellcheck', 'false', this.textEditor.editing.view.document.getRoot()));
        //await import(/* webpackIgnore: true */'../../libraries/ckeditor/inspector');
        //CKEditorInspector.attach(this.textEditor);
    }
    dataChanged() {
        this.lastUpdatedNoteId = this.noteId;
        if (this.lastSavedContent === this.textEditor.getData()) {
            this.$saveAttributesButton.fadeOut();
        }
        else {
            this.$saveAttributesButton.fadeIn();
        }
        if (this.$errors.is(":visible")) {
            // using .hide() instead of .slideUp() since this will also hide the error after confirming
            // mention for relation name which suits up. When using.slideUp() error will appear and the slideUp which is weird
            this.$errors.hide();
        }
    }
    async handleEditorClick(e) {
        const pos = this.textEditor.model.document.selection.getFirstPosition();
        if (pos && pos.textNode && pos.textNode.data) {
            const clickIndex = this.getClickIndex(pos);
            let parsedAttrs;
            try {
                parsedAttrs = attributeParser.lexAndParse(this.getPreprocessedData(), true);
            }
            catch (e) {
                // the input is incorrect because the user messed up with it and now needs to fix it manually
                return null;
            }
            let matchedAttr = null;
            for (const attr of parsedAttrs) {
                if (clickIndex > attr.startIndex && clickIndex <= attr.endIndex) {
                    matchedAttr = attr;
                    break;
                }
            }
            setTimeout(() => {
                if (matchedAttr) {
                    this.$editor.tooltip('hide');
                    this.attributeDetailWidget.showAttributeDetail({
                        allAttributes: parsedAttrs,
                        attribute: matchedAttr,
                        isOwned: true,
                        x: e.pageX,
                        y: e.pageY
                    });
                }
                else {
                    this.showHelpTooltip();
                }
            }, 100);
        }
        else {
            this.showHelpTooltip();
        }
    }
    showHelpTooltip() {
        this.attributeDetailWidget.hide();
        this.$editor.tooltip({
            trigger: 'focus',
            html: true,
            title: HELP_TEXT,
            placement: 'bottom',
            offset: "0,30"
        });
        this.$editor.tooltip('show');
    }
    getClickIndex(pos) {
        let clickIndex = pos.offset - pos.textNode.startOffset;
        let curNode = pos.textNode;
        while (curNode.previousSibling) {
            curNode = curNode.previousSibling;
            if (curNode.name === 'reference') {
                clickIndex += curNode._attrs.get('notePath').length + 1;
            } else {
                clickIndex += curNode.data.length;
            }
        }
        return clickIndex;
    }
    async loadReferenceLinkTitle($el, href) {
        const {noteId} = linkService.parseNavigationStateFromUrl(href);
        const note = await froca.getNote(noteId, true);
        const title = note ? note.title : '[missing]';
        $el.text(title);
    }
    async refreshWithNote(note) {
        await this.renderOwnedAttributes(note.getOwnedAttributes(), true);
    }
    async renderOwnedAttributes(ownedAttributes, saved) {
        // attrs are not resorted if position changes after the initial load
        ownedAttributes.sort((a, b) => a.position - b.position);
        let htmlAttrs = (await attributeRenderer.renderAttributes(ownedAttributes, true)).html();
        if (htmlAttrs.length > 0) {
            htmlAttrs += " ";
        }
        this.textEditor.setData(htmlAttrs);
        if (saved) {
            this.lastSavedContent = this.textEditor.getData();
            this.$saveAttributesButton.fadeOut(0);
        }
    }
    async createNoteForReferenceLink(title) {
        const {note} = await noteCreateService.createNoteWithTypePrompt(this.notePath, {
            activate: false,
            title: title
        });
        return note.getBestNotePathString();
    }
    async updateAttributeList(attributes) {
        await this.renderOwnedAttributes(attributes, false);
    }
    focus() {
        this.$editor.trigger('focus');
        this.textEditor.model.change( writer => {
            const positionAt = writer.createPositionAt(this.textEditor.model.document.getRoot(), 'end');
            writer.setSelection(positionAt);
        } );
    }
    entitiesReloadedEvent({loadResults}) {
        if (loadResults.getAttributeRows(this.componentId).find(attr => attributeService.isAffecting(attr, this.note))) {
            this.refresh();
        }
    }
}