import { DOMPurify } from '../../../external/dompurify/index.js';
import { Marked } from '../../../external/marked/index.js';
import { UmbArrayState } from '../../../libs/observable-api/index.js';
import { UmbContextBase } from '../../../libs/class-api/index.js';
import { UmbContextToken } from '../../../libs/context-api/index.js';
import { UmbExtensionsApiInitializer } from '../../../libs/extension-api/index.js';
import { umbExtensionsRegistry } from '../../core/extension-registry/index.js';
const UmbDomPurify = DOMPurify(window);
const UmbDomPurifyConfig = {
    USE_PROFILES: { html: true },
    CUSTOM_ELEMENT_HANDLING: {
        tagNameCheck: /^(?:ufm|umb|uui)-.*$/,
        attributeNameCheck: /^(?!on)/,
        allowCustomizedBuiltInElements: false,
    },
};
UmbDomPurify.addHook('afterSanitizeAttributes', function (node) {
    // set all elements owning target to target=_blank
    if ('target' in node && node instanceof HTMLElement) {
        node.setAttribute('target', '_blank');
    }
});
export const UmbMarked = new Marked({
    async: true,
    gfm: true,
    breaks: true,
    hooks: {
        postprocess: (markup) => UmbDomPurify.sanitize(markup, UmbDomPurifyConfig),
    },
});
export class UmbUfmContext extends UmbContextBase {
    #filters;
    constructor(host) {
        super(host, UMB_UFM_CONTEXT);
        this.#filters = new UmbArrayState([], (x) => x.alias);
        this.filters = this.#filters.asObservable();
        new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'markedExtension', [UmbMarked]);
        new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'ufmFilter', [], undefined, (controllers) => {
            const filters = controllers
                .map((controller) => {
                const ctrl = controller;
                if (!ctrl.manifest || !ctrl.api)
                    return null;
                return { alias: ctrl.manifest.meta.alias, filter: ctrl.api.filter };
            })
                .filter((x) => x);
            this.#filters.setValue(filters);
        });
    }
    /**
     * Get the filters registered in the UFM context.
     * @returns {Array<UmbUfmFilterType>} An array of filters with their aliases and filter functions.
     */
    getFilters() {
        return this.#filters.getValue();
    }
    /**
     * Get a filter by its alias.
     * @param alias The alias of the filter to retrieve.
     * @returns {UmbUfmFilterFunction} The filter function associated with the alias, or undefined if not found.
     */
    getFilterByAlias(alias) {
        return this.#filters.getValue().find((x) => x.alias === alias)?.filter;
    }
    /**
     * Parse markdown content, optionally inline.
     * @param markdown The markdown string to parse.
     * @param inline If true, parse inline markdown; otherwise, parse block markdown.
     * @returns {Promise<string>} A promise that resolves to the parsed HTML string.
     */
    async parse(markdown, inline) {
        return !inline ? await UmbMarked.parse(markdown) : await UmbMarked.parseInline(markdown);
    }
}
export const UMB_UFM_CONTEXT = new UmbContextToken('UmbUfmContext');
export { UmbUfmContext as api };
