<!DOCTYPE html>
<html lang="es">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Eventos y Enlaces Acestream</title>
    <style>
        /* Estilos existentes */
        .enlace-android {
            color: #ff002b;
            text-decoration: none;
            padding: 5px 10px;
        }

        .enlace-pc {
            color: #ff33a8;
            text-decoration: none;
            padding: 5px 10px;
        }

        .enlace-android:hover,
        .enlace-pc:hover {
            text-decoration: underline;
            background-color: rgba(255, 255, 255, 0.1);
        }

        body {
            text-align: center;
            background-color: #242424;
            color: #ffffff;
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
        }

        table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 20px;
            background-color: rgba(0, 0, 0, 0.2);
        }

        th,
        td {
            border: 1px solid #ffffff;
            padding: 12px 8px;
            text-align: center;
        }

        th {
            background-color: #0a8228;
            color: white;
        }

        #debug-console {
            margin-top: 20px;
            width: 100%;
            height: 300px;
            border: 2px solid #ff33a8;
            background-color: #000;
            color: #0f0;
            font-family: monospace;
            padding: 10px;
            box-sizing: border-box;
            overflow-y: auto;
            text-align: left;
            display: none;
        }

        .log-entry {
            margin: 5px 0;
            padding: 5px;
            border-bottom: 1px solid #333;

        }

        .log-info {
            color: #0f0;
        }

        .log-error {
            color: #f00;
        }

        .log-warning {
            color: #ff0;
        }

        .log-success {
            color: #0ff;
        }

        .log-data {
            color: #ff9900;
        }

        #connection-status {
            position: fixed;
            top: 10px;
            left: 10px;
            padding: 5px 10px;
            border-radius: 5px;
            font-weight: bold;
        }

        .status-connecting {
            background-color: #ff9900;
        }

        .status-connected {
            background-color: #00ff00;
            display: none;
        }

        .status-error {
            background-color: #ff0000;
        }

        .raw-data {
            margin-top: 10px;
            padding: 10px;
            background-color: rgba(0, 0, 0, 0.3);
            border: 1px solid #666;
            font-size: 12px;
            white-space: pre-wrap;
            max-height: 200px;
            overflow-y: auto;
        }

        .category-icon {
            width: 20px;
            height: 20px;
            vertical-align: middle;
            margin-right: 5px;
        }

        /* Eliminamos .category-cell y sus estilos */
        td img.category-icon+span {
            vertical-align: middle;
        }
    </style>
</head>

