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 { UMB_BLOCK_RTE_PROPERTY_EDITOR_SCHEMA_ALIAS } from '../constants.js';
import { jsonStringComparison, observeMultiple } from '../../../libs/observable-api/index.js';
import { property, state } from '../../../external/lit/index.js';
import { UmbBlockRteEntriesContext, UmbBlockRteManagerContext } from '../../block/block-rte/index.js';
import { UmbChangeEvent } from '../../core/event/index.js';
import { UmbFormControlMixin, UmbValidationContext, UMB_VALIDATION_EMPTY_LOCALIZATION_KEY, } from '../../core/validation/index.js';
import { UmbLitElement } from '../../core/lit-element/index.js';
import { UMB_VARIANT_CONTEXT, UmbVariantId } from '../../core/variant/index.js';
import { UMB_CONTENT_WORKSPACE_CONTEXT } from '../../content/content/index.js';
import { UMB_PROPERTY_CONTEXT } from '../../core/property/index.js';
/**
 * The abstract base class that is used as a base for the rich-text-editor component.
 * @cssprop --umb-rte-width - The width of the rich-text-editor (default: unset)
 * @cssprop --umb-rte-min-width - The minimum width of the rich-text-editor (default: unset)
 * @cssprop --umb-rte-max-width - The maximum width of the rich-text-editor (default: 100%)
 * @cssprop --umb-rte-height - The height of the rich-text-editor (default: 100%)
 * @cssprop --umb-rte-min-height - The minimum height of the rich-text-editor (default: 100%)
 * @cssprop --umb-rte-max-height - The maximum height of the rich-text-editor (default: 100%)
 */
