<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cleonibus - VIP</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
    <script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/leaflet.markercluster@1.5.1/dist/leaflet.markercluster.js"></script>
    <style>
        @font-face {
            font-family: forque;
            src: url('Forque.ttf');
        }
        @font-face {
            font-family: sptrans;
            src: url('Ceritane-mLXx9.otf');
        }
        /* Estilo global */
        body {

            color: #ee2525; /* Texto escuro para melhor contraste */
            font-family: 'Courier New', Courier, monospace !important;
            margin: 0;
            padding: 0;
            line-height: 1.6;
            background-image: url('back.jpg');
            background-repeat: no-repeat;
            background-size: cover; /* Faz com que a imagem cubra todo o espaço */
            background-position: center; /* Centraliza a imagem */
        }
    
        /* Container central */
        .container {
            background: #06130226;
            padding: 30px;
            max-width: 800px;
            margin: 50px auto;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
        }
    
        /* Cabeçalho */
        h1 {
            font-size: 2.5rem;
            margin-bottom: 20px;
            text-align: center;
            color: #2c3e50;
            font-weight: 700;
        }
    
        h1 span {
            color: #afafaff2;
            font-family: 'Courier New', Courier, monospace !important;
        }
    
        /* Input e rótulos */
        .form-label {
            font-size: 1rem;
            color: #fff;
            margin-bottom: 8px;
            display: block;
            font-weight: 500;
        }
    
        .form-control {
            width: 100%;
            padding: 12px;
            font-size: 1rem;
            border: 1px solid #ddd;
            border-radius: 8px;
            background: #f9f9f9;
            color: #e74c3c;
            transition: all 0.3s;
        }
    
        .form-control:focus {
            border-color: #3498db;
            outline: none;
            box-shadow: 0 0 5px rgba(52, 152, 219, 0.5);
        }
    
        /* Botão */
        .btn-primary {
            background-color: #3498db;
            color: #fff;
            border: none;
            border-radius: 8px;
            font-size: 1.1rem;
            padding: 12px 20px;
            cursor: pointer;
            display: inline-block;
            width: 100%;
            max-width: 200px;
            margin: 20px auto;
            text-align: center;
            transition: all 0.3s ease;
        }
    
        .btn-primary:hover {
            background-color: #2980b9;
            transform: translateY(-2px);
        }
    
        /* Mapa */
        #map {
            width: 100%;
            height: 700px;
            margin-top: 20px;
            border: 1px solid #ddd;
        }
    
        /* Lista de ônibus */
        #busList {
            font-size: 1rem;
            color: #d34242;
            margin-top: 20px;
        }
    
        /* Categorias de ônibus */
        .bus-approaching {
            color: #2ecc71;
            font-weight: 600;
        }
    
        .bus-moving-away {
            color: #e74c3c;
            font-weight: 600;
        }
    
        .bus-stationary {
            color: #f1c40f;
            font-weight: 600;
        }
    
        /* Rodapé */
        footer {
            text-align: center;
            padding: 20px 0;
            background-color: #111d28;
            color: #ecf0f1;
            font-size: 0.9rem;
            margin-top: 50px;
            border-radius: 0 0 12px 12px;
        }
    
        footer p {
            margin: 5px 0;
        }
    
        footer a {
            color: #e74c3c;
            text-decoration: none;
            font-weight: 600;
        }
    
        footer a:hover {
            text-decoration: underline;
        }
    
        footer img {
            max-height: 60px;
            margin-top: 15px;
            opacity: 0.85;
        }
    
        /* Responsividade */
        @media (max-width: 768px) {
            .container {
                padding: 20px;
            }
    
            h1 {
                font-size: 2rem;
            }
    
            .btn-primary {
                font-size: 1rem;
            }
    
            .form-control {
                font-size: 1rem;
            }
        }
    </style>
    
    
    <body>
        <header style="background-color: #13090991; color: white; padding: 15px 20px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);">
            <div style="display: flex; justify-content: space-between; align-items: center; display: flex !important; flex-direction: column;">
                <!-- Nome da empresa com fonte estilizada -->
                <h1 style="font-family: 'Courier New', Courier, monospace !important; font-size: 24px; font-weight: 400; margin: 0; color: white !important;">
                    Cleonibus   -    <span style="font-size: small; font-family: 'Courier New', Courier, monospace !important;">Por Julio Stravino</span>
                </h1>
                <!-- Descrição ao lado -->
                <p style="font-family: 'Courier New', Courier, monospace !important; font-size: 16px; color: #7f8c8d; margin: 0;">
                    Localização de ônibus em tempo real
                </p>
            </div>
        </header>

        <div class="container">
            <h1 style="font-size: 2em; color: #fff; text-align: center; font-family: 'Courier New', Courier, monospace !important;">
                <span style="font-size: 1.2em !important; color: #d4d4d4; font-family: 'Courier New', Courier, monospace !important;"></span><br>Rastreamento de Ônibus em Tempo Real
            </h1>
            
                        <div class="mb-3">
                <label for="busNumber" class="form-label">Digite o número da linha:</label>
                <input type="text" id="busNumber" class="form-control" placeholder="ex.: 407G." maxlength="4" required>
            </div>
            <button id="searchBus" class="btn btn-secondary" style="color: greenyellow !important;">Buscar</button>
            <button id="recomecar" class="btn btn-secondary" onclick="atualizarPagina()">Recomeçar</button>
            <div id="busList" class="mt-4"></div>
            <div id="map"></div>
            <div id="busLocations" class="mt-4"></div>
        </div>
    
        <footer>
            <p>Desenvolvido por <strong style="color: red !important;">Julio Stravino - 2024</strong> | Utilizando a API da <strong>SPTrans</strong> para informações em tempo real sobre ônibus na cidade de São Paulo.</p>
            <p>Saiba mais sobre meus projetos em <a href="https://juliostravino.netlify.app" target="_blank">meu site</a>.</p>
            <img src="sptrans.png" alt="Logo da SPTrans" style="max-height: 90px; margin-top: 10px;">
        </footer>
        

    <script>
        let currentZoom = 14;  // Armazenar o nível de zoom atual
        let currentCenter = [0, 0];  // Armazenar a posição central atual
        let notifiedBuses = new Set(); // Conjunto para rastrear ônibus que já notificaram
        let previousDistances = {}; // Objeto para armazenar as distâncias anteriores
        let isMapInitialized = false; // Variável para verificar se o mapa já foi inicializado
        let map, userMarker, busMarkers = [];
        let userCoords = null;
        const busDistances = new Map();
        let iniciado = 0;

        async function fetchBusData(busNumber) {
            const url = `https://corsproxy.io/?url=${encodeURIComponent('https://www.expertsubjects.com/members/bus.php?termosBusca=' + busNumber)}&cache_bust=${new Date().getTime()}`;
            try {
                const response = await fetch(url);
                const text = await response.text();
                const jsonStart = text.indexOf('[');
                const jsonEnd = text.lastIndexOf(']') + 1;
                if (jsonStart === -1 || jsonEnd === -1) {
                    throw new Error('Formato de resposta inválido.');
                }
                const busData = JSON.parse(text.substring(jsonStart, jsonEnd));
                return busData;
            } catch (err) {
                alert('Erro ao buscar dados dos ônibus: ' + err.message);
            }
        }

        async function getBusLocation(cl) {
            const url = `https://corsproxy.io/?url=${encodeURIComponent('https://www.expertsubjects.com/members/bus.php?sentidoLinha=' + cl)}&cache_bust=${new Date().getTime()}`;
            try {
                const response = await fetch(url);
                const text = await response.text();
                const jsonStart = text.indexOf('"vs":[');
                const jsonEnd = text.lastIndexOf(']}') + 1;
                if (jsonStart === -1 || jsonEnd === -1) {
                    throw new Error('Formato de resposta inválido.');
                }
                const busLocationData = JSON.parse('{' + text.substring(jsonStart, jsonEnd) + '}');
                const buses = busLocationData.vs || [];

                const busLocationsDiv = document.getElementById('busLocations');
                busLocationsDiv.innerHTML = `<p><strong>Ônibus em operação: ${buses.length}</strong></p><br><br><span>A estimativa de tempo de chegada abaixo é uma previsão baseada em cálculos matemáticos de distância longitudinal. Utilize o mapa acima para verificar a localização atual do ônibus e realize seu próprio cálculo do tempo estimado de chegada com base nessa posição.</span>`;

                buses.forEach(bus => {
                    const currentDistance = calculateDistance(userCoords.latitude, userCoords.longitude, bus.py, bus.px);
                    const previousDistance = busDistances.get(bus.p) || currentDistance;

                    let status = 'Parado';
                    let statusClass = 'bus-stationary';

                    if (currentDistance < previousDistance) {
                        status = 'Aproximando';
                        statusClass = 'bus-approaching';
                    } else if (currentDistance > previousDistance) {
                        status = 'Afastando';
                        statusClass = 'bus-moving-away';
                    }

                    const estimatedTime = calculateEstimatedTime(previousDistance, currentDistance);
                    busDistances.set(bus.p, currentDistance);

                    const busInfo = document.createElement('p');
                    busInfo.className = statusClass;
                    busInfo.style.color = 'white';
                    busInfo.innerText = `Ônibus [${bus.p}] - Latitude: ${bus.py}, Longitude: ${bus.px}, Status: ${status}, Estimativa de chegada: ${estimatedTime} min`;
                    busLocationsDiv.appendChild(busInfo);
                });

                setTimeout(() => getBusLocation(cl), 2000); // VIP
            } catch (err) {
                alert('Erro ao buscar localização dos ônibus: ' + err.message);
            }
        }

        function calculateDistance(lat1, lon1, lat2, lon2) {
            const R = 6371; // Raio da Terra em km
            const dLat = (lat2 - lat1) * Math.PI / 180;
            const dLon = (lon2 - lon1) * Math.PI / 180;
            const a =
                Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
                Math.sin(dLon / 2) * Math.sin(dLon / 2);
            const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
            return R * c * 1000; // Distância em metros
        }

        function calculateEstimatedTime(previousDistance, currentDistance) {
            const speed = Math.abs(previousDistance - currentDistance) / 15; // m/s (assume atualizações a cada 15 segundos)
            return speed > 0 ? Math.ceil(currentDistance / speed / 60) : 'Indisponível';
        }

        async function getUserLocation() {
            return new Promise((resolve, reject) => {
                if (navigator.geolocation) {
                    navigator.geolocation.getCurrentPosition(
                        position => {
                            resolve({
                                latitude: position.coords.latitude,
                                longitude: position.coords.longitude
                            });
                        },
                        error => reject(error)
                    );
                } else {
                    reject(new Error('Geolocalização não foi encontrada.'));
                }
            });
        }

        document.getElementById('searchBus').addEventListener('click', async () => {
            const busNumber = document.getElementById('busNumber').value;
            const busListDiv = document.getElementById('busList');
            busListDiv.innerHTML = '';

            if (busNumber.length < 4) {
                // A variável busNumber tem menos de 4 caracteres
                document.getElementById('busNumber').value = '';  // Limpa o campo
                alert('Por favor, preencha o número do ônibus com pelo menos 4 caracteres.');
                
                // Atualiza a página forçadamente
                return;
            }

            if (iniciado != 0){
                atualizarPagina();
            }

            try {
                userCoords = await getUserLocation();
                const userLocationDiv = document.createElement('p');
                userLocationDiv.innerText = `Sua localização: Latitude: ${userCoords.latitude}, Longitude: ${userCoords.longitude}`;
                document.getElementById('busList').appendChild(userLocationDiv);

                const busData = await fetchBusData(busNumber);
                if (busData) {
    busData.forEach(bus => {
        const routeName = bus.sl === 1 ? bus.tp : bus.ts; // Define o sentido da rota
        const busOption = document.createElement('button');
        busOption.className = 'btn btn-secondary mb-2';
        busOption.innerText = `Sentido: ${routeName}`;

        // Aqui chamamos tanto getBusLocation quanto mapa, mas verificando se mapa existe
        busOption.onclick = () => {
            getBusLocation(bus.cl);  // Mantém a função que já estava
            
            // Verifica se a função 'mapa' está definida antes de chamá-la
            if (typeof mapa === 'function') {
                mapa();  // Chama a função mapa se ela estiver definida
            } else {
                console.warn('Função "mapa" não está definida.');
            }
        };

        busListDiv.appendChild(busOption);
    });
}
            } catch (err) {
                alert('Erro ao obter localização do usuário: ' + err.message);
            }
        });


        function mapa() {
    const mapContainer = document.getElementById('map');
    mapContainer.style.display = 'block';

    let hasZoomedToUser = false; // Flag para controlar o zoom inicial

    document.querySelector('#busList').style.display = "none";

    // Inicializar o mapa apenas uma vez
    if (!map) {
        map = L.map('map').setView([0, 0], 2);
        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);

        // Tentar obter a localização do usuário ao carregar o mapa
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(
                position => {
                    const userLat = position.coords.latitude;
                    const userLng = position.coords.longitude;

                    // Centralizar e dar zoom na posição do usuário uma única vez
                    if (!hasZoomedToUser) {
                        map.setView([userLat, userLng], 15);
                        hasZoomedToUser = true;

                        // Adicionar marcador do usuário imediatamente, se necessário
                        if (!userMarker) {
                            const userIcon = L.icon({
                                iconUrl: 'usuario.png',
                                iconSize: [32, 32],
                                iconAnchor: [16, 32],
                                popupAnchor: [0, -32],
                            });
                            userMarker = L.marker([userLat, userLng], { icon: userIcon })
                                .bindPopup(`Você está aqui: ${userLat}, ${userLng}`)
                                .addTo(map);
                        }
                    }
                },
                error => {
                    console.error("Erro ao obter localização do usuário:", error);
                }
            );
        } else {
            console.error("Geolocalização não é suportada neste navegador.");
        }
    }

    const userIcon = L.icon({
        iconUrl: 'usuario.png',
        iconSize: [32, 32],
        iconAnchor: [16, 32],
        popupAnchor: [0, -32],
    });

    const busIcon = L.icon({
        iconUrl: 'onibus.png',
        iconSize: [35, 35],
        iconAnchor: [16, 32],
        popupAnchor: [0, -32],
    });

    let busCircles = []; // Lista para armazenar os círculos

    function updateMarkers() {
        // Salvar o centro e o zoom atuais do mapa
        const currentCenter = map.getCenter();
        const currentZoom = map.getZoom();

        // Atualizar posição do usuário
        const userLocationElement = document.querySelector('#busList > p');
        if (userLocationElement) {
            const match = userLocationElement.textContent.match(/Latitude:\s*(-?\d+\.\d+),\s*Longitude:\s*(-?\d+\.\d+)/);
            if (match) {
                const [_, lat, lng] = match;
                const userLatLng = [parseFloat(lat), parseFloat(lng)];
                if (userMarker) {
                    userMarker.setLatLng(userLatLng);
                } else {
                    userMarker = L.marker(userLatLng, { icon: userIcon })
                        .bindPopup(`Você está aqui: ${lat}, ${lng}`).addTo(map);
                }
            }
        }

        // Atualizar posições dos ônibus
        const busLocationElements = document.querySelectorAll('#busLocations > p');
        const newBusMarkers = [];
        const newBusCircles = [];

        busLocationElements.forEach(busElement => {
            const match = busElement.textContent.match(/Latitude:\s*(-?\d+\.\d+),\s*Longitude:\s*(-?\d+\.\d+)/);
            if (match) {
                const [_, lat, lng] = match;
                const busLatLng = [parseFloat(lat), parseFloat(lng)];

                // Adicionar marcador do ônibus
                const busMarker = L.marker(busLatLng, { icon: busIcon })
                    .bindPopup(`Ônibus: ${lat}, ${lng}`);
                newBusMarkers.push(busMarker);

                // Adicionar círculo ao redor do ônibus
                const busCircle = L.circle(busLatLng, {
                    color: 'red',
                    fillColor: 'yellowgreen',
                    fillOpacity: 0.3,
                    radius: 200, // Raio em metros
                });
                newBusCircles.push(busCircle);
            }
        });

        // Remover marcadores e círculos antigos
        busMarkers.forEach(marker => map.removeLayer(marker));
        busCircles.forEach(circle => map.removeLayer(circle));

        // Adicionar novos marcadores e círculos
        newBusMarkers.forEach(marker => marker.addTo(map));
        newBusCircles.forEach(circle => circle.addTo(map));

        // Atualizar listas
        busMarkers = newBusMarkers;
        busCircles = newBusCircles;

        // Restaurar o centro e o zoom do mapa
        map.setView(currentCenter, currentZoom);
    }

    // Atualizar marcadores a cada 8 segundos
    setInterval(updateMarkers, 500);
    iniciado = 1;
    updateMarkers(); // Atualizar imediatamente na inicialização
}
function atualizarPagina() {
    location.reload(true);
}


    </script>
  
</body>
</html>
