/**
 * @type {HTMLElement[]}
 */
const barrasProgresso = [];
const atualizaBarrasProgresso = () => {
    barrasProgresso.forEach((barra, idx) => {
        barra.style.setProperty('--idx', '' + idx);
    });
};

/**
 * Operações gerais para utilização dentro dos componentes do GOVBRPlataformaJS.
 */
class GOVBRPlataformaComponentUtils {
    /**
     * Escapa um valor para ser utilizado como atributo no HTML via innerHTML. (Não necessário se utilizado setAttribute).
     * @param {string} valor
     * @returns {string}
     */
    static escapaValorAtributoHTML(valor) {
        return (valor || '').replace(/"/g, '&quot;').replace(/>/g, '&gt;').replace(/</g, '&lt;').replace(/&/g, '&amp;');
    }

    /**
     * Abre um dialog para o Usuário confirmar/cancelar
     * @param {string} titulo
     * @param {() => void} onConfirma
     * @param {() => void} onValida
     */
    static abreDialog(titulo, onConfirma = null, onValida = null) {
        const dialog = document.createElement('dialog');
        dialog.classList.add('govbr-plataforma-dialog');
        dialog.addEventListener('click', function (event) {
            const rect = conteudo.getBoundingClientRect();
            if (event.target === dialog) {
                const isInDialog = rect.top <= event.clientY && event.clientY <= rect.top + rect.height && rect.left <= event.clientX && event.clientX <= rect.left + rect.width;
                if (!isInDialog) {
                    dialog.close();
                }
            }
        });
        dialog.addEventListener('keydown', (e) => {
            if (e.key === 'Escape') {
                dialog.close();
            }
        });
        dialog.addEventListener('close', () => {
            dialog.remove();
        });
        const dialogCt = document.createElement('div');
        dialogCt.classList.add('govbr-plataforma-dialog-base');
        dialog.append(dialogCt);
        const conteudo = document.createElement('article');
        conteudo.classList.add('govbr-plataforma-dialog-conteudo');
        const cabecalho = document.createElement('h2');
        cabecalho.classList.add('govbr-plataforma-dialog-cabecalho');
        cabecalho.innerText = titulo;
        conteudo.append(cabecalho);
        dialogCt.append(conteudo);

        const rodape = document.createElement('nav');
        rodape.classList.add('govbr-plataforma-dialog-rodape');
        if (onConfirma) {
            const botaoConfirma = document.createElement('button');
            botaoConfirma.type = 'button';
            botaoConfirma.classList.add('govbr-plataforma-dialog-botao');
            botaoConfirma.classList.add('govbr-plataforma-dialog-botao-confirma');
            botaoConfirma.innerText = 'Confirmar';
            botaoConfirma.addEventListener('click', () => {
                if (!onValida || onValida()) {
                    onConfirma();
                    dialog.close();
                }
            });
            rodape.append(botaoConfirma);
        }
        const botaoCancela = document.createElement('button');
        botaoCancela.type = 'button';
        botaoCancela.classList.add('govbr-plataforma-dialog-botao');
        botaoCancela.classList.add('govbr-plataforma-dialog-botao-fechar');
        botaoCancela.innerText = 'Fechar';
        botaoCancela.addEventListener('click', () => {
            dialog.close();
        });
        rodape.append(botaoCancela);
        dialogCt.append(rodape);

        document.body.append(dialog);
        dialog.show();
        return conteudo;
    }

    /**
     * Monta uma barra de progresso flutuante ou apendada a um alvo.
     * @param {HTMLElement} alvo
     * @return {{setTitulo: (valor: string) => void, setTotal: (valor: number) => void, setValor: (valor: number) => void, setProgressoTexto: (valor: string) => void, remove: () => void}}
     */
    static montaBarraProgresso(alvo = null) {
        const base = document.createElement('div');
        base.className = 'govbr-plataforma-progress';
        base.innerHTML = `
<h3 class="govbr-plataforma-progress-titulo">Enviando Dados</h3>
<div class="govbr-plataforma-progress-barra-container">
    <div class="govbr-plataforma-progress-barra"></div>
    <div class="govbr-plataforma-progress-barra-sobrepoe" style="--progresso: 0; --total: 1;"></div>
</div>
<span class="govbr-plataforma-progress-progresso"></span>`;
        const titulo = /** @type {HTMLElement} */ (base.querySelector('.govbr-plataforma-progress-titulo'));
        const barra = /** @type {HTMLElement} */ (base.querySelector('.govbr-plataforma-progress-barra-sobrepoe'));
        const progresso = /** @type {HTMLElement} */ (base.querySelector('.govbr-plataforma-progress-progresso'));

        if (alvo) {
            alvo.append(base);
        } else {
            document.body.append(base);
        }
        barrasProgresso.push(base);
        atualizaBarrasProgresso();

        return {
            setTitulo: (valor) => {
                titulo.innerText = 'Enviando: ' + valor;
            },
            setTotal: (valor) => {
                barra.style.setProperty('--total', '' + valor);
            },
            setValor: (valor) => {
                barra.style.setProperty('--progresso', '' + valor);
            },
            setProgressoTexto: (valor) => {
                progresso.innerText = valor;
            },
            remove: () => {
                base.remove();
                barrasProgresso.splice(barrasProgresso.indexOf(base), 1);
                atualizaBarrasProgresso();
            },
        };
    }

    /**
     * Converte a unidade de medida em bytes para um valor legível
     * @param {number} tamanho;
     */
    static converteUMTamanhoBytes(tamanho) {
        if (!tamanho) {
            return '0B';
        }

        const valorK = 1024;
        const tamanhos = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
        const idx = Math.floor(Math.log(tamanho) / Math.log(valorK));

        return `${parseFloat((tamanho / Math.pow(valorK, idx)).toFixed(2))} ${tamanhos[idx]}`;
    }
}

export { GOVBRPlataformaComponentUtils };
