import {
    ClassicEditor,
    Essentials,
    Paragraph,
    Bold,
    Italic,
    Font,
    Heading,
    List,
    Link,
    Editor,
    AccessibilityHelp,
    Alignment,
    AutoImage,
    Base64UploadAdapter,
    BlockQuote,
    Code,
    CodeBlock,
    FontFamily,
    FontSize,
    FontColor,
    FontBackgroundColor,
    Highlight,
    HorizontalLine,
    HtmlEmbed,
    ImageBlock,
    ImageCaption,
    ImageInline,
    ImageInsert,
    ImageInsertViaUrl,
    ImageResize,
    ImageStyle,
    ImageTextAlternative,
    ImageToolbar,
    ImageUpload,
    Indent,
    IndentBlock,
    LinkImage,
    ListProperties,
    Mention,
    PasteFromOffice,
    RemoveFormat,
    SelectAll,
    ShowBlocks,
    SourceEditing,
    SpecialCharacters,
    TodoList,
    SpecialCharactersArrows,
    SpecialCharactersCurrency,
    SpecialCharactersEssentials,
    SpecialCharactersLatin,
    SpecialCharactersMathematical,
    SpecialCharactersText,
    Strikethrough,
    Subscript,
    Superscript,
    Table,
    TableCaption,
    TableCellProperties,
    TableColumnResize,
    TableProperties,
    TableToolbar,
    Underline,
    Undo,
} from './../../ckeditor/5-43.3.1/ckeditor5.js';
import translations from './../../ckeditor/5-43.3.1/translations/pt-br.js';
import FullScreen from './GOVBREditorFullScreen.mjs';
import Resizable from './GOVBREditorResizable.mjs';
import Fuse from '../../fusejs/7.0.0/fuse.min.mjs';
import { CastersMencoes } from './GOVBREditorCastersMencoes.mjs';

const CORES_EDITOR = [
    {
        color: '#000000',
        label: 'Black',
    },
    {
        color: '#4d4d4d',
        label: 'Dim grey',
    },
    {
        color: '#999999',
        label: 'Grey',
    },
    {
        color: '#e6e6e6',
        label: 'Light grey',
    },
    {
        color: '#ffffff',
        label: 'White',
    },
    {
        color: '#e64c4c',
        label: 'Red',
    },
    {
        color: '#e6994c',
        label: 'Orange',
    },
    {
        color: '#e6e64c',
        label: 'Yellow',
    },
    {
        color: '#99e64c',
        label: 'Light green',
    },
    {
        color: '#4ce64c',
        label: 'Green',
    },
    {
        color: '#4ce699',
        label: 'Aquamarine',
    },
    {
        color: '#4ce6e6',
        label: 'Turquoise',
    },
    {
        color: '#4c99e6',
        label: 'Light blue',
    },
    {
        color: '#4c4ce6',
        label: 'Blue',
    },
    {
        color: '#994ce6',
        label: 'Purple',
    },
];

/**
 * Classe para o UC de editor de textos HTML
 */
class GOVBREditorHTMLUC {
    /**
     * @type {import('./GOVBREditorHTMLUserControl.mjs').GOVBREditorHTMLUserControl}
     */
    userControl;
    /**
     * @type {HTMLElement}
     */
    host;
    /**
     * @type {HTMLTextAreaElement}
     */
    textarea;
    /**
     * @type {Editor}
     */
    editor;