<body>
    <div class="container">
        <div id="connection-status">Verificando conexión...</div>
        <h1>/⁠╲⁠/⁠\⁠╭⁠(⁠•⁠‿⁠•⁠)⁠╮⁠/⁠\⁠╱⁠\</h1>
        <h1>Eventos Acestream Arena4Viewer ;)</h1>
        <h1>by TokyoGhoull</h1>

        <table id="eventos-tabla">
            <thead>
                <tr>
                    <th>Fecha</th>
                    <th>Hora</th>
                    <th>Categoría</th>
                    <th>Campeonato</th>
                    <th>Evento</th>
                    <th>Enlaces Android</th>
                    <th>Enlaces PC</th>
                </tr>
            </thead>
            <tbody></tbody>
        </table>

        <div id="debug-console"></div>
    </div>

    <script>
        // Diccionario de traducción de categorías
        const CATEGORIAS = {
            'BEACHSOCCER': 'Futbol Playa',
            'MOTOGP': 'MotoGP',
            'PADDLE': 'Pádel',
            'SOCCER': 'Futbol',
            'SPORTS': 'Deportes',
            'TENNIS': 'Tenis',
            'SYNCHRONIZED SWIMMING': 'Natación Sincronizada',
            'SNOOKER': 'Billar',
            'BASEBALL': 'Béisbol',
            'VOLLEYBALL': 'Voleibol',
            'MOTORCYCLING': 'Motociclismo',
            'F1': 'Fórmula 1',
            'MMA': 'Artes Marciales Mixtas',
            'UFC': 'UFC',
            'GOLF': 'Golf',
            'EVENT': 'Evento',
            'MOTOR': 'Motor',
            'MOTOS': 'Motocicletas',
            'RUGBY': 'Rugby',
            'TENIS': 'Tenis',
            'FORMULA 1': 'Fórmula 1',
            'VOLLEYBALL (W)': 'Voleibol (F)',
            'ATHLETICS': 'Atletismo',
            'BASKETBALL (W)': 'Baloncesto (F)',
            'SWIMMING': 'Natación',
            'BADMINTON': 'Bádminton',
            'HANDBALL': 'Balonmano',
            'MOTORSPORT': 'Automovilismo',
            'SWIMMING (W)': 'Natación (F)',
            'SWIMMING(W)': 'Natación (F)',
            'FOOTBALL': 'Futbol',
            'BASKETBALL': 'Baloncesto',
            'FORMULA1': 'Fórmula 1',
            'GYMNASTICS TRAMPOLINE': 'Gimnasia Trampolín',
            'BALONCESTO': 'Baloncesto',
            'MOTOCYCLING': 'Motociclismo',
            'BEACH SOCCER': 'Futbol Playa',
            'MIXEDMARTIALARTS': 'Artes Marciales Mixtas',
            'VOLLEYBALL(W)': 'Voleibol (F)',
            'BASKETBALL(W)': 'Baloncesto (F)',
            'CURLING': 'Curling',
            'SOCCER(W)': 'Futbol (F)',
            'CYCLING': 'Ciclismo',
            'BOXING': 'Boxeo',
            'SOCCER (W)': 'Futbol (F)',
            'EVENTS': 'Eventos',
            'FUTSAL': 'Futbol Sala',
            'BOBSLEIGH': 'Bobsleigh',
            'WRESTLING': 'Lucha Libre',
            'MARATHON': 'Atletismo',
        };

        // Diccionario de iconos en base64 (SVG)
        const CATEGORY_ICONS = {
            'Deportes': 'data:file/octet-stream;base64,UklGRkoCAABXRUJQVlA4WAoAAAAQAAAAHwAAHwAAQUxQSMIAAAABgLtt2/HlzrZte/v92u3aO9rs2uzJ3Gz3P9iTbWOzn/QprhExAfiH2kbnRYuUeVOLGrojItoqseXFMGODmC+L5Tmp5J0S+wkrDuFLxHnHno3+APG5rs3gGT9J/PZCQgJwansh3r0Ao/IbErBRJv2UBB1UOSNh61ApzJYVvAQ5MgVkpoXoAIBIIcQfFNb5S8WniWxGx/YeGF5mI/C50hxTFqBiIw6MTE+LDXKVALPvJzf1IvDeRXRR6wABPWYKjfBXB1ZQOCBiAQAAcAcAnQEqIAAgAD6RQpxKJaOioagIALASCWwAtvdengbJ45XUJuAAPoDk5VLjP23RrOZ0MLDjmAtAYw/LrxeizHf5AAAA/vsIaBgeOkUIOgZF7gvj3YG/vgNBLSvoVtZGNm//LgB2lOwV3FrmdSx0c2cvnt7sv/9f64sS7Qch1PeaKDx5SaMf3E/VlCqbe1Pv+GWu5hy0wQD3om9O+X55BLS7KstRCooFJdZpBGgNByHveZXVApo25/mvOj9rb65QcZ6PS2rghNhgh2xFGrzOfEijqF/apUVHgKNh+Z0u90x59oXXgdw5b1TSDRerumXUrVA9ue7OM9ojeX0Q0MCfsFEuwbSS/sZrbHJVheas/+Rc9mJRgAi+6gibr38/Hx3RVx8WC+uqbQRX+FvyS61Uix6f66jC4iIp/Kz6F/20lJiiTX+OZgS10jiz/f9MhkBPCmBhppJg7csrQVRPnx8CAAAA',
            'Motor': 'https://static.futbolenlatv.com/img/32/20130624110336-automovilismo.webp',
            'Boxeo': 'https://static.futbolenlatv.com/img/32/20130624110538-boxeo.webp',
            'Balonmano': 'https://static.futbolenlatv.com/img/32/20130724090914-balonmano.webp',
            'Pádel': 'https://static.futbolenlatv.com/img/32/20141020014848-padel.webp',
            'Rugby': 'https://static.futbolenlatv.com/img/32/20200729125932-rugby.webp',
            'Tenis': 'https://static.futbolenlatv.com/img/32/20130618113307-tenis.webp',
            'Futbol (F)': 'https://static.futbolenlatv.com/img/32/20130618113222-futbol.webp',
            'Futbol': 'https://static.futbolenlatv.com/img/32/20130618113222-futbol.webp',
            'Baloncesto (F)': 'https://static.futbolenlatv.com/img/32/20130618113234-baloncesto.webp',
            'Baloncesto': 'https://static.futbolenlatv.com/img/32/20130618113234-baloncesto.webp',
            'Fórmula 1': 'https://static.futbolenlatv.com/img/32/20130624110336-automovilismo.webp',
            'Golf': 'https://static.futbolenlatv.com/img/32/20130724083030-bola-golf.webp',
            'MotoGP': 'https://static.futbolenlatv.com/img/32/20130629041459-motociclismo.webp',
            // Mantener el default en base64 ya que es el icono de respaldo
            'default': 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTEyIDJDNi40OCAyIDIgNi40OCAyIDEyczQuNDggMTAgMTAgMTAgMTAtNC40OCAxMC0xMFMxNy41MiAyIDEyIDJ6bTEgMTVoLTJ2LTZoMnY2em0wLThoLTJWN2gydjJ6Ii8+PC9zdmc+'
        };

        class DebugConsole {


            constructor() {
                this.console = document.getElementById('debug-console');
                this.connectionStatus = document.getElementById('connection-status');
            }


            log(message, type = 'info') {
                const entry = document.createElement('div');
                entry.className = `log-entry log-${type}`;
                entry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
                this.console.appendChild(entry);
                this.console.scrollTop = this.console.scrollHeight;
            }

            logRawData(title, data) {
                const container = document.createElement('div');
                container.className = 'log-entry';

                const titleEl = document.createElement('div');
                titleEl.className = 'log-data';
                titleEl.textContent = `[${new Date().toLocaleTimeString()}] ${title}:`;

                const dataEl = document.createElement('div');
                dataEl.className = 'raw-data';
                dataEl.textContent = typeof data === 'object' ? JSON.stringify(data, null, 2) : data;

                container.appendChild(titleEl);
                container.appendChild(dataEl);
                this.console.appendChild(container);
                this.console.scrollTop = this.console.scrollHeight;
            }

            updateConnectionStatus(status, message) {
                this.connectionStatus.className = `status-${status}`;
                this.connectionStatus.textContent = message;
            }

            clear() {
                this.console.innerHTML = '';
            }
        }

        class AceStreamViewer {
            constructor() {
                this.PRIMARY_URL = 'https://api.codetabs.com/v1/proxy/?quest=https://www.arena4viewer.co.in/misguia2.php';
                this.BACKUP_URL = 'https://archive.org/download/abcd_20240416/Arena4view.txt';
                // this.USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';
                this.KEY = '';
                this.EXPIRE = '';
                this.debugConsole = new DebugConsole();
            }

            async checkConnection() {
                try {
                    this.debugConsole.updateConnectionStatus('connecting', 'Verificando conexión...');
                    this.debugConsole.log('Iniciando verificación de conexión...', 'info');

                    const response = await fetch('https://www.google.com', {
                        mode: 'no-cors'
                    });

                    this.debugConsole.updateConnectionStatus('connected', 'Conexión OK');
                    this.debugConsole.log('Conexión a Internet establecida', 'success');
                    return true;
                } catch (error) {
                    this.debugConsole.updateConnectionStatus('error', 'Sin conexión');
                    this.debugConsole.log('Error de conexión: ' + error.message, 'error');
                    return false;
                }
            }

            async obtenerEnlacesBackup() {
                try {
                    this.debugConsole.log('Intentando obtener enlaces desde URL de respaldo...', 'info');
                    const response = await fetch(this.BACKUP_URL);

                    if (!response.ok) {
                        throw new Error(`HTTP error! status: ${response.status}`);
                    }

                    const data = await response.text();
                    this.debugConsole.log('Enlaces de respaldo obtenidos correctamente', 'success');
                    this.debugConsole.logRawData('Enlaces de respaldo', data);

                    return data.split('\n').filter(line => line.trim());
                } catch (error) {
                    this.debugConsole.log('Error al obtener enlaces de respaldo: ' + error.message, 'error');
                    return [];
                }
            }

            async obtenerDatos() {
                try {
                    this.debugConsole.log('Intentando obtener datos del servidor principal...', 'info');

                    const response = await fetch(this.PRIMARY_URL, {
                        method: 'POST',
                        headers: {
                            'User-Agent': this.USER_AGENT,
                            'Connection': 'Keep-Alive',
                            'Content-Type': 'application/x-www-form-urlencoded'
                        },
                        body: new URLSearchParams({
                            key: this.KEY,
                            expire: this.EXPIRE
                        })
                    });

                    this.debugConsole.log(`Respuesta del servidor: ${response.status} ${response.statusText}`, 'info');

                    if (!response.ok) {
                        throw new Error(`HTTP error! status: ${response.status}`);
                    }

                    const data = await response.text();
                    this.debugConsole.log('Datos recibidos correctamente', 'success');
                    this.debugConsole.log('Longitud de la respuesta: ' + data.length + ' caracteres', 'info');
                    this.debugConsole.logRawData('Muestra de datos del servidor principal', data.substring(0, 500));

                    const processedData = await this.procesarDatos(data);

                    // Si no hay enlaces en los datos principales, intentar con el backup
                    if (!processedData.enlaces || processedData.enlaces.length === 0) {
                        this.debugConsole.log('No se encontraron enlaces en datos principales, usando respaldo', 'warning');
                        processedData.enlaces = await this.obtenerEnlacesBackup();
                    }

                    return processedData;
                } catch (error) {
                    this.debugConsole.log('Error al obtener datos principales: ' + error.message, 'error');

                    // En caso de error, intentar obtener al menos los enlaces del backup
                    const enlaces = await this.obtenerEnlacesBackup();
                    return { horarios: [], enlaces };
                }
            }

            procesarDatos(htmlContent) {
                this.debugConsole.log('Iniciando procesamiento de datos...', 'info');

                try {
                    const parser = new DOMParser();
                    const doc = parser.parseFromString(htmlContent, 'text/html');

                    // Procesar horarios
                    const horarios = Array.from(doc.querySelectorAll('tr'))
                        .map(tr => Array.from(tr.querySelectorAll('td.auto-style3'))
                            .map(td => td.textContent.trim())
                            .filter(text => text))
                        .filter(row => row.length);

                    this.debugConsole.log(`Encontrados ${horarios.length} horarios`, 'success');
                    this.debugConsole.logRawData('Horarios procesados', horarios);

                    // Procesar enlaces acestream
                    const streamDiv = doc.querySelector('div.streams');
                    const enlaces = streamDiv ? streamDiv.textContent.split(',') : [];

                    this.debugConsole.log(`Encontrados ${enlaces.length} enlaces en datos principales`, 'success');
                    this.debugConsole.logRawData('Enlaces principales', enlaces);

                    return { horarios, enlaces };
                } catch (error) {
                    this.debugConsole.log('Error al procesar datos: ' + error.message, 'error');
                    return null;
                }
            }

            // Método para traducir categoría y obtener icono
            procesarCategoria(categoria) {
                const categoriaOriginal = categoria.toUpperCase();
                const categoriaTraducida = CATEGORIAS[categoriaOriginal] || categoria;
                const icono = CATEGORY_ICONS[categoriaTraducida] || CATEGORY_ICONS['default'];

                return {
                    nombre: categoriaTraducida,
                    icono: icono
                };
            }

            actualizarTabla(datos) {
                if (!datos || !datos.horarios) {
                    this.debugConsole.log('No hay datos para actualizar la tabla', 'warning');
                    return;
                }

                this.debugConsole.log('Actualizando tabla con nuevos datos...', 'info');

                const tabla = document.getElementById('eventos-tabla');
                const tbody = tabla.querySelector('tbody');
                tbody.innerHTML = '';

                try {
                    const fechaActual = new Date();
                    fechaActual.setHours(0, 0, 0, 0);

                    let eventosAgregados = 0;

                    datos.horarios.forEach((evento, index) => {
                        const fechaEvento = this.parsearFecha(evento[0]);

                        if (fechaEvento >= fechaActual) {
                            const categoria = this.procesarCategoria(evento[2] || 'SPORTS');

                            const tr = document.createElement('tr');
                            tr.innerHTML = `
                    <td>${evento[0] || 'N/A'}</td>
                    <td>${evento[1] || 'N/A'}</td>
                    <td>
                        <img src="${categoria.icono}" class="category-icon" alt="${categoria.nombre}"><span>${categoria.nombre}</span>
                    </td>
                    <td>${evento[3] || 'N/A'}</td>
                    <td>${evento[4] || 'N/A'}</td>
                    <td>${this.generarEnlaces(evento[5], datos.enlaces, 'android')}</td>
                    <td>${this.generarEnlaces(evento[5], datos.enlaces, 'pc')}</td>
                `;
                            tbody.appendChild(tr);
                            eventosAgregados++;
                        }
                    });

                    // Si no hay eventos futuros, mostrar mensaje informativo
                    if (eventosAgregados === 0) {
                        const tr = document.createElement('tr');
                        tr.innerHTML = `
                <td colspan="7" style="text-align: center; padding: 20px;">
                    <div style="color: #ff33a8;">
                        <h3>¡No hay eventos programados! /⁠╲⁠/\⁠\\⁠╭⁠(⁠•⁠‿⁠•⁠)⁠╮⁠/⁠\\⁠╱⁠\\</h3>
                        <p>En este momento no hay eventos futuros disponibles.</p>
                        <p>La página se actualizará automáticamente cada 5 minutos.</p>
                        <p>¡Vuelve más tarde para ver los próximos eventos!</p>
                    </div>
                </td>
            `;
                        tbody.appendChild(tr);
                        this.debugConsole.log('No se encontraron eventos futuros', 'warning');
                    }

                    this.debugConsole.log(`Tabla actualizada. Se encontraron ${eventosAgregados} eventos futuros`, 'success');
                } catch (error) {
                    this.debugConsole.log('Error al actualizar tabla: ' + error.message, 'error');
                    const tr = document.createElement('tr');
                    tr.innerHTML = `
            <td colspan="7" style="text-align: center; padding: 20px;">
                <div style="color: #ff0000;">
                    <h3>¡Ups! Ha ocurrido un error</h3>
                    <p>No se han podido cargar los eventos correctamente.</p>
                    <p>Por favor, intenta recargar la página.</p>
                </div>
            </td>
        `;
                    tbody.appendChild(tr);
                }
            }

            // Añadir este método a la clase AceStreamViewer para parsear la fecha
            parsearFecha(fechaStr) {
                try {
                    // Suponiendo que la fecha viene en formato "DD/MM/YYYY"
                    const [dia, mes, año] = fechaStr.split('/').map(Number);
                    return new Date(año, mes - 1, dia); // mes - 1 porque en JavaScript los meses van de 0 a 11
                } catch (error) {
                    this.debugConsole.log(`Error al parsear fecha: ${fechaStr}`, 'error');
                    return new Date(0); // Fecha inválida
                }
            }


            generarEnlaces(numeros, enlaces, tipo) {
                if (!numeros) return 'Próximamente';
                if (!enlaces || enlaces.length === 0) return 'Sin enlaces disponibles';

                // Depuración inicial
                this.debugConsole.log(`Procesando números originales: ${numeros}`, 'info');

                // Limpiamos el string de cualquier texto adicional (como [SPA])
                const cleanNumeros = numeros.replace(/\s*\[.*?\]\s*/g, '').trim();
                this.debugConsole.log(`Números después de limpieza: ${cleanNumeros}`, 'info');

                // Dividimos por guiones y limpiamos cada número
                const nums = cleanNumeros.split('-').map(num => num.trim());
                this.debugConsole.log(`Array de números a procesar: ${JSON.stringify(nums)}`, 'info');

                return nums.map((num, i) => {
                    this.debugConsole.log(`Buscando enlace para número: ${num}`, 'info');

                    const link = enlaces.find(e => e.includes(`av${num}#`));
                    if (link) {
                        this.debugConsole.log(`Enlace encontrado para ${num}: ${link}`, 'success');
                        const aceLink = link.split('#')[1];
                        if (tipo === 'android') {
                            return `<a href="${aceLink}" title="${aceLink}" target="_blank" class="enlace-android">Enlace ${i + 1}</a>`;
                        } else {
                            const pcLink = `http://127.0.0.1:6878/server/api?method=open_in_player&player_id=&content_id=${aceLink.replace('acestream://', '')}`;
                            return `<a href="${pcLink}" title="${pcLink}" target="_blank" class="enlace-pc">Enlace ${i + 1}</a>`;
                        }
                    } else {
                        this.debugConsole.log(`No se encontró enlace para número ${num}`, 'warning');
                        return '';
                    }
                }).filter(Boolean).join('<br>') || 'Próximamente';
            }

        }

        function openInNewTab(url) {
            window.open(url, '_blank').focus();
        }

        // Inicialización
        document.addEventListener('DOMContentLoaded', async () => {
            const viewer = new AceStreamViewer();

            // Verificar conexión inicial
            if (await viewer.checkConnection()) {
                // Obtener datos iniciales
                const datos = await viewer.obtenerDatos();
                if (datos) {
                    viewer.actualizarTabla(datos);
                }

                // Actualizar datos cada 5 minutos
                setInterval(async () => {
                    if (await viewer.checkConnection()) {
                        const nuevoDatos = await viewer.obtenerDatos();
                        if (nuevoDatos) {
                            viewer.actualizarTabla(nuevoDatos);
                        }
                    }
                }, 300000);
            }
        });
    </script>
</body>

</html>