import { IconesFontAwesome } from '../../fontawesome/6.5.1/fa.mjs';

/**
 * @readonly
 * @enum {string}
 */
export const ResolucoesPagina = {
    DESKTOP: '',
    LAPTOPS: 'Ld',
    TABLET: 'Md',
    CELULAR: 'Sd',
};

/**
 * @readonly
 * @enum {number}
 */
export const ComponenteEditorTiposPropriedade = {
    TEXTO: 1,
    NUMERO: 2,
    BOOLEANO: 3,
    TEXTO_LONGO: 4,
    COR: 5,
    HTML: 6,
    LISTA: 7,
    LISTA_MULTIPLA: 8,
    ARRAY: 9,
    SUGGEST: 10,
};

/**
 * @typedef {Object} ComponenteEditorPosicao
 * @prop {number} numeroColunas
 * @prop {number} numeroLinhas
 * @prop {number=} posicaoColuna
 * @prop {number=} posicaoLinha
 */

/**
 * @typedef {Object} ComponenteEditorPropriedade
 * @prop {string} atributo
 * @prop {ComponenteEditorTiposPropriedade} tipo
 * @prop {Omit<ComponenteEditorPropriedade, 'valor'>[]=} subtipos
 * @prop {{ valor: string; titulo: string; icone?: string; padrao?: boolean; termos?: string[] }[]=} opcoes
 * @prop {any=} valor
 * @prop {string=} titulo
 * @prop {(componente: ComponenteEditor, propriedade: ComponenteEditorPropriedade, valor: string | boolean) => void=} change
 * @prop {boolean=} oculta
 * @prop {boolean=} leitura
 * @prop {boolean=} quebraLinha
 * @prop {string=} hint
 */

/**
 * @typedef {Object} ComponenteEditor
 * @prop {string} id
 * @prop {string} titulo
 * @prop {string} icone
 * @prop {ComponenteEditorPosicao} posicao
 * @prop {ComponenteEditorPosicao} posicaoLd
 * @prop {ComponenteEditorPosicao} posicaoMd
 * @prop {ComponenteEditorPosicao} posicaoSd
 * @prop {ComponenteEditorPropriedade[]} propriedades
 * @prop {boolean} exibeLateral
 */

/**
 * @typedef {Object} ComponenteEditorDefault
 * @prop {string=} id
 * @prop {string=} titulo
 * @prop {string=} icone
 * @prop {ComponenteEditorPosicao=} posicao
 * @prop {ComponenteEditorPosicao=} posicaoLd
 * @prop {ComponenteEditorPosicao=} posicaoMd
 * @prop {ComponenteEditorPosicao=} posicaoSd
 * @prop {ComponenteEditorPropriedade[]=} propriedades
 * @prop {boolean=} exibeLateral
 */

/**
 * @type {ComponenteEditorPosicao}
 */
const POSICAO_XLD_DEFAULT = {
    numeroColunas: 6,
    numeroLinhas: 1,
};

/**
 * @type {ComponenteEditorPosicao}
 */
const POSICAO_LD_MD_SD_DEFAULT = {
    numeroColunas: 12,
    numeroLinhas: 1,
};

/**
 * @param {ComponenteEditor} componente
 * @param {ComponenteEditorPropriedade} propriedade
 * @param {any} valor
 */
const atualizaPropriedadeOrigemServico = (componente, propriedade, valor) => {
    propriedade.valor = valor;
    /**
     * @type {ComponenteEditorPropriedade}
     */
    let categoria = {};
    /**
     * @type {ComponenteEditorPropriedade}
     */
    let perfil = {};
    /**
     * @type {ComponenteEditorPropriedade}
     */
    let tags = {};
    componente.propriedades.forEach((propriedade) => {
        switch (propriedade.atributo) {
            case 'dados.categoria':
                categoria = propriedade;
                break;
            case 'dados.perfil':
                perfil = propriedade;
                break;
            case 'dados.tags':
                tags = propriedade;
                break;
        }
    });
    switch (valor) {
        case 'categoria':
            categoria.oculta = false;
            perfil.valor = [];
            perfil.oculta = true;
            tags.valor = [];
            tags.oculta = true;
            break;
        case 'perfil':
            categoria.valor = [];
            categoria.oculta = true;
            perfil.oculta = false;
            tags.valor = [];
            tags.oculta = true;
            break;
        case 'tags':
            categoria.valor = [];
            categoria.oculta = true;
            perfil.valor = [];
            perfil.oculta = true;
            tags.oculta = false;
            break;
        case 'acessados':
        case 'destaques':
        default:
            categoria.valor = [];
            categoria.oculta = true;
            perfil.valor = [];
            perfil.oculta = true;
            tags.valor = [];
            tags.oculta = true;
            break;
    }
};