    /**
     * @param {any} userControl
     * @param {HTMLElement} host
     */
    constructor(userControl, host) {
        this.userControl = userControl;
        this.host = host;
        this.host.style.setProperty('--largura-componente', this.userControl.LARGURA_COMPONENTE);
        if (!this.userControl.LARGURA_COMPONENTE?.includes('%')) {
            let largura = this.userControl.LARGURA_COMPONENTE;
            if (largura.startsWith('calc')) {
                largura = largura.substring(4);
            }
            this.host.style.setProperty('--ck-toolbar-dropdown-max-width', 'calc(' + largura + ' - 8px)');
        }
        this.host.style.setProperty('--altura-componente', this.userControl.ALTURA_COMPONENTE);
        this.host.addEventListener('keydown', (event) => {
            // Necessário parar a propagação das teclas para o GeneXus ou este irá "engolir" elas, evitando que estas funcionem corretamente.
            event.stopPropagation();
        });
        /**
         * @type {HTMLElement}
         */
        let elHint;
        if (this.userControl.HINT_RODAPE) {
            elHint = document.createElement('sub');
            elHint.classList.add('govbr-editor-html-hint-rodape');
            elHint.innerText = this.userControl.HINT_RODAPE;
            this.host.append(elHint);
        }
        this.textarea = host.querySelector('.govbr-editor-textarea');

        (async () => {
            this.textarea.style.display = 'none';
            await GOVBRPlataformaJS.importarStyleSheet(this.userControl.URL_CDN, 'ckeditor', '5-43.3.1', 'ckeditor5', this.host);
            await GOVBRPlataformaJS.importarStyleSheet(this.userControl.URL_CDN, 'editor-html', this.userControl.VERSAO_JS_COMPONENTE, 'GOVBREditorHTMLUC', this.host);
            const configuracoes = await this.getConfiguracoes();
            this.textarea.style.display = '';
            ClassicEditor.create(this.textarea, configuracoes)
                .then((editor) => {
                    this.editor = editor;
                    const menubarElement = this.editor.ui.view.menuBarView?.element;
                    const toolbarElement = this.editor.ui.view.toolbar?.element;
                    this.editor.on(
                        'change:isReadOnly',
                        /**
                         * @param {never} _
                         * @param {never} __
                         * @param {boolean} isReadOnly
                         */
                        (_, __, isReadOnly) => {
                            if (menubarElement) {
                                menubarElement.style.display = isReadOnly ? 'none' : '';
                            }
                            if (toolbarElement) {
                                toolbarElement.style.display = isReadOnly ? 'none' : '';
                            }
                        }
                    );
                    GOVBR.logs.debug('GOVBR-Editor - Carregado');
                    GOVBR.logs.debug(this);
                    this.setReadOnly(!this.userControl.Enabled);
                    elHint && this.host.append(elHint);
                    editor.model.document.on('change:data', () => {
                        this.textarea.value = this.editor.getData();
                        this.textarea.dispatchEvent(new Event('change'));
                    });
                })
                .catch((error) => {
                    GOVBR.logs.error(error);
                });
        })();
    }

    /**
     * Define o editor como somente leitura
     * @param {boolean} readOnly
     * @param {string} lock
     */
    setReadOnly(readOnly, lock = 'base') {
        if (readOnly) {
            this.editor.enableReadOnlyMode(lock);
        } else {
            this.editor.disableReadOnlyMode(lock);
        }
    }

    /**
     * Retorna as configurações do CKEditor.
     * @returns {Promise<Record<string, any>>}
     */
    async getConfiguracoes() {
        /**
         * @type {Record<string, any>}
         */
        const retorno = {
            plugins: this.getPlugins(),
            toolbar: {
                items: this.getToolbar(),
            },
            menuBar: {
                isVisible: this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.BARRA_MENUS,
            },
            language: 'pt-br',
            translations,
            placeholder: this.userControl.PLACEHOLDER,
        };
        if (this.userControl.QUEBRAR_LINHA_TOOLBAR) {
            retorno.toolbar.shouldNotGroupWhenFull = true;
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_MUDAR_TAMANHO_ESTILO_FONTE) {
            retorno.fontFamily = {
                supportAllValues: true,
            };
            retorno.fontSize = {
                options: [10, 12, 'default', 16, 18, 20, 22],
                supportAllValues: true,
            };
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_MUDAR_COR_FONTE_FUNDO) {
            retorno.fontColor = {
                colors: CORES_EDITOR,
                colorPicker: {
                    format: 'hex',
                },
            };
            retorno.fontBackgroundColor = {
                colors: CORES_EDITOR,
                colorPicker: {
                    format: 'hex',
                },
            };
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_IMAGENS) {
            retorno.image = {
                toolbar: [
                    'toggleImageCaption',
                    'imageTextAlternative',
                    '|',
                    'imageStyle:inline',
                    'imageStyle:wrapText',
                    'imageStyle:breakText',
                    '|',
                    'resizeImage',
                ],
            };
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_LINKS) {
            retorno.link = {
                addTargetToExternalLinks: true,
                defaultProtocol: 'https://',
            };
        }
        if (this.userControl.PODE_MENCOES) {
            try {
                retorno.mention = {
                    feeds: await this.getFeedsMencoes(),
                };
            } catch (ex) {
                // Caso ocorra erro ao carregar as menções, atrasa para o próximo loop, isto evita que o editor não carregue devido ao erro porém a excessão ainda é disparada.
                setTimeout(() => {
                    throw ex;
                }, 0);
            }
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_TABELAS) {
            retorno.table = {
                contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties', 'tableCellProperties'],
            };
        }
        return retorno;
    }