export class UmbPropertyEditorUiRteElementBase extends UmbFormControlMixin(UmbLitElement) {
    set config(config) {
        if (!config)
            return;
        this._config = config;
        const blocks = config.getValueByAlias('blocks') ?? [];
        this.#managerContext.setBlockTypes(blocks);
        this.#managerContext.setEditorConfiguration(config);
        const dimensions = config.getValueByAlias('dimensions');
        this._css = {
            '--umb-rte-max-width': dimensions?.width ? `${dimensions.width}px` : '100%',
            '--umb-rte-height': dimensions?.height ? `${dimensions.height}px` : 'unset',
        };
    }
    set value(value) {
        if (!value) {
            super.value = undefined;
            this._markup = '';
            this.#managerContext.setLayouts([]);
            this.#managerContext.setContents([]);
            this.#managerContext.setSettings([]);
            this.#managerContext.setExposes([]);
            return;
        }
        const buildUpValue = value ? { ...value } : {};
        buildUpValue.markup ??= '';
        if (buildUpValue.blocks) {
            buildUpValue.blocks = { ...buildUpValue.blocks };
        }
        else {
            buildUpValue.blocks ??= { layout: {}, contentData: [], settingsData: [], expose: [] };
        }
        buildUpValue.blocks.layout ??= {};
        buildUpValue.blocks.contentData ??= [];
        buildUpValue.blocks.settingsData ??= [];
        buildUpValue.blocks.expose ??= [];
        super.value = buildUpValue;
        // Only update the actual editor markup if it is not the same as the value.
        if (this._markup !== super.value.markup) {
            this._markup = super.value.markup;
        }
        this.#managerContext.setLayouts(buildUpValue.blocks.layout[UMB_BLOCK_RTE_PROPERTY_EDITOR_SCHEMA_ALIAS] ?? []);
        this.#managerContext.setContents(buildUpValue.blocks.contentData);
        this.#managerContext.setSettings(buildUpValue.blocks.settingsData);
        this.#managerContext.setExposes(buildUpValue.blocks.expose);
    }
    get value() {
        return super.value;
    }
    /**
     * @deprecated _value is depreacated, use `super.value` instead.
     * @returns {UmbPropertyEditorRteValueType | undefined} The value of the property editor.
     */
    get _value() {
        return super.value;
    }
    set _value(value) {
        super.value = value;
    }
    #managerContext;
    #entriesContext;
    #validationContext;
    #unusedLayoutLookup;
    #unusedContentLookup;
    #unusedSettingsLookup;
    constructor() {
        super();
        /**
         * Sets the input to readonly mode, meaning value cannot be changed but still able to read and select its content.
         * @default false
         */
        this.readonly = false;
        this._css = {};
        /**
         * Separate state for markup, to avoid re-rendering/re-setting the value of the Tiptap editor when the value does not really change.
         */
        this._markup = '';
        this.#managerContext = new UmbBlockRteManagerContext(this);
        this.#entriesContext = new UmbBlockRteEntriesContext(this);
        this.#validationContext = new UmbValidationContext(this);
        this.#unusedLayoutLookup = new Map();
        this.#unusedContentLookup = new Map();
        this.#unusedSettingsLookup = new Map();
        this.consumeContext(UMB_CONTENT_WORKSPACE_CONTEXT, (context) => {
            if (context) {
                this.observe(observeMultiple([
                    this.#managerContext.blockTypes,
                    context.structure.variesByCulture,
                    context.structure.variesBySegment,
                ]), async ([blockTypes, variesByCulture, variesBySegment]) => {
                    if (blockTypes.length > 0 && (variesByCulture === false || variesBySegment === false)) {
                        // check if any of the Blocks varyByCulture or Segment and then display a warning.
                        const promises = await Promise.all(blockTypes.map(async (blockType) => {
                            const elementType = blockType.contentElementTypeKey;
                            await this.#managerContext.contentTypesLoaded;
                            const structure = await this.#managerContext.getStructure(elementType);
                            if (variesByCulture === false && structure?.getVariesByCulture() === true) {
                                // If block varies by culture but document does not.
                                return true;
                            }
                            else if (variesBySegment === false && structure?.getVariesBySegment() === true) {
                                // If block varies by segment but document does not.
                                return true;
                            }
                            return false;
                        }));
                        const notSupportedVariantSetting = promises.filter((x) => x === true).length > 0;
                        if (notSupportedVariantSetting) {
                            this.setCustomValidity('#blockEditor_blockVariantConfigurationNotSupported');
                            this.checkValidity();
                        }
                    }
                }, 'blockTypeConfigurationCheck');
            }
            else {
                this.removeUmbControllerByAlias('blockTypeConfigurationCheck');
            }
        }).passContextAliasMatches();
        this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => {
            this.#gotPropertyContext(context);
        });
        this.consumeContext(UMB_VARIANT_CONTEXT, async (context) => {
            this.observe(context?.displayVariantId, (variantId) => {
                this.#managerContext.setVariantId(variantId);
            }, 'observeContextualVariantId');
        });
        this.observe(this.#entriesContext.layoutEntries, (layouts) => {
            // Update manager:
            this.#managerContext.setLayouts(layouts);
        }, null);
        this.addValidator('valueMissing', () => this.mandatoryMessage ?? UMB_VALIDATION_EMPTY_LOCALIZATION_KEY, () => !!this.mandatory && this.value === undefined);
    }
    #gotPropertyContext(context) {
        this.observe(context?.dataPath, (dataPath) => {
            if (dataPath) {
                // Set the data path for the local validation context:
                this.#validationContext.setDataPath(dataPath + '.blocks');
                this.#validationContext.autoReport();
            }
        }, 'observeDataPath');
        this.observe(context?.alias, (alias) => {
            this.#managerContext.setPropertyAlias(alias);
        }, 'observePropertyAlias');
        this.observe(observeMultiple([
            this.#managerContext.layouts,
            this.#managerContext.contents,
            this.#managerContext.settings,
            this.#managerContext.exposes,
        ]), ([layouts, contents, settings, exposes]) => {
            if (layouts.length === 0) {
                if (super.value?.markup === undefined) {
                    if (this.value === undefined) {
                        return;
                    }
                    super.value = undefined;
                }
                else {
                    const newValue = {
                        ...super.value,
                        blocks: {
                            layout: {},
                            contentData: [],
                            settingsData: [],
                            expose: [],
                        },
                    };
                    if (jsonStringComparison(this.value, newValue)) {
                        return;
                    }
                    super.value = newValue;
                }
            }
            else {
                const newValue = {
                    markup: this._markup,
                    blocks: {
                        layout: { [UMB_BLOCK_RTE_PROPERTY_EDITOR_SCHEMA_ALIAS]: layouts },
                        contentData: contents,
                        settingsData: settings,
                        expose: exposes,
                    },
                };
                if (jsonStringComparison(this.value, newValue)) {
                    return;
                }
                super.value = newValue;
            }
            // If we don't have a value set from the outside or an internal value, we don't want to set the value.
            // This is added to prevent the block list from setting an empty value on startup.
            if (super.value?.markup === undefined) {
                return;
            }
            context?.setValue(super.value);
        }, 'blockManagerObserver');
    }
    #setUnusedBlockLookups(unusedLayouts) {
        if (unusedLayouts.length) {
            unusedLayouts.forEach((layout) => {
                if (layout.contentKey) {
                    this.#unusedLayoutLookup.set(layout.contentKey, layout);
                    const contentBlock = this.#managerContext.getContentOf(layout.contentKey);
                    if (contentBlock) {
                        this.#unusedContentLookup.set(layout.contentKey, contentBlock);
                    }
                    else {
                        console.warn(`Expected content block for '${layout.contentKey}' was not found. This may indicate a data consistency issue.`);
                    }
                    if (layout.settingsKey) {
                        const settingsBlock = this.#managerContext.getSettingsOf(layout.settingsKey);
                        if (settingsBlock) {
                            this.#unusedSettingsLookup.set(layout.settingsKey, settingsBlock);
                        }
                        else {
                            console.warn(`Expected settings block for '${layout.settingsKey}' was not found. This may indicate a data consistency issue.`);
                        }
                    }
                }
            });
        }
    }
    #restoreUnusedBlocks(usedContentKeys) {
        if (usedContentKeys.length) {
            usedContentKeys.forEach((contentKey) => {
                if (contentKey && this.#unusedLayoutLookup.has(contentKey)) {
                    const layout = this.#unusedLayoutLookup.get(contentKey);
                    if (layout) {
                        this.#managerContext.setOneLayout(layout);
                        this.#unusedLayoutLookup.delete(contentKey);
                        const contentBlock = this.#unusedContentLookup.get(contentKey);
                        if (contentBlock) {
                            this.#managerContext.setOneContent(contentBlock);
                            this.#managerContext.setOneExpose(contentKey, UmbVariantId.CreateInvariant());
                            this.#unusedContentLookup.delete(contentKey);
                        }
                        if (layout.settingsKey && this.#unusedSettingsLookup.has(layout.settingsKey)) {
                            const settingsBlock = this.#unusedSettingsLookup.get(layout.settingsKey);
                            if (settingsBlock) {
                                this.#managerContext.setOneSettings(settingsBlock);
                                this.#unusedSettingsLookup.delete(layout.settingsKey);
                            }
                        }
                    }
                }
            });
        }
    }
    _filterUnusedBlocks(usedContentKeys) {
        const unusedLayouts = this.#managerContext.getLayouts().filter((x) => usedContentKeys.indexOf(x.contentKey) === -1);
        // Temporarily set the unused layouts to the lookup, as they could be restored later, e.g. via an RTE undo action. [LK]
        this.#restoreUnusedBlocks(usedContentKeys);
        this.#setUnusedBlockLookups(unusedLayouts);
        const unusedContentKeys = unusedLayouts.map((x) => x.contentKey);
        const unusedSettingsKeys = unusedLayouts
            .map((x) => x.settingsKey)
            .filter((x) => typeof x === 'string');
        this.#managerContext.removeManyContent(unusedContentKeys);
        this.#managerContext.removeManySettings(unusedSettingsKeys);
        this.#managerContext.removeManyLayouts(unusedContentKeys);
    }
    _fireChangeEvent() {
        this.dispatchEvent(new UmbChangeEvent());
    }
    destroy() {
        super.destroy();
        this.#unusedLayoutLookup.clear();
        this.#unusedContentLookup.clear();
        this.#unusedSettingsLookup.clear();
    }
}
__decorate([
    property({
        attribute: false,
        type: Object,
        hasChanged(value, oldValue) {
            return value?.markup !== oldValue?.markup;
        },
    })
], UmbPropertyEditorUiRteElementBase.prototype, "value", null);
__decorate([
    property({ type: Boolean, reflect: true })
], UmbPropertyEditorUiRteElementBase.prototype, "readonly", void 0);
__decorate([
    property({ type: Boolean })
], UmbPropertyEditorUiRteElementBase.prototype, "mandatory", void 0);
__decorate([
    property({ type: String })
], UmbPropertyEditorUiRteElementBase.prototype, "mandatoryMessage", void 0);
__decorate([
    state()
], UmbPropertyEditorUiRteElementBase.prototype, "_config", void 0);
__decorate([
    state()
], UmbPropertyEditorUiRteElementBase.prototype, "_css", void 0);
__decorate([
    state()
], UmbPropertyEditorUiRteElementBase.prototype, "_value", null);
__decorate([
    state()
], UmbPropertyEditorUiRteElementBase.prototype, "_markup", void 0);
