<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Server Progress</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        .progress-container {
            text-align: center;
            padding: 2rem;
            background-color: white;
            border-radius: 10px;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
        }
        .progress-bar {
            width: 100%;
            height: 20px;
            background-color: #f0f0f0;
            border-radius: 10px;
            margin: 1rem 0;
            overflow: hidden;
        }
        .progress-bar-fill {
            height: 100%;
            background-color: #4CAF50;
            width: 0%;
            transition: width 0.3s ease-in-out;
        }
        .progress-description {
            font-size: 1.2rem;
            color: #666;
            margin-bottom: 1rem;
        }
        .progress-message {
            font-size: 3rem;
            font-weight: bold;
            color: #333;
        }
        .elapsed-time {
            font-size: 1.2rem;
            color: #666;
            margin-top: 1rem;
        }
        .parameters {
            margin-bottom: 1rem;
        }
        .parameter {
            margin-bottom: 0.5rem;
        }
    </style>
</head>
<body>
    <div class="progress-container">
        <div class="progress-description">Your plan will be visible after it's generated.</div>
        <div class="progress-bar" id="progress-bar"></div>
        <div class="progress-message" id="progress-message"></div>
        <div class="elapsed-time" id="elapsed-time">Elapsed Time: 0:00</div>
    </div>

    <script>
        class PlanExeError extends Error {
            constructor(message) {
                super(message);
                this.name = 'PlanExeError';
            }
        }

        const progressMessageElement = document.getElementById('progress-message');
        const progressBarElement = document.getElementById('progress-bar');
        const elapsedTimeElement = document.getElementById('elapsed-time');
        const progressBarFill = document.createElement('div');
        progressBarFill.className = 'progress-bar-fill';
        progressBarElement.appendChild(progressBarFill);

        // Timer functionality
        const startTime = Date.now();
        
        function updateElapsedTime() {
            if (document.hidden) {
                return;
            }
            const elapsed = Date.now() - startTime;
            const minutes = Math.floor(elapsed / 60000);
            const seconds = Math.floor((elapsed % 60000) / 1000);
            elapsedTimeElement.textContent = `Elapsed Time: ${minutes}:${seconds.toString().padStart(2, '0')}`;
        }

        // Update elapsed time every second
        const timeInterval = setInterval(updateElapsedTime, 1000);
        const MAX_CONSECUTIVE_ERRORS = 5;
        let consecutive_error_count = 0;
        let schedule_next_do_nothing = false;

        function scheduleNext() {
            if (consecutive_error_count >= MAX_CONSECUTIVE_ERRORS) {
                console.error("Too many consecutive errors. Inspect the web console for more details. Stopped polling.");
                return;
            }
            if (schedule_next_do_nothing) {
                console.log("schedule_next_do_nothing is true. Skipping the next poll.");
                return;
            }
            let ms = 5_000;
            if (document.hidden) {
                ms = 60_000;
            } else if (consecutive_error_count > 0) {
                // simple back-off up to 60 s
                ms = Math.min(consecutive_error_count * 5_000, 60_000);
            }
            setTimeout(poll, ms);
        }
        
        function poll() {
            fetch(`/progress?plan_id={{ plan_id }}`, { cache: 'no-cache' })
                .then(response => {
                    console.log('Response status:', response.status);
                    console.log("Response headers:");
                    console.table(Array.from(response.headers.entries()));
                    console.log('Response URL:', response.url);                    
                    if (!response.ok) {
                        throw new PlanExeError(`HTTP error! status: ${response.status}`);
                    }
                    
                    return response.text(); // Get the raw text first
                })
                .then(text => {
                    console.log('Raw response text:', text);
                    console.log('Response text length:', text.length);
                    console.log('Response text type:', typeof text);
                    
                    // Check if response is empty
                    if (!text || text.trim() === '') {
                        console.error('Empty response from server');
                        throw new PlanExeError("Empty response from server");
                    }
                    
                    let data = {};
                    try {
                        data = JSON.parse(text);
                    } catch (parseError) {
                        console.error('JSON parse error:', parseError);
                        console.error('Response text that failed to parse:', text);
                        console.error('Response text as hex:', Array.from(text).map(c => c.charCodeAt(0).toString(16).padStart(2, '0')).join(' '));
                        throw new PlanExeError("Invalid JSON response from server");
                    }
                    console.log('Parsed JSON data:', JSON.stringify(data, null, 2));
                        
                    const is_completed = data.status == "completed";
                    const is_pending = data.status == "pending";
                    const is_processing = data.status == "processing";
                    const is_failed = data.status == "failed";
                    const is_stopped = data.status == "stopped";
                    progressMessageElement.textContent = data.progress_message || 'No progress message';

                    if (is_pending || is_processing || is_completed) {
                        // There is a connection with the server, so ignore past errors
                        consecutive_error_count = 0;
                    } else if (is_stopped) {
                        throw new PlanExeError("Plan stopped by user");
                    } else if (is_failed) {
                        throw new PlanExeError("Failed to generate plan");
                    } else {
                        throw new PlanExeError(`Unhandled status: ${data.status}`);
                    }
                    
                    // Update progress bar
                    if (data.progress_percentage !== undefined) {
                        progressBarFill.style.width = `${data.progress_percentage}%`;
                    }
                    
                    if (is_completed) {
                        // Clear the timers when completed
                        schedule_next_do_nothing = true;
                        // when the operation has completed redirect to the viewplan page
                        window.location.href = `/viewplan?plan_id={{ plan_id }}`;
                    }
                })
                .catch(error => {
                    console.error('Error checking progress:', error);
                    console.error('Error details:', {
                        name: error.name,
                        message: error.message,
                        consecutive_error_count: consecutive_error_count
                    });
                    
                    // Check if it's our custom error with human-readable message
                    if (error instanceof PlanExeError) {
                        progressMessageElement.textContent = error.message;
                    } else {
                        progressMessageElement.textContent = 'Unknown error, see console for details';
                    }
                    
                    consecutive_error_count++;
                })
                .finally(() => {
                    scheduleNext();
                });
        }

        // immediate catch-up when returning to the tab
        document.addEventListener('visibilitychange', () => {
          if (!document.hidden) poll();
        });

        // kick it off!
        poll();
    </script>
</body>
</html> 