    /**
     * Retorna os plugins disponibilizados.
     * @returns {any[]}
     */
    getPlugins() {
        /**
         * @type {any[]}
         */
        const plugins = [
            AccessibilityHelp,
            Essentials,
            Paragraph,
            PasteFromOffice,
            SelectAll,
        ];

        if (this.userControl.PODE_REDIMENSIONAR) {
            plugins.push(Resizable);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_ALTERAR_ALINHAMENTO) {
            plugins.push(Alignment);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_IMAGENS) {
            plugins.push(AutoImage);
            plugins.push(Base64UploadAdapter);
            plugins.push(ImageBlock);
            plugins.push(ImageCaption);
            plugins.push(ImageInline);
            plugins.push(ImageInsert);
            plugins.push(ImageInsertViaUrl);
            plugins.push(ImageResize);
            plugins.push(ImageStyle);
            plugins.push(ImageTextAlternative);
            plugins.push(ImageToolbar);
            plugins.push(ImageUpload);
            plugins.push(LinkImage);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_CITACAO_BLOCO) {
            plugins.push(BlockQuote);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_NEGRITO) {
            plugins.push(Bold);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_CODIGO_FONTE) {
            plugins.push(Code);
            plugins.push(ShowBlocks);
            plugins.push(SourceEditing);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_BLOCO_CODIGO_FONTE) {
            plugins.push(CodeBlock);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_MUDAR_COR_FONTE_FUNDO) {
            plugins.push(Font);
            plugins.push(FontBackgroundColor);
            plugins.push(FontColor);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_MUDAR_TAMANHO_ESTILO_FONTE) {
            plugins.push(FontFamily);
            plugins.push(FontSize);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_DEFINIR_CABECALHOS) {
            plugins.push(Heading);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_DESTACAR) {
            plugins.push(Highlight);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_LINHA_HORIZONTAL) {
            plugins.push(HorizontalLine);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_EMBEDAR_CONTEUDO_EXTERNO) {
            plugins.push(HtmlEmbed);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_INDENTAR) {
            plugins.push(Indent);
            plugins.push(IndentBlock);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_ITALICO) {
            plugins.push(Italic);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_LINKS) {
            plugins.push(Link);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_LISTAS_CHECKBOX || this.userControl.PODE_LISTAS_NUMERO || this.userControl.PODE_LISTAS_TRACOS) {
            plugins.push(List);
            plugins.push(ListProperties);
            if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_LISTAS_CHECKBOX) {
                plugins.push(TodoList);
            }
        }
        if (this.userControl.PODE_MENCOES) {
            plugins.push(Mention);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_REMOVER_FORMATACAO) {
            plugins.push(RemoveFormat);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_CARACTERES_ESPECIAIS) {
            plugins.push(SpecialCharacters);
            plugins.push(SpecialCharactersEssentials);
            plugins.push(SpecialCharactersArrows);
            plugins.push(SpecialCharactersCurrency);
            plugins.push(SpecialCharactersLatin);
            plugins.push(SpecialCharactersMathematical);
            plugins.push(SpecialCharactersText);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_RISCAR_TEXTO) {
            plugins.push(Strikethrough);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_SUBSCRITO) {
            plugins.push(Subscript);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_SUPERSCRITO) {
            plugins.push(Superscript);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_TABELAS) {
            plugins.push(Table);
            plugins.push(TableCaption);
            plugins.push(TableCellProperties);
            plugins.push(TableColumnResize);
            plugins.push(TableProperties);
            plugins.push(TableToolbar);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_UNDERLINE) {
            plugins.push(Underline);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_DESFAZER_REFAZER) {
            plugins.push(Undo);
        }
        if (this.userControl.FORCE_EDITOR_COMPLETO || this.userControl.PODE_TELA_CHEIA) {
            plugins.push(FullScreen);
        }
        if (this.userControl.PODE_MENCOES) {
            plugins.push(CastersMencoes);
        }

