var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { Editor } from '../../externals.js';
import { UmbTiptapRteContext } from '../../contexts/tiptap-rte.context.js';
import { css, customElement, html, property, repeat, state, unsafeCSS, when, } from '../../../../external/lit/index.js';
import { loadManifestApi } from '../../../../libs/extension-api/index.js';
import { umbExtensionsRegistry } from '../../../core/extension-registry/index.js';
import { UmbChangeEvent } from '../../../core/event/index.js';
import { umbDestroyOnDisconnect, UmbLitElement } from '../../../core/lit-element/index.js';
import { UmbFormControlMixin } from '../../../core/validation/index.js';
import '../toolbar/tiptap-toolbar.element.js';
import '../statusbar/tiptap-statusbar.element.js';
const TIPTAP_CORE_EXTENSION_ALIAS = 'Umb.Tiptap.RichTextEssentials';
/**
 * The default root path for the stylesheets on the server.
 * This is used as a fallback if the server configuration is not available.
 */
const DEFAULT_STYLESHEET_ROOT_PATH = '/css';
let UmbInputTiptapElement = class UmbInputTiptapElement extends UmbFormControlMixin(UmbLitElement) {
    #context;
    #hasToolbar;
    #hasStatusbar;
    #stylesheets;
    #stylesheetRootPath;
    set value(value) {
        if (value === this.#value)
            return;
        this.#value = value;
        // Try to set the value to the editor if it is ready.
        if (this._editor) {
            this._editor.commands.setContent(value);
        }
    }
    get value() {
        return this.#value;
    }
    #value;
    constructor() {
        super();
        this.#context = new UmbTiptapRteContext(this);
        this.#hasToolbar = false;
        this.#hasStatusbar = false;
        this.#stylesheets = new Set(['/umbraco/backoffice/css/rte-content.css']);
        this.#stylesheetRootPath = DEFAULT_STYLESHEET_ROOT_PATH;
        this.#value = '';
        /**
         * Sets the input to readonly mode, meaning value cannot be changed but still able to read and select its content.
         */
        this.readonly = false;
        this._extensions = [];
        this._toolbar = [[[]]];
        this._statusbar = [[], []];
        this.addValidator('valueMissing', () => this.requiredMessage ?? 'Value is required', () => !!this.required && this.isEmpty());
    }
    async firstUpdated() {
        await this.#loadStylesheetPath();
        await this.#loadExtensions();
        await this.#loadEditor();
    }
    /**
     * Checks if the editor is empty.
     * @returns {boolean} returns true if the editor contains no markup
     */
    isEmpty() {
        return this._editor?.isEmpty ?? false;
    }
    async #loadStylesheetPath() {
        return this.observe(this.#context.stylesheetRootPath, (stylesheetRootPath) => {
            if (stylesheetRootPath) {
                this.#stylesheetRootPath = stylesheetRootPath;
            }
        }).asPromise();
    }
    async #loadExtensions() {
        const enabledExtensions = this.configuration?.getValueByAlias('extensions') ?? [];
        // Ensures that the "Rich Text Essentials" extension is always enabled. [LK]
        if (!enabledExtensions.includes(TIPTAP_CORE_EXTENSION_ALIAS)) {
            const { default: api } = await import('../../extensions/core/rich-text-essentials.tiptap-api.js');
            this._extensions.push(new api(this));
        }
        await new Promise((resolve) => {
            this.observe(umbExtensionsRegistry.byTypeAndAliases('tiptapExtension', enabledExtensions), async (manifests) => {
                for (const manifest of manifests) {
                    if (manifest.api) {
                        const extension = await loadManifestApi(manifest.api);
                        if (extension) {
                            const ext = new extension(this);
                            ext.manifest = manifest;
                            this._extensions.push(ext);
                        }
                    }
                }
                resolve();
            });
        });
    }
    async #loadEditor() {
        const element = this.shadowRoot?.querySelector('#editor');
        if (!element)
            return;
        const stylesheets = this.configuration?.getValueByAlias('stylesheets');
        if (stylesheets?.length) {
            stylesheets.forEach((stylesheet) => {
                const linkHref = stylesheet.startsWith('http') || stylesheet.startsWith(this.#stylesheetRootPath)
                    ? stylesheet
                    : `${this.#stylesheetRootPath}${stylesheet}`;
                this.#stylesheets.add(linkHref);
            });
        }
        const tiptapExtensions = new Map();
        const collectedStyles = [];
        this._extensions.forEach((ext) => {
            const tiptapExt = ext.getTiptapExtensions({ configuration: this.configuration });
            if (tiptapExt?.length) {
                tiptapExt.forEach((extension) => {
                    if (!tiptapExtensions.has(extension.name)) {
                        tiptapExtensions.set(extension.name, extension);
                    }
                });
            }
            const styles = ext.getStyles();
            if (styles) {
                collectedStyles.push(styles);
            }
        });
        if (collectedStyles.length) {
            this._extensionStyles = unsafeCSS(collectedStyles.map((s) => s.toString()).join(''));
        }
        this._toolbar = this.configuration?.getValueByAlias('toolbar') ?? [[[]]];
        this._statusbar = this.configuration?.getValueByAlias('statusbar') ?? [];
        this.#hasToolbar = this._toolbar.flat(2).length > 0;
        this.#hasStatusbar = this._statusbar.flat().length > 0;
        this._editor = new Editor({
            element: element,
            editable: !this.readonly,
            editorProps: {
                attributes: {
                    'aria-label': this.label || this.localize.term('rte_label'),
                    'aria-required': this.required ? 'true' : 'false',
                },
            },
            extensions: Array.from(tiptapExtensions.values()),
            content: this.#value,
            injectCSS: false, // Prevents injecting CSS into `window.document`, as it never applies to the shadow DOM. [LK]
            //enableContentCheck: true,
            onBeforeCreate: ({ editor }) => {
                this._extensions.forEach((ext) => ext.setEditor(editor));
            },
            onContentError: ({ error }) => {
                console.error('contentError', [error.message, error.cause]);
            },
            onUpdate: ({ editor }) => {
                this.#value = editor.getHTML();
                this._runValidators();
                this.dispatchEvent(new UmbChangeEvent());
            },
        });
        this.#context.setEditor(this._editor);
    }
    render() {
        const loading = !this._editor && !this._extensions?.length;
        return html `
			${when(loading, () => html `<div id="loader"><uui-loader></uui-loader></div>`)}
			${when(!loading, () => html `${this.#renderStyles()}${this.#renderToolbar()}`)}
			<div id="editor" data-mark="input:tiptap-rte" ?data-loaded=${!loading}></div>
			${when(!loading, () => this.#renderStatusbar())}
		`;
    }
    #renderStyles() {
        if (!this._extensionStyles)
            return;
        return html `
			${repeat(this.#stylesheets, (stylesheet) => stylesheet, (stylesheet) => html `<link rel="stylesheet" href=${stylesheet} />`)}
			<style>
				${this._extensionStyles}
			</style>
		`;
    }
    #renderToolbar() {
        if (!this.#hasToolbar)
            return;
        return html `
			<umb-tiptap-toolbar
				data-mark="tiptap-toolbar"
				.toolbar=${this._toolbar}
				.editor=${this._editor}
				.configuration=${this.configuration}
				?readonly=${this.readonly}>
			</umb-tiptap-toolbar>
		`;
    }
    #renderStatusbar() {
        if (!this.#hasStatusbar)
            return;
        return html `
			<umb-tiptap-statusbar
				data-mark="tiptap-statusbar"
				.statusbar=${this._statusbar}
				.editor=${this._editor}
				.configuration=${this.configuration}
				?readonly=${this.readonly}
				${umbDestroyOnDisconnect()}>
			</umb-tiptap-statusbar>
		`;
    }
    destroy() {
        this._editor?.destroy();
        this._editor = undefined;
    }
    static { this.styles = [
        css `
			:host {
				display: block;
				position: relative;
				z-index: 0;

				width: var(--umb-rte-width, unset);
				min-width: var(--umb-rte-min-width, unset);
				max-width: var(--umb-rte-max-width, 100%);
			}

			:host(:hover) {
				--umb-tiptap-edge-border-color: var(--uui-color-border-standalone);
			}

			:host(:focus),
			:host(:focus-within) {
				--umb-tiptap-edge-border-color: var(--uui-color-border-emphasis);
			}

			:host([readonly]) {
				pointer-events: none;

				#editor {
					background-color: var(--uui-color-surface-alt);
				}
			}

			#loader {
				display: flex;
				align-items: center;
				justify-content: center;
			}

			:host(:invalid:not([pristine])),
			/* polyfill support */
			:host(:not([pristine])[internals-invalid]) {
				--umb-tiptap-edge-border-color: var(--uui-color-invalid);
				#editor {
					border-color: var(--uui-color-invalid);
				}
			}

			#editor {
				display: flex;
				overflow: auto;
				border-radius: var(--uui-border-radius);
				border: 1px solid transparent;
				padding: 1rem;
				box-sizing: border-box;

				height: var(--umb-rte-height, 100%);
				min-height: var(--umb-rte-min-height, 100%);
				max-height: var(--umb-rte-max-height, 100%);

				width: 100%;
				max-width: 100%;

				&[data-loaded] {
					border-color: var(--umb-tiptap-edge-border-color, var(--uui-color-border));
				}

				> .tiptap {
					height: 100%;
					width: 100%;
					outline: none;
					white-space: wrap;
					min-width: 0;

					p:first-of-type {
						margin-top: 0;
					}

					.is-editor-empty:first-child::before {
						color: var(--uui-color-text);
						opacity: 0.55;
						content: attr(data-placeholder);
						float: left;
						height: 0;
						pointer-events: none;
					}
				}

				&:has(+ umb-tiptap-statusbar) {
					border-bottom-left-radius: 0;
					border-bottom-right-radius: 0;
				}
			}

			#editor,
			umb-tiptap-toolbar,
			umb-tiptap-statusbar {
				transition: border-color 120ms ease-out;
			}

			umb-tiptap-toolbar + #editor {
				border-top: 0;
				border-top-left-radius: 0;
				border-top-right-radius: 0;
			}
		`,
    ]; }
};
__decorate([
    property({ type: String })
], UmbInputTiptapElement.prototype, "value", null);
__decorate([
    property({ attribute: false })
], UmbInputTiptapElement.prototype, "configuration", void 0);
__decorate([
    property()
], UmbInputTiptapElement.prototype, "label", void 0);
__decorate([
    property({ type: Boolean })
], UmbInputTiptapElement.prototype, "required", void 0);
__decorate([
    property({ type: String })
], UmbInputTiptapElement.prototype, "requiredMessage", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], UmbInputTiptapElement.prototype, "readonly", void 0);
__decorate([
    state()
], UmbInputTiptapElement.prototype, "_editor", void 0);
__decorate([
    state()
], UmbInputTiptapElement.prototype, "_extensions", void 0);
__decorate([
    state()
], UmbInputTiptapElement.prototype, "_extensionStyles", void 0);
__decorate([
    state()
], UmbInputTiptapElement.prototype, "_toolbar", void 0);
__decorate([
    state()
], UmbInputTiptapElement.prototype, "_statusbar", void 0);
UmbInputTiptapElement = __decorate([
    customElement('umb-input-tiptap')
], UmbInputTiptapElement);
export { UmbInputTiptapElement };