/**
 * @param {ComponenteEditor} componente
 * @param {ComponenteEditorPropriedade} propriedade
 * @param {any} valor
 */
const atualizaPropriedadeAgrupamentoServicos = (componente, propriedade, valor) => {
    propriedade.valor = valor;
    /**
     * @type {ComponenteEditorPropriedade}
     */
    let categoria = {};
    /**
     * @type {ComponenteEditorPropriedade}
     */
    let perfil = {};
    componente.propriedades.forEach((propriedade) => {
        switch (propriedade.atributo) {
            case 'dados.categoria':
                categoria = propriedade;
                break;
            case 'dados.perfil':
                perfil = propriedade;
                break;
        }
    });
    switch (valor) {
        case 'perfil':
            categoria.valor = [];
            categoria.oculta = true;
            perfil.oculta = false;
            break;
        case 'categoria':
        default:
            categoria.oculta = false;
            perfil.valor = [];
            perfil.oculta = true;
            break;
    }
};

/**
 * @param {any[]} todasCategorias
 * @param {any[]} todosPublicosAlvo
 * @param {any[]} todasTags
 * @param {any[]} todasAgendas
 * @returns {Promise<ComponenteEditor[]>}
 */
export async function ListaComponentesEditor(todasCategorias, todosPublicosAlvo, todasTags, todasAgendas) {
    const categorias = await (async () => {
        return (todasCategorias || []).map((categoria) => ({ valor: categoria.id, titulo: categoria.titulo }));
    })();
    const perfis = await (async () => {
        return (todosPublicosAlvo || []).map((perfil) => ({ valor: perfil.id, titulo: perfil.nome }));
    })();
    const tags = (todasTags || []).map((tag) => ({ valor: tag.id, titulo: tag.nome }));

    const icones = IconesFontAwesome.map((icone) => ({
        valor: icone.nome,
        titulo: icone.titulo,
        icone: icone.nome,
        termos: [...[icone.nome, icone.titulo], ...icone.termosPesquisa],
    }));

    const agendas = (todasAgendas || []).map((agenda) => ({
        valor: agenda.id,
        titulo: agenda.nome,
        icone: agenda.icone,
    }));

    /**
     * @param {boolean} icone
     * @param {boolean} titulo
     * @param {ComponenteEditorDefault} props
     * @returns {ComponenteEditor}
     */
    function montaComponenteDefault(icone, titulo, props) {
        /**
         * @type {Record<keyof ComponenteEditor, any>}
         */
        const retorno = {
            id: '',
            titulo: '',
            icone: '',
            posicao: POSICAO_XLD_DEFAULT,
            posicaoLd: POSICAO_LD_MD_SD_DEFAULT,
            posicaoMd: POSICAO_LD_MD_SD_DEFAULT,
            posicaoSd: POSICAO_LD_MD_SD_DEFAULT,
            propriedades: [],
            exibeLateral: true,
        };
        Object.entries(props).forEach(
            /**
             * @param {[string & keyof(ComponenteEditor), any]} _
             */
            ([prop, val]) => {
                retorno[prop] = val;
            }
        );
        if (titulo) {
            retorno.propriedades.unshift({
                atributo: 'dados.titulo',
                titulo: 'Título',
                tipo: ComponenteEditorTiposPropriedade.TEXTO,
                hint: 'Título que é exibido no topo do componente.',
            });
        }
        if (icone) {
            retorno.propriedades.unshift({
                atributo: 'dados.icone',
                titulo: 'Ícone',
                tipo: ComponenteEditorTiposPropriedade.SUGGEST,
                opcoes: icones,
                hint: 'Ícone exibido junto ao título do componente.',
            });
        }
        return retorno;
    }

    return [
        montaComponenteDefault(false, true, {
            id: 'agenda',
            titulo: 'Agenda',
            icone: 'fas fa-calendar-days',
            propriedades: [
                {
                    atributo: 'dados.agendas',
                    titulo: 'Agendas',
                    tipo: ComponenteEditorTiposPropriedade.LISTA_MULTIPLA,
                    opcoes: agendas,
                    hint: 'Agendas do qual os eventos serão buscados.',
                },
                {
                    atributo: 'dados.agendasAgrupadas',
                    titulo: 'Exibir Agendas como Agrupamentos',
                    tipo: ComponenteEditorTiposPropriedade.BOOLEANO,
                    hint: 'Caso marcado, ao invés do Usuário filtrar pelas agendas, ele será exibido uma lista para seleção da agenda a visualizar.',
                },
                {
                    atributo: 'dados.formato',
                    titulo: 'Formato de Exibição',
                    tipo: ComponenteEditorTiposPropriedade.LISTA,
                    opcoes: [
                        { valor: '3', titulo: 'Calendário', padrao: true },
                        { valor: '4', titulo: 'Eventos' },
                    ],
                    hint: 'Se deve exibir em formato de calendário com os dias, ou apenas os eventos do mês selecionado.',
                },
            ],
        }),
        montaComponenteDefault(false, true, {
            id: 'avisos',
            titulo: 'Aviso',
            icone: 'fas fa-triangle-exclamation',
            propriedades: [
                {
                    atributo: 'dados.formato',
                    titulo: 'Formato',
                    tipo: ComponenteEditorTiposPropriedade.LISTA,
                    opcoes: [
                        { valor: 'aviso', titulo: 'Aviso', padrao: true },
                        { valor: 'alerta', titulo: 'Alerta' },
                        { valor: 'sucesso', titulo: 'Sucesso' },
                        { valor: 'erro', titulo: 'Emergência' },
                    ],
                    hint: '<b>Aviso:</b> Para avisos gerais de menor importância. Aparece em azul. Ex: "Participe da festa anual no dia 12 de Agosto!"<br/><b>Alerta:</b> Para alertas de maior importância. Aparece em amarelo. Ex: "Atente-se a interdições devido obras nas vias centrais ao trafegar pela cidade.".<br/><b>Sucesso:</b> Para indicações de sucesso, melhorias, ou ausência de problemas. Aparece em verde. Ex: "O nível do rio está normal. Estamos monitorando este continuamente."<br/><b>Emergência:</b> Para indicações de Emergências. Aparece em vermelho. Ex: "Diversas ruas foram inundadas devido as recentes cheias. Caso você tenha sido atingido, ligue para o número de telefone: (número).".',
                },
                { atributo: 'conteudo', titulo: 'Conteúdo Textual', tipo: ComponenteEditorTiposPropriedade.TEXTO_LONGO },
            ],
        }),
        montaComponenteDefault(false, false, {
            id: 'banner',
            titulo: 'Banners',
            icone: 'fas fa-ticket',
            propriedades: [
                {
                    atributo: 'dados.estilo',
                    titulo: 'Estilo',
                    tipo: ComponenteEditorTiposPropriedade.LISTA,
                    opcoes: [
                        { valor: 'branco', titulo: 'Branco', padrao: true },
                        { valor: 'preto', titulo: 'Preto' },
                    ],
                },
                {
                    atributo: 'dados.banners',
                    titulo: 'Banners',
                    tipo: ComponenteEditorTiposPropriedade.ARRAY,
                    subtipos: [
                        { atributo: 'descricao', titulo: 'Descrição', tipo: ComponenteEditorTiposPropriedade.TEXTO, hint: 'Descrição da imagem do Banner.' },
                        { atributo: 'url', titulo: 'URL da Imagem', tipo: ComponenteEditorTiposPropriedade.TEXTO, hint: 'URL da imagem exibida no Banner.' },
                        { atributo: 'href', titulo: 'Link ao Clicar', tipo: ComponenteEditorTiposPropriedade.TEXTO, hint: 'URL que será aberta ao clicar no Banner.' },
                    ],
                },
            ],
        }),
        montaComponenteDefault(true, true, {
            id: 'conteudo-html',
            titulo: 'Conteúdo HTML',
            icone: 'fas fa-code',
            propriedades: [
                { atributo: 'conteudo', titulo: 'Conteúdo HTML', tipo: ComponenteEditorTiposPropriedade.HTML },
            ],
        }),
        montaComponenteDefault(true, true, {
            id: 'conteudo-textual',
            titulo: 'Conteúdo Textual',
            icone: 'fas fa-align-center',
            propriedades: [
                { atributo: 'conteudo', titulo: 'Conteúdo Textual', tipo: ComponenteEditorTiposPropriedade.TEXTO_LONGO },
            ],
        }),
        montaComponenteDefault(false, true, {
            id: 'enquete',
            titulo: 'Enquetes',
            icone: 'fas fa-comments',
            propriedades: [],
        }),
        montaComponenteDefault(false, false, {
            id: 'imagem',
            titulo: 'Imagem',
            icone: 'fas fa-image',
            propriedades: [
                { atributo: 'dados.descricao', titulo: 'Descrição', tipo: ComponenteEditorTiposPropriedade.TEXTO },
                { atributo: 'dados.url', titulo: 'URL da Imagem', tipo: ComponenteEditorTiposPropriedade.TEXTO },
            ],
        }),
        montaComponenteDefault(true, true, {
            id: 'links',
            titulo: 'Links',
            icone: 'fas fa-link',
            propriedades: [
                {
                    atributo: 'dados.formato',
                    titulo: 'Formato',
                    tipo: ComponenteEditorTiposPropriedade.LISTA,
                    opcoes: [
                        { valor: 'lista', titulo: 'Lista', padrao: true },
                        { valor: 'blocos', titulo: 'Blocos' },
                    ],
                },
                {
                    atributo: 'dados.links',
                    titulo: 'Links',
                    tipo: ComponenteEditorTiposPropriedade.ARRAY,
                    subtipos: [
                        { atributo: 'link', titulo: 'Link ao Clicar', tipo: ComponenteEditorTiposPropriedade.TEXTO, hint: 'URL que será aberta ao clicar no Link.' },
                        { atributo: 'titulo', titulo: 'Título', tipo: ComponenteEditorTiposPropriedade.TEXTO, hint: 'Título do link a ser exibido para o Usuário.' },
                        {
                            atributo: 'imagem',
                            titulo: 'URL da Imagem',
                            tipo: ComponenteEditorTiposPropriedade.TEXTO,
                            hint: 'URL de uma imagem, dependendo do formato será exibida ao fundo ou adjacente ao título.',
                        },
                    ],
                },
            ],
        }),
        montaComponenteDefault(false, true, {
            id: 'midias',
            titulo: 'Midias',
            icone: 'fas fa-camera',
            propriedades: [
                {
                    atributo: 'dados.tipo',
                    titulo: 'Tipo',
                    tipo: ComponenteEditorTiposPropriedade.LISTA,
                    opcoes: [
                        { valor: '', titulo: 'Todos', padrao: true },
                        { valor: 'imagens', titulo: 'Imagens' },
                        { valor: 'videos', titulo: 'Vídeos' },
                    ],
                },
            ],
        }),
        montaComponenteDefault(false, true, {
            id: 'noticias',
            titulo: 'Noticias',
            icone: 'fas fa-newspaper',
            propriedades: [
                {
                    atributo: 'dados.tags',
                    titulo: 'Filtros (Tags)',
                    tipo: ComponenteEditorTiposPropriedade.LISTA_MULTIPLA,
                    opcoes: tags,
                },
            ],
        }),
        montaComponenteDefault(false, false, {
            id: 'tempo',
            titulo: 'Previsão do Tempo',
            icone: 'fas fa-cloud-sun',
            propriedades: [
                {
                    atributo: 'dados.geokey',
                    titulo: 'Chave de Localização',
                    tipo: ComponenteEditorTiposPropriedade.TEXTO,
                    hint: 'Chave de geolocalização, adquirida da URL da página da cidade.<br/>Por exemplo, para a cidade de blumenau, a URL é:<br/><i><a target="_blank" href="https://www.climaeradar.com.br/previsao-tempo/blumenau/11848281">https://www.climaeradar.com.br/previsao-tempo/blumenau/11848281</a></i><br/>portanto a chave é <i>11848281</i>.',
                },
            ],
        }),
        montaComponenteDefault(false, true, {
            id: 'secretarias',
            titulo: 'Secretarias',
            icone: 'fas fa-landmark',
            propriedades: [
                {
                    atributo: 'dados.formato',
                    titulo: 'Formato',
                    tipo: ComponenteEditorTiposPropriedade.LISTA,
                    opcoes: [
                        { valor: 'blocos', titulo: 'Blocos', padrao: true },
                        { valor: 'lista', titulo: 'Lista' },
                    ],
                },
            ],
        }),
        montaComponenteDefault(false, true, {
            id: 'servicos',
            titulo: 'Servicos',
            icone: 'fas fa-circle-info',
            propriedades: [
                {
                    atributo: 'dados.formato',
                    titulo: 'Formato',
                    tipo: ComponenteEditorTiposPropriedade.LISTA,
                    opcoes: [
                        { valor: 'blocos', titulo: 'Blocos', padrao: true },
                        { valor: 'lista', titulo: 'Lista' },
                        { valor: 'lista-agrupada', titulo: 'Lista com Agrupamentos' },
                    ],
                    change: (componente, propriedade, valor) => {
                        propriedade.valor = valor;
                        const propriedadeOrigem = componente.propriedades.find((propriedade) => propriedade.atributo === 'dados.origem');
                        const propriedadeAgrupamento = componente.propriedades.find((propriedade) => propriedade.atributo === 'dados.agrupamentos');
                        if (valor === 'lista-agrupada') {
                            atualizaPropriedadeOrigemServico(componente, propriedadeOrigem, null);
                            atualizaPropriedadeAgrupamentoServicos(componente, propriedadeAgrupamento, propriedadeAgrupamento.valor || 'categoria');
                            propriedadeOrigem.oculta = true;
                            propriedadeAgrupamento.oculta = false;
                        } else {
                            atualizaPropriedadeAgrupamentoServicos(componente, propriedadeAgrupamento, null);
                            atualizaPropriedadeOrigemServico(componente, propriedadeOrigem, propriedadeOrigem.valor || 'acessados');
                            propriedadeOrigem.oculta = false;
                            propriedadeAgrupamento.oculta = true;
                        }
                    },
                },
                {
                    atributo: 'dados.agrupamentos',
                    titulo: 'Agrupamentos',
                    tipo: ComponenteEditorTiposPropriedade.LISTA,
                    opcoes: [
                        { valor: 'categoria', titulo: 'Categorias', padrao: true },
                        { valor: 'perfil', titulo: 'Perfis' },
                    ],
                    change: (componente, propriedade, valor) => {
                        atualizaPropriedadeAgrupamentoServicos(componente, propriedade, valor);
                    },
                },
                {
                    atributo: 'dados.origem',
                    titulo: 'Origem',
                    tipo: ComponenteEditorTiposPropriedade.LISTA,
                    opcoes: [
                        { valor: 'acessados', titulo: 'Mais Acessados', padrao: true },
                        { valor: 'destaques', titulo: 'Destaques' },
                        { valor: 'categoria', titulo: 'Todos das Categorias' },
                        { valor: 'perfil', titulo: 'Todos dos Perfis' },
                        { valor: 'tags', titulo: 'Todos das Tags' },
                    ],
                    change: atualizaPropriedadeOrigemServico,
                },
                {
                    atributo: 'dados.categoria',
                    titulo: 'Categorias',
                    tipo: ComponenteEditorTiposPropriedade.LISTA_MULTIPLA,
                    opcoes: categorias,
                },
                {
                    atributo: 'dados.perfil',
                    titulo: 'Perfis',
                    tipo: ComponenteEditorTiposPropriedade.LISTA_MULTIPLA,
                    opcoes: perfis,
                },
                {
                    atributo: 'dados.tags',
                    titulo: 'Tags',
                    tipo: ComponenteEditorTiposPropriedade.LISTA_MULTIPLA,
                    opcoes: tags,
                },
                {
                    atributo: 'dados.cartaServicos',
                    titulo: 'Exibe Carta de Serviços',
                    tipo: ComponenteEditorTiposPropriedade.BOOLEANO,
                    valor: true,
                },
            ],
        }),
        montaComponenteDefault(false, false, {
            id: 'tema',
            titulo: 'Tema',
            icone: 'fas fa-brush',
            propriedades: [
                { atributo: 'dados.corDestaque', titulo: 'Cor de Destaque', tipo: ComponenteEditorTiposPropriedade.COR },
                { atributo: 'dados.tituloPagina', titulo: 'Título da Página', tipo: ComponenteEditorTiposPropriedade.TEXTO },
                { atributo: 'dados.linkBrasao', titulo: 'Link para a Imagem do Brasão', tipo: ComponenteEditorTiposPropriedade.TEXTO },
                { atributo: 'dados.linkHome', titulo: 'Link ao clicar no Brasão', tipo: ComponenteEditorTiposPropriedade.TEXTO },
            ],
            exibeLateral: false,
        }),
        montaComponenteDefault(false, true, {
            id: 'textos-normativos',
            titulo: 'Textos Normativos',
            icone: 'fas fa-gavel',
            propriedades: [],
        }),
        montaComponenteDefault(false, true, {
            id: 'acoes-projetos',
            titulo: 'Ações Projetos',
            icone: 'fas fa-link',
            propriedades: [
                {
                    atributo: 'dados.formato',
                    titulo: 'Formato',
                    tipo: ComponenteEditorTiposPropriedade.LISTA,
                    opcoes: [
                        { valor: 'lista', titulo: 'Lista', padrao: true },
                        { valor: 'blocos', titulo: 'Blocos' },
                    ],
                },
                {
                    atributo: 'dados.tipo',
                    titulo: 'Tipo',
                    tipo: ComponenteEditorTiposPropriedade.LISTA,
                    opcoes: [
                        { valor: '', titulo: 'Todos', padrao: true },
                        { valor: 'acao', titulo: 'Ações' },
                        { valor: 'projeto', titulo: 'Projetos' },
                    ],
                },
            ],
        }),
    ];
}
