/**
 * Classe para o UC do PDFJS.
 */
class GOVBRPDFJSUC {
    /**
     * @type {import("./GOVBRPDFJSUserControl.mjs").GOVBRPDFJSUserControl}
     */
    userControl;
    /**
     * @type {string}
     */
    id;
    /**
     * @type {HTMLIFrameElement}
     */
    frame;

    /**
     * @param {import("./GOVBRPDFJSUserControl.mjs").GOVBRPDFJSUserControl} userControl
     * @param {HTMLElement} host
     */
    constructor(userControl, host) {
        this.userControl = userControl;

        // Trata a URL do PDF.
        let urlPDF = this.userControl.URL_PDF || '';
        if (urlPDF.startsWith('./')) {
            urlPDF = '../../.' + urlPDF;
        }

        // Cria o IFRAME do PDFJS.
        this.frame = document.createElement('iframe');
        this.frame.classList.add('govbr-pdfjs-content-frame');
        this.id = new Date().getTime() + '-' + Math.floor(Math.random() * 10000);
        this.frame.setAttribute('data-govbr-id', this.id);
        this.frame.src = this.userControl.URL_CDN + '/genexus/pdfjs-lib/' + this.userControl.VERSAO_COMPONENTE + '/web/viewer.html?file=' + urlPDF + '&govbrId=' + this.id;
        this.frame.style.width = this.userControl.LARGURA_COMPONENTE;
        this.frame.style.height = this.userControl.ALTURA_COMPONENTE;
        // @ts-ignore
        this.frame.__govbr_self = this;
        host.append(this.frame);
        GOVBR.logs.debug('PDFJS - Inicializado', this.userControl);

        GOVBRPlataformaJS.importarStyleSheet(this.userControl.URL_CDN, 'pdfjs', this.userControl.VERSAO_JS_COMPONENTE, 'GOVBRPDFJSUC', host);

        // Cria o evento de clicar em um item de assinatura caso este não exista.
        if (!this.userControl.__govbr_fn_click_assinatura) {
            this.userControl.__govbr_fn_click_assinatura = (details) => {
                this.userControl.ID_ASSINATURA_CLICADA = details.fieldName;
                this.userControl?.clickAssinatura?.();
            };
        }

        // Cria o evento global de inicialização do PDFJS.
        // @ts-ignore
        if (!window['__GOVBR_PDFJS_EVENT']) {
            // @ts-ignore
            window['__GOVBR_PDFJS_EVENT'] = (event) => this.recebeMessagesComponente(event);
            // @ts-ignore
            window.addEventListener('message', window['__GOVBR_PDFJS_EVENT']);
        }
    }

    /**
     * Inicia o recebimento de mensagens via postMessage para o componente
     * @param {MessageEvent} event
     */
    recebeMessagesComponente(event) {
        if (Array.isArray(event.data)) {
            if (/^https:\/\/.*\.govbr(\.cloud|\.com\.br)|^http:\/\/localhost/.test(event?.origin || '')) {
                const [nomeEvento, id, ...dadosAdicionais] = event.data;
                let origem = document.querySelector('[data-govbr-id="' + id + '"]');
                if (!origem) {
                    /**
                     * @param {Document|ShadowRoot} tg
                     * @param {string} selector
                     * @returns {HTMLElement}
                     */
                    function fetchShadow(tg, selector) {
                        let ret = /** @type {HTMLElement} */ (tg.querySelector(selector));
                        if (!ret) {
                            Array.from(tg.querySelectorAll('*'), (e) => e.shadowRoot)
                                .filter((e) => e)
                                .some((e) => (ret = fetchShadow(e, selector)));
                        }
                        return ret;
                    }
                    origem = fetchShadow(document, '[data-govbr-id="' + id + '"]');
                }
                if (origem) {
                    this.trataMensagemComponente(origem, nomeEvento, dadosAdicionais);
                } else {
                    GOVBR.logs.error('PDFJS - Falha, não foi possível encontrar o IFrame de origem. ID: ' + id);
                }
            } else {
                GOVBR.logs.error('Domínio inválido - ' + event?.origin);
            }
        }
    }

    /**
     * Trata as mensagens recebidas via postMessage para o componente.
     * @param {any} origem
     * @param {string} nomeEvento
     * @param {any} dadosAdicionais
     */
    trataMensagemComponente(origem, nomeEvento, dadosAdicionais) {
        switch (nomeEvento) {
            // IFRAME FOI CARREGADO
            case '__pdfjs_webviewerloaded':
                origem.__govbr_self.iniciaPDFJS();
                break;
            // WIDGET FOI CARREGADO
            case '__pdfjs_wdgt_pronto':
                origem.setAttribute('data-carregado-pdfjs', '');
                break;
            // CLICOU EM UMA ASSINATURA
            case '__govbr_pdfjs_click_assinatura':
                if (this.userControl.__govbr_fn_click_assinatura) {
                    this.userControl.__govbr_fn_click_assinatura(dadosAdicionais[0]);
                }
                break;
            // PÁGINAS CARREGADAS
            case '__govbr_pdfjs_pagesloaded':
                const paginas = dadosAdicionais[0];
                this.userControl.NUMERO_PAGINAS = parseInt(paginas);
                break;
            // TROCOU A POSIÇÃO DO CARIMBO
            case '__govbr_pdfjs_carimbo_change':
                origem.dispatchEvent(
                    new CustomEvent('__govbr_pdfjs_carimbo_change', {
                        detail: dadosAdicionais[0],
                    })
                );
                break;
        }
    }

    /**
     * Inicia o PDFJS para o IFRAME especificado pelo source.
     */
    async iniciaPDFJS() {
        /**
         * @type {import("./GOVBRPDFJSUserControl.mjs").GovbrPDFJSUCConfig}
         */
        const config = {
            urlCDN: this.userControl.URL_CDN,
            versaoArquivo: this.userControl.VERSAO_JS_COMPONENTE || (await GOVBRPlataformaJS.getVersaoComponente('GOVBRPDFJSUC')),
            permiteSidebar: this.userControl.PERMITE_SIDEBAR,
            permiteImprimir: this.userControl.PERMITE_IMPRIMIR,
            permiteDownload: this.userControl.PERMITE_DOWNLOAD,
            permiteAnotacoes: this.userControl.PERMITE_ANOTACOES,
        };
        this.frame.contentWindow?.postMessage?.(['__govbr_pdfjs_init', this.id, config], '*');
    }
}

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