        return plugins;
    }

    /**
     * Retorna os itens da toolbar do editor.
     * @returns {string[]}
     */
    getToolbar() {
        /**
         * @type {string[]}
         */
        const toolbar = [];
        let insereQuebra = false;

        /**
         * @param {boolean} validacao
         * @param {string[]} itens
         * @param {boolean} quebra
         */
        const insereItemToolbar = (validacao, itens, quebra) => {
            if (this.userControl.FORCE_EDITOR_COMPLETO || validacao) {
                if (insereQuebra) {
                    toolbar.push('|');
                    insereQuebra = false;
                }
                toolbar.push.apply(toolbar, itens);
            }
            if (quebra) {
                insereQuebra = true;
            }
        };
        insereItemToolbar(this.userControl.PODE_DESFAZER_REFAZER, ['undo', 'redo'], false);
        insereItemToolbar(true, ['selectAll'], true);
        insereItemToolbar(this.userControl.PODE_DEFINIR_CABECALHOS, ['heading'], true);
        insereItemToolbar(this.userControl.PODE_MUDAR_TAMANHO_ESTILO_FONTE, ['fontSize', 'fontFamily'], false);
        insereItemToolbar(this.userControl.PODE_MUDAR_COR_FONTE_FUNDO, ['fontColor', 'fontBackgroundColor'], true);
        insereItemToolbar(this.userControl.PODE_REMOVER_FORMATACAO, ['removeFormat'], false);
        insereItemToolbar(this.userControl.PODE_NEGRITO, ['bold'], false);
        insereItemToolbar(this.userControl.PODE_ITALICO, ['italic'], false);
        insereItemToolbar(this.userControl.PODE_UNDERLINE, ['underline'], false);
        insereItemToolbar(this.userControl.PODE_RISCAR_TEXTO, ['strikethrough'], false);
        insereItemToolbar(this.userControl.PODE_SUBSCRITO, ['subscript'], false);
        insereItemToolbar(this.userControl.PODE_SUPERSCRITO, ['superscript'], false);
        insereItemToolbar(this.userControl.PODE_CODIGO_FONTE, ['code'], true);
        insereItemToolbar(this.userControl.PODE_LINKS, ['link'], false);
        insereItemToolbar(this.userControl.PODE_CARACTERES_ESPECIAIS, ['specialCharacters'], false);
        insereItemToolbar(this.userControl.PODE_LINHA_HORIZONTAL, ['horizontalLine'], false);
        insereItemToolbar(this.userControl.PODE_CITACAO_BLOCO, ['blockQuote'], false);
        insereItemToolbar(this.userControl.PODE_BLOCO_CODIGO_FONTE, ['codeBlock'], true);
        insereItemToolbar(this.userControl.PODE_IMAGENS, ['insertImage'], false);
        insereItemToolbar(this.userControl.PODE_TABELAS, ['insertTable'], false);
        insereItemToolbar(this.userControl.PODE_EMBEDAR_CONTEUDO_EXTERNO, ['htmlEmbed'], true);
        insereItemToolbar(this.userControl.PODE_ALTERAR_ALINHAMENTO, ['alignment'], false);
        insereItemToolbar(this.userControl.PODE_INDENTAR, ['outdent', 'indent'], false);
        insereItemToolbar(this.userControl.PODE_DESTACAR, ['highlight'], true);
        insereItemToolbar(this.userControl.PODE_LISTAS_TRACOS, ['bulletedList'], false);
        insereItemToolbar(this.userControl.PODE_LISTAS_NUMERO, ['numberedList'], false);
        insereItemToolbar(this.userControl.PODE_LISTAS_CHECKBOX, ['todoList'], true);
        insereItemToolbar(this.userControl.PODE_EDITAR_VISUALIZAR_FONTE, ['sourceEditing', 'showBlocks'], true);
        insereItemToolbar(this.userControl.PODE_TELA_CHEIA, ['fullScreen'], false);
        insereItemToolbar(true, ['accessibilityHelp'], false);
        return toolbar;
    }

    /**
     * Retorna os feeds para exibir as menções para usuários.
     */
    async getFeedsMencoes() {
        // @ts-ignore
        const mencoes = this.userControl.ORIGEM_DADOS_MENCOES || gx?.http?.viewState?.[this.userControl.LabelForAttValue + '_Origem_dados_mencoes'];
        if (!mencoes) {
            GOVBR.logs.warn('Não recebeu ou não foi configurada uma lista de menções para exibir, o recurso estará disponíveis apenas em modo de visualização.');
            return [];
        }
        return await Promise.all(
            JSON.parse(mencoes).map(
                /**
                 * @param {import('./GOVBREditorHTMLUserControl.mjs').GOVBREditorHTMLUserControlOrigemDadosMencoes} origemDadosMencao
                 * @returns {Promise<any>}
                 */
                async (origemDadosMencao) => {
                    /**
                     * @type {import('./GOVBREditorHTMLUserControl.mjs').GOVBREditorHTMLUserControlMencao[]}
                     */
                    let dados = null;
                    /**
                     * @type {number}
                     */
                    let timeout = null;
                    if (origemDadosMencao.filtrarNoCliente) {
                        dados = await this.carregaMencoes(origemDadosMencao.origemDados, origemDadosMencao.caractereMarcador, origemDadosMencao.naoDestacar);
                    }
                    return {
                        marker: origemDadosMencao.caractereMarcador,
                        minimumCharacters: origemDadosMencao.minimoCaracteres || 0,
                        feed:
                            /**
                             * @param {string} query
                             * @returns {Promise<import('./GOVBREditorHTMLUserControl.mjs').GOVBREditorHTMLUserControlMencao[]>}
                             */
                            (query) => {
                                if (origemDadosMencao.filtrarNoCliente) {
                                    return this.carregaFeedMencoesCliente(dados, query);
                                }
                                if (timeout) {
                                    clearTimeout(timeout);
                                }
                                return new Promise((resolve) => {
                                    timeout = setTimeout(() => {
                                        timeout = null;
                                        resolve(
                                            this.carregaFeedMencoesServidor(
                                                origemDadosMencao.origemDados,
                                                query,
                                                origemDadosMencao.caractereMarcador,
                                                origemDadosMencao.naoDestacar
                                            )
                                        );
                                    }, 350);
                                });
                            },
                        itemRenderer: this.renderizaItemFeed.bind(this),
                    };
                }
            )
        );
    }

    /**
     * Retorna o feed de menções filtrando no cliente.
     * @param {import('./GOVBREditorHTMLUserControl.mjs').GOVBREditorHTMLUserControlMencao[]} dados
     * @param {string} query
     * @return {Promise<import('./GOVBREditorHTMLUserControl.mjs').GOVBREditorHTMLUserControlMencao[]>}
     */
    async carregaFeedMencoesCliente(dados, query) {
        if (!query) {
            return dados.map((dado) => {
                dado.matches = [];
                return dado;
            });
        }
        const fuseOptions = {
            threshold: 0.3,
            includeMatches: true,
            includeScore: true,
            /**
             * @param {any} obj
             * @param {string|string[]} path
             * @returns {string|string[]}
             */
            getFn: (obj, path) => {
                const value = Fuse.config.getFn(obj, path) || '';
                if (Array.isArray(value)) {
                    return value.map((el) => el.normalize('NFD').replace(/[\u0300-\u036f]/g, ''));
                }
                return value.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
            },
            /**
             * @param {any} a
             * @param {any} b
             */
            sortFn: (a, b) => {
                return b.score - a.score;
            },
            keys: [
                'id',
                'nome',
                {
                    name: 'dadosAdicionais',
                    weight: 0.4,
                },
            ],
        };
        const fuse = new Fuse(dados, fuseOptions);
        /**
         * @type {any[]}
         */
        const ret = fuse.search(query.normalize('NFD').replace(/[\u0300-\u036f]/g, ''));
        return ret.map((resultado) => {
            const item = dados[resultado.refIndex];
            item.matches = resultado.matches;
            return item;
        });
    }

    /**
     * Retorna o feed de menções filtrando no servidor.
     * @param {string} origemDados
     * @param {string} query
     * @param {string} marcador
     * @param {boolean} naoDestacar
     * @return {Promise<import('./GOVBREditorHTMLUserControl.mjs').GOVBREditorHTMLUserControlMencao[]>}
     */
    async carregaFeedMencoesServidor(origemDados, query, marcador, naoDestacar) {
        let separador = '?';
        if (origemDados.includes('?')) {
            separador = '&';
        }
        return await this.carregaMencoes(origemDados + separador + 'q=' + query, marcador, naoDestacar);
    }

    /**
     * Carrega as menções para a origem de dados.
     * @param {string} origemDados
     * @param {string} marcador
     * @param {boolean} naoDestacar
     * @return {Promise<import('./GOVBREditorHTMLUserControl.mjs').GOVBREditorHTMLUserControlMencao[]>}
     */
    async carregaMencoes(origemDados, marcador, naoDestacar) {
        try {
            const retorno = await fetch(origemDados);
            if (retorno.status !== 200) {
                throw new Error('Resposta inválida do servidor: ' + retorno.status + '.');
            }
            const dados = await retorno.json();
            if (!Array.isArray(dados)) {
                throw new Error('Retorno inválido do servidor.');
            }
            return dados.map((dado) => {
                dado.id = marcador + dado.id;
                if (dado.text) {
                    dado.text = marcador + dado.text;
                }
                dado.naoDestacar = naoDestacar;
                return dado;
            });
        } catch (ex) {
            GOVBR.logs.error(ex);
            throw new Error('Não foi possível carregar as menções: ' + ex.message);
        }
    }

    /**
     * Renderiza um item do feed.
     * @param {import('./GOVBREditorHTMLUserControl.mjs').GOVBREditorHTMLUserControlMencao} item
     * @returns {HTMLElement}
     */
    renderizaItemFeed(item) {
        GOVBR.logs.debug(this, item);

        const base = document.createElement('div');
        base.classList.add('govbr-item-mencao');

        const id = document.createElement('p');
        id.setAttribute('data-id', 'id');
        id.classList.add('govbr-item-mencao-id');
        id.innerText = item.id;
        base.append(id);

        const nome = document.createElement('p');
        nome.setAttribute('data-id', 'nome');
        nome.classList.add('govbr-item-mencao-nome');
        nome.innerText = item.nome;
        base.append(nome);

        if (item.dadosAdicionais?.length) {
            const dadosAdicionais = document.createElement('div');
            dadosAdicionais.classList.add('govbr-item-mencao-dados');
            item.dadosAdicionais.forEach((dado, idx) => {
                const dadoHtml = document.createElement('p');
                dadoHtml.setAttribute('data-id', 'dadosAdicionais');
                dadoHtml.setAttribute('data-ref-index', '' + idx);
                dadoHtml.classList.add('govbr-item-mencao-dados-dado');
                dadoHtml.innerText = dado;
                dadosAdicionais.append(dadoHtml);
            });
            base.append(dadosAdicionais);
        }

        if (item.matches?.length) {
            item.matches.forEach((match) => {
                let seletor = '[data-id="' + match.key + '"]';
                if (typeof match.refIndex === 'number') {
                    seletor += '[data-ref-index="' + match.refIndex + '"]';
                }
                const el = base.querySelector(seletor);
                if (el) {
                    match.indices
                        .slice()
                        .reverse()
                        .forEach((indice) => {
                            let ini, fim;
                            if (Array.isArray(indice)) {
                                [ini, fim] = indice;
                            } else {
                                ({ ini, fim } = indice);
                            }
                            el.innerHTML = el.innerHTML.substring(0, ini) + '<strong>' + el.innerHTML.substring(ini, fim + 1) + '</strong>' + el.innerHTML.substring(fim + 1);
                        });
                }
            });
        }

        return base;
    }
}

// Caso esteja no browser, disponibiliza a classe no objeto de window.
if (typeof window !== 'undefined') {
    // @ts-ignore
    window['GOVBREditorHTMLUC'] = GOVBREditorHTMLUC;
}
export { GOVBREditorHTMLUC };
