#!/usr/bin/env python3
"""
BB10 RocketChat Navigator
A BlackBerry 10 optimized web application for navigating RocketChat private groups and direct messages.
Follows BB10 development standards and conventions.
"""
import http.server
import socketserver
import json
import os
import sys
import urllib.request
import urllib.parse
import ssl
import time
import threading
import socket
import subprocess
import tempfile

PORT = 8026
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
CONFIG_FILE_PATH = os.path.join(BASE_DIR, '.env')

# Embedded HTML content (BB10 standard - single file deployment)
HTML_CONTENT = '''<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="initial-scale=1, user-scalable=no">
    <title>RocketChat Navigator - BB10</title>
    <style>
        /* BB10 Standard Theme */
        body {
            background-color: #1e1e1e;
            color: white;
            font-family: "Slate Pro", Slate, "Myriad Pro", Helvetica, Arial, sans-serif;
            font-size: 12pt;
            margin: 0;
            padding: 0;
            overflow-x: hidden;
        }
        
        .header {
            background-color: #2b2b2b;
            border-bottom: 2px solid #00769e;
            padding: 15px;
            position: relative;
            box-shadow: 0 2px 4px rgba(0,0,0,0.3);
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        
        .header h1 {
            margin: 0;
            font-size: 16pt;
            font-weight: normal;
            flex: 1;
            text-align: center;
        }
        
        .header-right {
            display: flex;
            align-items: center;
            gap: 20px;
            position: relative;
        }
        
        .settings-icon {
            font-size: 18px;
            cursor: pointer;
            padding: 8px;
            border-radius: 3px;
            transition: background-color 0.2s;
            color: white;
            margin-right: 10px;
        }
        
        .settings-icon:hover {
            background-color: rgba(255, 255, 255, 0.1);
        }
        
        .status-indicator {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            background-color: #666;
        }
        
        .status-indicator.connected {
            background-color: #4CAF50;
        }
        
        .status-indicator.error {
            background-color: #f44336;
        }
        
        
        /* Navigation Tabs */
        .nav-tabs {
            display: flex;
            background-color: #2b2b2b;
            border-bottom: 1px solid #444;
        }
        
        .nav-tab {
            flex: 1;
            padding: 12px 8px;
            text-align: center;
            background-color: #2b2b2b;
            color: #ccc;
            border: none;
            cursor: pointer;
            font-size: 11pt;
            border-right: 1px solid #444;
        }
        
        .nav-tab:last-child {
            border-right: none;
        }
        
        .nav-tab.active {
            background-color: #00769e;
            color: white;
        }
        
        .nav-tab:hover {
            background-color: #005f7a;
        }
        
        /* Content Area */
        .content {
            padding: 10px;
            height: calc(100vh - 140px);
            overflow-y: auto;
        }
        
        .tab-content {
            display: none;
        }
        
        .tab-content.active {
            display: block;
        }
        
        /* Room List */
        .room-list {
            list-style: none;
            padding: 0;
            margin: 0;
        }
        
        .room-item {
            background-color: #2b2b2b;
            border: 1px solid #444;
            border-radius: 4px;
            margin-bottom: 8px;
            padding: 12px;
            cursor: pointer;
            transition: background-color 0.2s;
        }
        
        .room-item:hover {
            background-color: #3b3b3b;
        }
        
        .room-item.selected {
            background-color: #00769e;
            border-color: #0099cc;
        }
        
        .room-name {
            font-weight: bold;
            font-size: 13pt;
            margin-bottom: 4px;
        }
        
        .room-type {
            font-size: 10pt;
            color: #aaa;
        }
        
        /* Messages */
        .messages-container {
            background-color: #2b2b2b;
            border: 1px solid #444;
            border-radius: 4px;
            height: 300px;
            overflow-y: auto;
            padding: 10px;
            margin-bottom: 10px;
        }
        
        .message-item {
            margin-bottom: 10px;
            padding-bottom: 8px;
            border-bottom: 1px solid #444;
        }
        
        .message-item:last-child {
            border-bottom: none;
        }
        
        .message-header {
            font-size: 10pt;
            color: #aaa;
            margin-bottom: 4px;
        }
        
        .message-username {
            color: #00769e;
            font-weight: bold;
        }
        
        .message-time {
            float: right;
        }
        
        .message-text {
            font-size: 11pt;
            line-height: 1.4;
        }
        
        /* Input Area */
        .input-area {
            display: flex;
            gap: 8px;
            margin-top: 10px;
        }
        
        .message-input {
            flex: 1;
            padding: 10px;
            background-color: #2b2b2b;
            border: 1px solid #444;
            border-radius: 4px;
            color: white;
            font-size: 11pt;
        }
        
        .message-input:focus {
            outline: none;
            border-color: #00769e;
        }
        
        /* Buttons */
        .btn {
            padding: 10px 16px;
            background-color: #00769e;
            color: white;
            border: none;
            border-radius: 4px;
            font-size: 11pt;
            cursor: pointer;
            transition: background-color 0.2s;
        }
        
        .btn:hover {
            background-color: #005f7a;
        }
        
        .btn:active {
            transform: scale(0.98);
        }
        
        .btn-small {
            padding: 6px 12px;
            font-size: 10pt;
        }
        
        /* Loading and Status */
        .loading {
            text-align: center;
            padding: 20px;
            color: #aaa;
        }
        
        .error-message {
            background-color: #f44336;
            color: white;
            padding: 10px;
            border-radius: 4px;
            margin-bottom: 10px;
        }
        
        .success-message {
            background-color: #4CAF50;
            color: white;
            padding: 10px;
            border-radius: 4px;
            margin-bottom: 10px;
        }
        
        /* Config Form */
        .config-form {
            background-color: #2b2b2b;
            border: 1px solid #444;
            border-radius: 4px;
            padding: 15px;
        }
        
        .form-group {
            margin-bottom: 15px;
        }
        
        .form-label {
            display: block;
            margin-bottom: 5px;
            font-size: 11pt;
            color: #ccc;
        }
        
        .form-input {
            width: 100%;
            padding: 8px;
            background-color: #1e1e1e;
            border: 1px solid #444;
            border-radius: 4px;
            color: white;
            font-size: 11pt;
            box-sizing: border-box;
        }
        
        .form-input:focus {
            outline: none;
            border-color: #00769e;
        }
        
        /* Responsive adjustments for BlackBerry Passport */
        @media (max-width: 480px) {
            .header h1 {
                font-size: 14pt;
            }
            
            .nav-tab {
                font-size: 10pt;
                padding: 10px 6px;
            }
            
            .content {
                padding: 8px;
            }
            
            .room-item {
                padding: 10px;
            }
            
            .messages-container {
                height: 250px;
            }
        }
    </style>
</head>
<body>
    <div class="header">
        <h1>Rocket Chat</h1>
        <div class="header-right">
            <div class="settings-icon" id="settingsIcon" onclick="showTab('settings')">⚙️</div>
            <div class="status-indicator" id="statusIndicator"></div>
        </div>
    </div>
    
    
    <div class="nav-tabs">
        <button class="nav-tab active" onclick="showTab('private-groups')">Private Groups</button>
        <button class="nav-tab" onclick="showTab('direct-messages')">Direct Messages</button>
        <button class="nav-tab" onclick="showTab('send-message')">Send Message</button>
        <button class="nav-tab" onclick="showTab('settings')">Settings</button>
    </div>
    
    <div class="content">
        <!-- Private Groups Tab -->
        <div id="private-groups" class="tab-content active">
            <div id="privateGroupsStatus"></div>
            <ul class="room-list" id="privateGroupsList">
                <li class="loading">Loading private groups...</li>
            </ul>
            
            <div id="privateGroupMessages" style="display: none;">
                <h3 id="selectedPrivateGroupName">Group Messages</h3>
                <div class="messages-container" id="privateGroupMessagesContainer"></div>
                <div class="input-area">
                    <input type="text" class="message-input" id="privateGroupMessageInput" placeholder="Type your message...">
                    <button class="btn" onclick="sendPrivateGroupMessage()">Send</button>
                </div>
            </div>
        </div>
        
        <!-- Direct Messages Tab -->
        <div id="direct-messages" class="tab-content">
            <div id="directMessagesStatus"></div>
            <ul class="room-list" id="directMessagesList">
                <li class="loading">Loading direct messages...</li>
            </ul>
            
            <div id="directMessageMessages" style="display: none;">
                <h3 id="selectedDirectMessageName">Direct Messages</h3>
                <div class="messages-container" id="directMessageMessagesContainer"></div>
                <div class="input-area">
                    <input type="text" class="message-input" id="directMessageMessageInput" placeholder="Type your message...">
                    <button class="btn" onclick="sendDirectMessage()">Send</button>
                </div>
            </div>
        </div>
        
        <!-- Send Message Tab -->
        <div id="send-message" class="tab-content">
            <div id="sendMessageStatus"></div>
            <div class="send-message-form">
                <h3>Send New Message</h3>
                
                <div class="form-group">
                    <label class="form-label">Message Type:</label>
                    <select class="form-input" id="messageType" onchange="updateRecipientOptions()">
                        <option value="dm">Direct Message</option>
                        <option value="group">Private Group</option>
                    </select>
                </div>
                
                <div class="form-group">
                    <label class="form-label">Recipient:</label>
                    <select class="form-input" id="recipientSelect">
                        <option value="">Select recipient...</option>
                    </select>
                </div>
                
                <div class="form-group">
                    <label class="form-label">Message:</label>
                    <textarea class="form-input" id="newMessageText" placeholder="Type your message here..." rows="4"></textarea>
                </div>
                
                <div class="form-group">
                    <button class="btn" onclick="sendNewMessage()">Send Message</button>
                </div>
            </div>
        </div>
        
        <!-- Settings Tab -->
        <div id="settings" class="tab-content">
            <div id="configStatus"></div>
            
            <!-- Login Form (Easy Setup) -->
            <div class="config-form" id="loginForm">
                <h3>🚀 Quick Setup - Login with Credentials</h3>
                <p style="color: #aaa; font-size: 11pt; margin-bottom: 15px;">Enter your RocketChat login details and we'll automatically get your tokens.</p>
                
                <div class="form-group">
                    <label class="form-label">Server URL:</label>
                    <input type="text" class="form-input" id="serverUrlLogin" placeholder="https://your-rocket-chat.com">
                </div>
                
                <div class="form-group">
                    <label class="form-label">Username or Email:</label>
                    <input type="text" class="form-input" id="usernameLogin" placeholder="your-username or email@example.com">
                </div>
                
                <div class="form-group">
                    <label class="form-label">Password:</label>
                    <input type="password" class="form-input" id="passwordLogin" placeholder="Your password">
                </div>
                
                <div class="form-group">
                    <button class="btn" onclick="loginAndSaveConfig()">🔐 Login & Save Configuration</button>
                    <button class="btn btn-small" onclick="showManualConfig()" style="margin-left: 10px;">Manual Setup</button>
                </div>
            </div>
            
            <!-- Manual Configuration Form (Advanced) -->
            <div class="config-form" id="manualForm" style="display: none;">
                <h3>⚙️ Manual Configuration</h3>
                <p style="color: #aaa; font-size: 11pt; margin-bottom: 15px;">For advanced users who already have their tokens.</p>
                
                <div class="form-group">
                    <label class="form-label">Server URL:</label>
                    <input type="text" class="form-input" id="serverUrlTab" placeholder="https://your-rocket-chat.com">
                </div>
                
                <div class="form-group">
                    <label class="form-label">Auth Token:</label>
                    <input type="password" class="form-input" id="authTokenTab" placeholder="Your authentication token">
                </div>
                
                <div class="form-group">
                    <label class="form-label">User ID:</label>
                    <input type="text" class="form-input" id="userIdTab" placeholder="Your user ID">
                </div>
                
                <div class="form-group">
                    <button class="btn" onclick="saveConfigFromTab()">Save Configuration</button>
                    <button class="btn btn-small" onclick="testConnection()" style="margin-left: 10px;">Test Connection</button>
                    <button class="btn btn-small" onclick="showLoginForm()" style="margin-left: 10px;">Back to Login</button>
                </div>
            </div>
        </div>
    </div>

    <script>
        // ES5 Compatible JavaScript for BlackBerry Passport
        
        // Global state
        var currentTab = 'private-groups';
        var selectedRoom = null;
        var privateGroups = [];
        var directMessages = [];
        var connectionStatus = false;
        
        // ES5 Compatible AJAX function (replaces fetch)
        function makeRequest(method, url, data, onSuccess, onError) {
            var xhr = new XMLHttpRequest();
            
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {
                        try {
                            var responseData = JSON.parse(xhr.responseText);
                            if (onSuccess) onSuccess(responseData);
                        } catch (e) {
                            if (onError) onError(e);
                        }
                    } else {
                        if (onError) onError(new Error('HTTP ' + xhr.status + ': ' + xhr.statusText));
                    }
                }
            };
            
            xhr.open(method, url, true);
            
            if (method === 'POST' && data) {
                xhr.setRequestHeader('Content-Type', 'application/json');
                xhr.send(JSON.stringify(data));
            } else {
                xhr.send();
            }
        }
        
        // Initialize app
        function initApp() {
            console.log('Initializing BB10 RocketChat Navigator...');
            checkConnectionStatus();
            loadConfiguration();
            loadRooms();
            
            // Set up periodic refresh - less frequent for speed
            setInterval(function() {
                if (connectionStatus) {
                    refreshCurrentView();
                }
            }, 60000); // Refresh every 60 seconds (less frequent)
        }
        
        // Load current config for settings tab
        function loadCurrentConfigForTab() {
            makeRequest('GET', '/api/config', null, function(data) {
                if (data.RCSERVER) {
                    document.getElementById('serverUrlTab').value = data.RCSERVER;
                }
                if (data.RCTOKEN) {
                    document.getElementById('authTokenTab').value = data.RCTOKEN;
                }
                if (data.RCID) {
                    document.getElementById('userIdTab').value = data.RCID;
                }
            }, function(error) {
                console.log('Could not load config:', error);
            });
        }
        
        // Login with credentials and auto-save config
        function loginAndSaveConfig() {
            var serverUrl = document.getElementById('serverUrlLogin').value.trim();
            var username = document.getElementById('usernameLogin').value.trim();
            var password = document.getElementById('passwordLogin').value.trim();
            var statusDiv = document.getElementById('configStatus');
            
            if (!serverUrl || !username || !password) {
                statusDiv.innerHTML = '<div class="error-message">Please fill in all fields</div>';
                return;
            }
            
            statusDiv.innerHTML = '<div class="loading">🔐 Logging in to RocketChat...</div>';
            
            var loginData = {
                server_url: serverUrl,
                username: username,
                password: password
            };
            
            makeRequest('POST', '/api/login', loginData, function(response) {
                if (response.status === 'success') {
                    statusDiv.innerHTML = '<div class="success-message">✅ Login successful! Configuration saved.</div>';
                    
                    // Clear password field for security
                    document.getElementById('passwordLogin').value = '';
                    
                    // Refresh connection status
                    setTimeout(function() {
                        checkConnectionStatus();
                        statusDiv.innerHTML = '';
                    }, 3000);
                } else {
                    statusDiv.innerHTML = '<div class="error-message">❌ Login failed: ' + (response.message || 'Unknown error') + '</div>';
                }
            }, function(error) {
                statusDiv.innerHTML = '<div class="error-message">❌ Network error: ' + error.message + '</div>';
            });
        }
        
        // Show/hide form sections
        function showManualConfig() {
            document.getElementById('loginForm').style.display = 'none';
            document.getElementById('manualForm').style.display = 'block';
        }
        
        function showLoginForm() {
            document.getElementById('manualForm').style.display = 'none';
            document.getElementById('loginForm').style.display = 'block';
        }

        // Save config from settings tab (manual method)
        function saveConfigFromTab() {
            var serverUrl = document.getElementById('serverUrlTab').value.trim();
            var authToken = document.getElementById('authTokenTab').value.trim();
            var userId = document.getElementById('userIdTab').value.trim();
            var statusDiv = document.getElementById('configStatus');
            
            if (!serverUrl || !authToken || !userId) {
                statusDiv.innerHTML = '<div class="error-message">Please fill in all fields</div>';
                return;
            }
            
            statusDiv.innerHTML = '<div class="loading">Saving configuration...</div>';
            
            var configData = {
                RCSERVER: serverUrl,
                RCTOKEN: authToken,
                RCID: userId
            };
            
            makeRequest('POST', '/api/save_config', configData, function(response) {
                if (response.status === 'success') {
                    statusDiv.innerHTML = '<div class="success-message">Configuration saved successfully!</div>';
                    // Refresh connection status
                    setTimeout(function() {
                        checkConnectionStatus();
                        statusDiv.innerHTML = '';
                    }, 2000);
                } else {
                    statusDiv.innerHTML = '<div class="error-message">Failed to save: ' + (response.message || 'Unknown error') + '</div>';
                }
            }, function(error) {
                statusDiv.innerHTML = '<div class="error-message">Network error: ' + error.message + '</div>';
            });
        }
        
        // Update recipient options based on message type
        function updateRecipientOptions() {
            var messageType = document.getElementById('messageType').value;
            var recipientSelect = document.getElementById('recipientSelect');
            
            // Clear existing options
            recipientSelect.innerHTML = '<option value="">Select recipient...</option>';
            
            if (messageType === 'dm') {
                // Add direct message contacts
                for (var i = 0; i < directMessages.length; i++) {
                    var dm = directMessages[i];
                    var option = document.createElement('option');
                    option.value = dm.id;
                    option.textContent = dm.display || dm.name || 'Unknown';
                    recipientSelect.appendChild(option);
                }
            } else if (messageType === 'group') {
                // Add private groups
                for (var i = 0; i < privateGroups.length; i++) {
                    var group = privateGroups[i];
                    var option = document.createElement('option');
                    option.value = group.id;
                    option.textContent = group.name || 'Unknown Group';
                    recipientSelect.appendChild(option);
                }
            }
        }
        
        // Send new message function
        function sendNewMessage() {
            var messageType = document.getElementById('messageType').value;
            var recipientId = document.getElementById('recipientSelect').value;
            var messageText = document.getElementById('newMessageText').value;
            var statusDiv = document.getElementById('sendMessageStatus');
            
            if (!recipientId) {
                statusDiv.innerHTML = '<div class="error">Please select a recipient</div>';
                return;
            }
            
            if (!messageText.trim()) {
                statusDiv.innerHTML = '<div class="error">Please enter a message</div>';
                return;
            }
            
            statusDiv.innerHTML = '<div class="loading">Sending message...</div>';
            
            var endpoint = messageType === 'dm' ? '/api/send-dm' : '/api/send-group-message';
            var data = {
                roomId: recipientId,
                message: messageText.trim()
            };
            
            makeRequest('POST', endpoint, data, function(response) {
                if (response.success) {
                    statusDiv.innerHTML = '<div class="success">Message sent successfully!</div>';
                    document.getElementById('newMessageText').value = '';
                    
                    // Clear status after 3 seconds
                    setTimeout(function() {
                        statusDiv.innerHTML = '';
                    }, 3000);
                } else {
                    statusDiv.innerHTML = '<div class="error">Failed to send message: ' + (response.error || 'Unknown error') + '</div>';
                }
            }, function(error) {
                statusDiv.innerHTML = '<div class="error">Network error: ' + error.message + '</div>';
            });
        }
        
        // Tab navigation
        function showTab(tabName) {
            // Update tab buttons
            var tabs = document.querySelectorAll('.nav-tab');
            for (var i = 0; i < tabs.length; i++) {
                tabs[i].classList.remove('active');
            }
            event.target.classList.add('active');
            
            // Update content
            var contents = document.querySelectorAll('.tab-content');
            for (var i = 0; i < contents.length; i++) {
                contents[i].classList.remove('active');
            }
            document.getElementById(tabName).classList.add('active');
            
            currentTab = tabName;
            
            // Load data for the tab
            if (tabName === 'private-groups' || tabName === 'direct-messages') {
                loadRooms();
            } else if (tabName === 'send-message') {
                // Load both groups and DMs for the send message tab
                loadRooms();
                // Update recipient options after a short delay to ensure data is loaded
                setTimeout(function() {
                    updateRecipientOptions();
                }, 500);
            } else if (tabName === 'settings') {
                loadCurrentConfigForTab();
            }
        }
        
        // Connection status
        function checkConnectionStatus() {
            makeRequest('GET', '/api/status', null, function(data) {
                connectionStatus = data.connected;
                updateStatusIndicator(data.connected, data.message);
            }, function(error) {
                console.error('Status check failed:', error);
                connectionStatus = false;
                updateStatusIndicator(false, 'Connection failed');
            });
        }
        
        function updateStatusIndicator(connected, message) {
            var indicator = document.getElementById('statusIndicator');
            indicator.className = 'status-indicator ' + (connected ? 'connected' : 'error');
            indicator.title = message || (connected ? 'Connected' : 'Disconnected');
        }
        
        // Load rooms (private groups and DMs)
        function loadRooms() {
            if (!connectionStatus) {
                showMessage('privateGroupsStatus', 'Not connected to RocketChat', 'error');
                showMessage('directMessagesStatus', 'Not connected to RocketChat', 'error');
                return;
            }
            
            makeRequest('GET', '/api/rooms', null, function(data) {
                if (data.status === 'success') {
                    privateGroups = data.private_groups || [];
                    directMessages = data.direct_messages || [];
                    
                    displayPrivateGroups();
                    displayDirectMessages();
                    
                    showMessage('privateGroupsStatus', 'Loaded ' + privateGroups.length + ' private groups', 'success');
                    showMessage('directMessagesStatus', 'Loaded ' + directMessages.length + ' direct messages', 'success');
                } else {
                    showMessage('privateGroupsStatus', 'Error: ' + data.message, 'error');
                    showMessage('directMessagesStatus', 'Error: ' + data.message, 'error');
                }
            }, function(error) {
                console.error('Failed to load rooms:', error);
                showMessage('privateGroupsStatus', 'Failed to load rooms', 'error');
                showMessage('directMessagesStatus', 'Failed to load rooms', 'error');
            });
        }
        
        function displayPrivateGroups() {
            var list = document.getElementById('privateGroupsList');
            list.innerHTML = '';
            
            if (privateGroups.length === 0) {
                list.innerHTML = '<li class="loading">No private groups found</li>';
                return;
            }
            
            for (var i = 0; i < privateGroups.length; i++) {
                var group = privateGroups[i];
                var li = document.createElement('li');
                li.className = 'room-item';
                li.onclick = createRoomClickHandler(group, 'private');
                
                li.innerHTML = 
                    '<div class="room-name">' + escapeHtml(group.display) + '</div>' +
                    '<div class="room-type">Private Group</div>';
                
                list.appendChild(li);
            }
        }
        
        function displayDirectMessages() {
            var list = document.getElementById('directMessagesList');
            list.innerHTML = '';
            
            if (directMessages.length === 0) {
                list.innerHTML = '<li class="loading">No direct messages found</li>';
                return;
            }
            
            for (var i = 0; i < directMessages.length; i++) {
                var dm = directMessages[i];
                var li = document.createElement('li');
                li.className = 'room-item';
                li.onclick = createRoomClickHandler(dm, 'direct');
                
                li.innerHTML = 
                    '<div class="room-name">' + escapeHtml(dm.display) + '</div>' +
                    '<div class="room-type">Direct Message</div>';
                
                list.appendChild(li);
            }
        }
        
        // Create click handler for rooms (closure to capture room data)
        function createRoomClickHandler(room, type) {
            return function() {
                selectRoom(room, type);
            };
        }
        
        function selectRoom(room, type) {
            selectedRoom = { room: room, type: type };
            
            // Update UI
            var items = document.querySelectorAll('.room-item');
            for (var i = 0; i < items.length; i++) {
                items[i].classList.remove('selected');
            }
            event.currentTarget.classList.add('selected');
            
            // Show messages area and scroll to it
            if (type === 'private') {
                var messagesDiv = document.getElementById('privateGroupMessages');
                messagesDiv.style.display = 'block';
                document.getElementById('selectedPrivateGroupName').textContent = room.display;
                loadMessages(room.id, 'privateGroupMessagesContainer', 'p', room.name);
                
                // Scroll to messages area
                setTimeout(function() {
                    messagesDiv.scrollIntoView({ behavior: 'smooth', block: 'start' });
                }, 200);
            } else {
                var messagesDiv = document.getElementById('directMessageMessages');
                messagesDiv.style.display = 'block';
                document.getElementById('selectedDirectMessageName').textContent = room.display;
                loadMessages(room.id, 'directMessageMessagesContainer', 'd', room.name);
                
                // Scroll to messages area
                setTimeout(function() {
                    messagesDiv.scrollIntoView({ behavior: 'smooth', block: 'start' });
                }, 200);
            }
        }
        
        function loadMessages(roomId, containerId, roomType, roomName) {
            var container = document.getElementById(containerId);
            container.innerHTML = '<div class="loading">Loading messages...</div>';
            
            var url = '/api/messages?room_id=' + encodeURIComponent(roomId) + 
                     '&room_type=' + encodeURIComponent(roomType || 'p') + 
                     '&room_name=' + encodeURIComponent(roomName || 'Room');
            
            makeRequest('GET', url, null, function(data) {
                if (data.status === 'success') {
                    displayMessages(data.messages, containerId);
                } else {
                    container.innerHTML = '<div class="error-message">Error: ' + data.message + '</div>';
                }
            }, function(error) {
                console.error('Failed to load messages:', error);
                container.innerHTML = '<div class="error-message">Failed to load messages</div>';
            });
        }
        
        function displayMessages(messages, containerId) {
            var container = document.getElementById(containerId);
            container.innerHTML = '';
            
            if (messages.length === 0) {
                container.innerHTML = '<div class="loading">No messages found</div>';
                return;
            }
            
            // Reverse messages to show oldest first (chat style)
            var sortedMessages = messages.slice().reverse();
            
            for (var i = 0; i < sortedMessages.length; i++) {
                var msg = sortedMessages[i];
                var div = document.createElement('div');
                div.className = 'message-item';
                
                div.innerHTML = 
                    '<div class="message-header">' +
                    '<span class="message-username">' + escapeHtml(msg.username) + '</span>' +
                    '<span class="message-time">' + escapeHtml(msg.time) + '</span>' +
                    '</div>' +
                    '<div class="message-text">' + escapeHtml(msg.text) + '</div>';
                
                container.appendChild(div);
            }
            
            // Auto-scroll to bottom to see latest messages - faster
            container.scrollTop = container.scrollHeight;
        }
        
        // Send messages
        function sendPrivateGroupMessage() {
            sendMessage('privateGroupMessageInput', 'p');
        }
        
        function sendDirectMessage() {
            sendMessage('directMessageMessageInput', 'd');
        }
        
        function sendMessage(inputId, roomType) {
            if (!selectedRoom) {
                alert('Please select a room first');
                return;
            }
            
            var input = document.getElementById(inputId);
            var message = input.value.trim();
            
            if (!message) {
                return;
            }
            
            // Show sending feedback
            var originalPlaceholder = input.placeholder;
            input.placeholder = 'Sending...';
            input.disabled = true;
            
            var data = {
                room_name: selectedRoom.room.name,
                room_type: roomType,
                message: message
            };
            
            makeRequest('POST', '/api/send_message', data, function(result) {
                // Restore input
                input.placeholder = originalPlaceholder;
                input.disabled = false;
                
                if (result.status === 'success') {
                    input.value = '';
                    
                    // Add optimistic message display
                    var containerId = roomType === 'p' ? 'privateGroupMessagesContainer' : 'directMessageMessagesContainer';
                    addOptimisticMessage(containerId, message);
                    
                    // Refresh messages after a shorter delay
                    setTimeout(function() {
                        loadMessages(selectedRoom.room.id, containerId, roomType, selectedRoom.room.name);
                    }, 500);
                } else {
                    alert('Failed to send message: ' + result.message);
                }
            }, function(error) {
                // Restore input on error
                input.placeholder = originalPlaceholder;
                input.disabled = false;
                
                console.error('Failed to send message:', error);
                alert('Failed to send message');
            });
        }
        
        function addOptimisticMessage(containerId, messageText) {
            var container = document.getElementById(containerId);
            var div = document.createElement('div');
            div.className = 'message-item';
            div.style.opacity = '0.7'; // Show as pending
            
            var now = new Date();
            var hours = now.getHours();
            var minutes = now.getMinutes();
            var timeStr = (now.getMonth() + 1) + '/' + now.getDate() + ' ' + 
                         (hours < 10 ? '0' : '') + hours + ':' + 
                         (minutes < 10 ? '0' : '') + minutes;
            
            div.innerHTML = 
                '<div class="message-header">' +
                '<span class="message-username">You</span>' +
                '<span class="message-time">' + timeStr + ' (sending...)</span>' +
                '</div>' +
                '<div class="message-text">' + escapeHtml(messageText) + '</div>';
            
            container.appendChild(div);
            container.scrollTop = container.scrollHeight;
        }
        
        // Configuration
        function loadConfiguration() {
            makeRequest('GET', '/api/config', null, function(data) {
                if (data.status === 'success') {
                    var config = data.config;
                    document.getElementById('serverUrl').value = config.RCSERVER || '';
                    // Don't load sensitive data like tokens
                }
            }, function(error) {
                console.error('Failed to load config:', error);
            });
        }
        
        function saveConfig() {
            var config = {
                RCSERVER: document.getElementById('serverUrl').value,
                RCTOKEN: document.getElementById('authToken').value,
                RCID: document.getElementById('userId').value
            };
            
            makeRequest('POST', '/api/save_config', config, function(result) {
                if (result.status === 'success') {
                    showMessage('configStatus', 'Configuration saved successfully', 'success');
                    // Clear sensitive fields
                    document.getElementById('authToken').value = '';
                    document.getElementById('userId').value = '';
                } else {
                    showMessage('configStatus', 'Error: ' + result.message, 'error');
                }
            }, function(error) {
                console.error('Failed to save config:', error);
                showMessage('configStatus', 'Failed to save configuration', 'error');
            });
        }
        
        function testConnection() {
            showMessage('configStatus', 'Testing connection...', 'info');
            
            setTimeout(function() {
                checkConnectionStatus();
                setTimeout(function() {
                    if (connectionStatus) {
                        showMessage('configStatus', 'Connection successful!', 'success');
                    } else {
                        showMessage('configStatus', 'Connection failed. Please check your settings.', 'error');
                    }
                }, 1000);
            }, 500);
        }
        
        // Utility functions
        function showMessage(elementId, message, type) {
            var element = document.getElementById(elementId);
            element.innerHTML = '<div class="' + type + '-message">' + escapeHtml(message) + '</div>';
            
            // Auto-hide success messages
            if (type === 'success') {
                setTimeout(function() {
                    element.innerHTML = '';
                }, 3000);
            }
        }
        
        function escapeHtml(text) {
            var div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }
        
        function refreshCurrentView() {
            if (currentTab === 'private-groups' || currentTab === 'direct-messages') {
                loadRooms();
                
                // Refresh messages if a room is selected
                if (selectedRoom) {
                    var containerId = selectedRoom.type === 'private' ? 'privateGroupMessagesContainer' : 'directMessageMessagesContainer';
                    var roomType = selectedRoom.type === 'private' ? 'p' : 'd';
                    loadMessages(selectedRoom.room.id, containerId, roomType, selectedRoom.room.name);
                }
            }
        }
        
        // Initialize when page loads
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', initApp);
        } else {
            initApp();
        }
        
        // Handle enter key in message inputs (ES5 compatible)
        document.addEventListener('keypress', function(e) {
            var keyCode = e.keyCode || e.which;
            if (keyCode === 13) { // Enter key
                if (e.target.id === 'privateGroupMessageInput') {
                    sendPrivateGroupMessage();
                } else if (e.target.id === 'directMessageMessageInput') {
                    sendDirectMessage();
                }
            }
        });
    </script>
</body>
</html>'''

# Performance optimization: Caching (following BB10 standards)
CACHE_DURATION = 30  # 30 seconds cache for rooms
MESSAGE_CACHE_DURATION = 15  # 15 seconds cache for messages
CONFIG_CACHE_DURATION = 60  # 60 seconds cache for config
REQUEST_TIMEOUT = 10  # 10 seconds timeout for requests

# Global cache to speed things up
cache = {
    'config': None,
    'config_time': 0,
    'rooms': None,
    'rooms_time': 0,
    'messages': {},  # room_id -> {messages, time}
    'user_info': None,
    'user_time': 0,
    'last_message_ids': {}  # room_id -> last_message_id (for notification tracking)
}

def execute_shell_command(title, subtitle, itemid="RocketChat"):
    """
    Executes the shell command to send a notification - EXACT copy from reminders.py
    
    Args:
        title (str): The title of the notification.
        subtitle (str): The subtitle/content of the notification.
        itemid (str): Identifier for the notification item.
    """
    payload = {
        "itemid": itemid,
        "title": title,
        "subtitle": subtitle,
        "target": "YourTarget",
        "targetAction": "YourTargetAction",
        "payload": "YourPayload",
        "payloadType": "YourPayloadType",
        "payloadURI": "YourPayloadURI"
    }
    json_payload = json.dumps(payload)

    try:
        with tempfile.NamedTemporaryFile(delete=False, mode="w", encoding="utf-8") as temp_file:
            temp_file.write(f"msg::notify\ndat:json:{json_payload}")
            temp_file_path = temp_file.name

        command = f"cat {temp_file_path} >> /pps/services/notify/control"
        subprocess.run(command, shell=True, check=True)
        print(f"[NOTIFY] Notification sent: {title}")
    except subprocess.CalledProcessError as e:
        print(f"[NOTIFY] Error sending notification '{title}': {e}")
    except Exception as e:
        print(f"[NOTIFY] General error sending notification '{title}': {e}")

def initialize_message_tracking():
    """
    Initialize message tracking with current latest messages - no notifications sent
    """
    global cache
    
    try:
        config = load_config()
        if not config.get('RCSERVER') or not config.get('RCTOKEN') or not config.get('RCID'):
            print("[NOTIFY] Not configured yet, skipping initialization")
            return
        
        print("[NOTIFY] Initializing message tracking...")
        
        # Get current rooms
        rooms_result = get_rooms_data(config)
        if rooms_result.get('status') == 'success':
            all_rooms = []
            all_rooms.extend(rooms_result.get('private_groups', []))
            all_rooms.extend(rooms_result.get('direct_messages', []))
            
            for room in all_rooms:
                room_id = room.get('id')
                room_type = 'd' if room.get('type') == 'dm' else 'p'
                
                if room_id:
                    # Get latest message ID (but don't send notification)
                    endpoint = f'im.messages?roomId={room_id}&count=1' if room_type == 'd' else f'groups.messages?roomId={room_id}&count=1'
                    messages_result = make_rocketchat_request(endpoint, config)
                    
                    if messages_result.get('success') and messages_result.get('messages'):
                        latest_message = messages_result['messages'][0]
                        message_id = latest_message.get('_id')
                        
                        if message_id:
                            # Store this as the "last known" message (no notification)
                            cache['last_message_ids'][room_id] = message_id
                            print(f"[NOTIFY] Initialized tracking for room {room.get('display', room_id)}")
        
        print("[NOTIFY] Message tracking initialized - will now notify for NEW messages only")
        
    except Exception as e:
        print(f"[NOTIFY] Error initializing message tracking: {e}")

def check_for_new_messages():
    """
    Check for new messages and send notifications - runs in background thread
    """
    global cache
    
    # Initialize tracking first (no notifications for existing messages)
    initialize_message_tracking()
    
    # Wait a bit before starting to check for new messages
    time.sleep(45)
    print("[NOTIFY] Starting new message monitoring...")
    
    initialization_complete = True  # Flag to track that initialization is done
    
    while True:
        try:
            config = load_config()
            if not config.get('RCSERVER') or not config.get('RCTOKEN') or not config.get('RCID'):
                time.sleep(30)  # Wait 30 seconds if not configured
                continue
            
            # Get rooms (use cached if available)
            now = time.time()
            if not cache['rooms'] or (now - cache['rooms_time']) > CACHE_DURATION:
                # Refresh rooms cache
                rooms_result = get_rooms_data(config)
                if rooms_result.get('status') == 'success':
                    cache['rooms'] = rooms_result
                    cache['rooms_time'] = now
            
            if cache['rooms'] and cache['rooms'].get('status') == 'success':
                all_rooms = []
                all_rooms.extend(cache['rooms'].get('private_groups', []))
                all_rooms.extend(cache['rooms'].get('direct_messages', []))
                
                for room in all_rooms:
                    room_id = room.get('id')
                    room_name = room.get('display', room.get('name', 'Unknown'))
                    room_type = 'd' if room.get('type') == 'dm' else 'p'
                    
                    if room_id:
                        # Get latest message
                        endpoint = f'im.messages?roomId={room_id}&count=1' if room_type == 'd' else f'groups.messages?roomId={room_id}&count=1'
                        messages_result = make_rocketchat_request(endpoint, config)
                        
                        if messages_result.get('success') and messages_result.get('messages'):
                            latest_message = messages_result['messages'][0]
                            message_id = latest_message.get('_id')
                            message_text = latest_message.get('msg', '')
                            sender = latest_message.get('u', {}).get('username', 'Unknown')
                            
                            # Check if this is a new message
                            last_known_id = cache['last_message_ids'].get(room_id)
                            if last_known_id != message_id and message_id:
                                # New message detected!
                                
                                # Only send notifications AFTER initialization is complete
                                if initialization_complete and last_known_id is not None:
                                    # This is a truly NEW message - update ID and notify
                                    cache['last_message_ids'][room_id] = message_id
                                    
                                    # Don't notify for our own messages
                                    my_username = get_user_info(config).get('username', '')
                                    if sender != my_username:
                                        # Send notification
                                        title = f"💬 {room_name}"
                                        subtitle = f"{sender}: {message_text[:100]}{'...' if len(message_text) > 100 else ''}"
                                        itemid = f"RocketChat-{room_id}"
                                        
                                        execute_shell_command(title, subtitle, itemid)
                                        print(f"[NOTIFY] New message notification sent for {room_name}")
                                else:
                                    # During initialization or first run - just store the ID
                                    cache['last_message_ids'][room_id] = message_id
            
            time.sleep(10)  # Check every 10 seconds
            
        except Exception as e:
            print(f"[NOTIFY] Error in notification checker: {e}")
            time.sleep(30)  # Wait longer on error

# Start notification checker thread
threading.Thread(target=check_for_new_messages, daemon=True).start()

def get_cached_or_fetch_config():
    """Load configuration with caching (following BB10 standards)"""
    global cache
    now = time.time()
    
    # Use cached config if fresh
    if cache['config'] and (now - cache['config_time']) < CONFIG_CACHE_DURATION:
        return cache['config']
    
    config = {}
    if os.path.exists(CONFIG_FILE_PATH):
        try:
            with open(CONFIG_FILE_PATH, 'r') as f:
                for line in f:
                    line = line.strip()
                    if line and not line.startswith('#') and '=' in line:
                        key, value = line.split('=', 1)
                        config[key.strip()] = value.strip()
        except Exception as e:
            print(f"Error loading config: {e}")
    
    # Cache it
    cache['config'] = config
    cache['config_time'] = now
    return config

def load_config():
    """Backward compatibility wrapper"""
    return get_cached_or_fetch_config()

def get_rooms_data(config):
    """Get rooms data for notifications - helper function"""
    if not config.get('RCSERVER') or not config.get('RCTOKEN'):
        return {'status': 'error', 'message': 'Missing config'}
    
    private_groups = []
    direct_messages = []
    
    # Get user info once
    user_info = get_user_info(config)
    my_username = user_info.get('username', '')
    
    # Get private groups
    groups_result = make_rocketchat_request('groups.list?count=20&sort={"lm":-1}', config)
    if groups_result.get('success'):
        for group in groups_result.get('groups', []):
            last_message = group.get('lm', group.get('_updatedAt', ''))
            private_groups.append({
                'id': group.get('_id'),
                'name': group.get('name'),
                'display': f"🔒{group.get('name')}",
                'type': 'private_group',
                'last_activity': last_message
            })
    
    # Get direct messages
    ims_result = make_rocketchat_request('im.list?count=20&sort={"lm":-1}', config)
    if ims_result.get('success'):
        for im in ims_result.get('ims', []):
            room_id = im.get('_id', '')
            username = 'Unknown'
            other_person = 'Unknown'
            
            # Get the other person's name
            usernames = im.get('usernames', [])
            if usernames and len(usernames) >= 2:
                for uname in usernames:
                    if uname != my_username and uname:
                        other_person = uname
                        break
            
            # Get username of who sent the LAST message
            if room_id:
                messages_result = make_rocketchat_request(f'im.messages?roomId={room_id}&count=1', config)
                if messages_result.get('success'):
                    messages = messages_result.get('messages', [])
                    if messages:
                        last_msg = messages[0]
                        last_sender = last_msg.get('u', {}).get('username', '')
                        username = last_sender if last_sender else other_person
                    else:
                        username = other_person
                else:
                    username = other_person
            else:
                username = other_person
            
            # Fallback if still unknown
            if username == 'Unknown' and usernames:
                username = usernames[0] if usernames[0] != my_username else (usernames[1] if len(usernames) > 1 else usernames[0])
            
            last_message = im.get('lm', im.get('_updatedAt', ''))
            display_name = f"@{username}" if username != 'Unknown' else f"@{other_person}"
            
            direct_messages.append({
                'id': im.get('_id'),
                'name': other_person,
                'display': display_name,
                'type': 'dm',
                'last_activity': last_message,
                'last_sender': username
            })
    
    return {
        'status': 'success',
        'private_groups': private_groups,
        'direct_messages': direct_messages,
        'total_private': len(private_groups),
        'total_dms': len(direct_messages)
    }

def make_rocketchat_request(endpoint, config, method='GET', data=None):
    """Make RocketChat API request with proper error handling (BB10 standards)"""
    try:
        print(f"[API] Making request to endpoint: {endpoint}")
        if not config.get('RCSERVER') or not config.get('RCTOKEN') or not config.get('RCID'):
            print(f"[API] Missing config - Server: {bool(config.get('RCSERVER'))}, Token: {bool(config.get('RCTOKEN'))}, ID: {bool(config.get('RCID'))}")
            return {'success': False, 'error': 'Missing configuration'}
        
        url = f"{config['RCSERVER']}/api/v1/{endpoint}"
        headers = {
            'X-Auth-Token': config['RCTOKEN'],
            'X-User-Id': config['RCID'],
            'Content-Type': 'application/json',
            'User-Agent': 'BB10RocketChatNavigator/1.0'
        }
        
        if method == 'POST' and data:
            data = json.dumps(data).encode('utf-8')
        
        req = urllib.request.Request(url, data=data, headers=headers)
        req.get_method = lambda: method
        
        # Optimized SSL context for BB10 performance
        ssl_context = ssl.create_default_context()
        ssl_context.check_hostname = False
        ssl_context.verify_mode = ssl.CERT_NONE
        
        response = urllib.request.urlopen(req, timeout=REQUEST_TIMEOUT, context=ssl_context)
        result = response.read().decode('utf-8')
        json_result = json.loads(result)
        print(f"[API] Success: {endpoint} -> {json_result.get('success', 'unknown')}")
        return json_result
        
    except urllib.error.HTTPError as e:
        print(f"[API] HTTP Error: {endpoint} -> {e.code}: {e.reason}")
        return {'success': False, 'error': f'HTTP {e.code}: {e.reason}'}
    except urllib.error.URLError as e:
        print(f"[API] URL Error: {endpoint} -> {e.reason}")
        return {'success': False, 'error': f'Connection error: {e.reason}'}
    except socket.timeout:
        print(f"[API] Timeout: {endpoint}")
        return {'success': False, 'error': 'Request timeout'}
    except json.JSONDecodeError as e:
        print(f"[API] JSON Error: {endpoint} -> {e}")
        return {'success': False, 'error': f'Invalid JSON response: {e}'}
    except Exception as e:
        print(f"[API] General Error: {endpoint} -> {e}")
        return {'success': False, 'error': str(e)}

def get_user_info(config):
    """Get user information with caching (BB10 standards)"""
    global cache
    now = time.time()
    
    # Use cached user info (cache longer for user info)
    if cache['user_info'] and (now - cache['user_time']) < CONFIG_CACHE_DURATION:
        return cache['user_info']
    
    result = make_rocketchat_request('me', config)
    if result.get('success'):
        user_info = result.get('user', {})
        cache['user_info'] = user_info
        cache['user_time'] = now
        return user_info
    else:
        print(f"Failed to get user info: {result.get('error', 'Unknown error')}")
        return {}

class RocketChatHandler(http.server.BaseHTTPRequestHandler):
    """BB10 RocketChat Navigator HTTP Handler (following BB10 standards)"""
    
    def log_message(self, format, *args):
        """Enable request logging for debugging"""
        print(f"[{time.strftime('%H:%M:%S')}] {format % args}")
    
    def do_GET(self):
        """Handle GET requests with proper routing (BB10 standards)"""
        try:
            parsed_path = urllib.parse.urlparse(self.path)
            config = load_config()
            
            # Route handling following BB10 patterns
            if parsed_path.path == '/':
                self.serve_html()
            elif parsed_path.path == '/api/status':
                self.handle_status_api(config)
            elif parsed_path.path == '/api/rooms':
                self.handle_rooms_api(config)
            elif parsed_path.path.startswith('/api/messages'):
                self.handle_messages_api(config)
            elif parsed_path.path == '/api/config':
                self.handle_config_api(config)
            else:
                self.send_error(404, 'Not Found')
                
        except Exception as e:
            print(f"GET request error: {e}")
            self.send_error(500, 'Internal Server Error')
    
    def do_POST(self):
        """Handle POST requests with proper routing (BB10 standards)"""
        try:
            parsed_path = urllib.parse.urlparse(self.path)
            config = load_config()
            
            # Route handling following BB10 patterns
            if parsed_path.path == '/api/send_message':
                self.handle_send_message_api(config)
            elif parsed_path.path == '/api/send-dm':
                self.handle_send_dm_api(config)
            elif parsed_path.path == '/api/send-group-message':
                self.handle_send_group_message_api(config)
            elif parsed_path.path == '/api/save_config':
                self.handle_save_config_api(config)
            elif parsed_path.path == '/api/login':
                self.handle_login_api()
            else:
                self.send_error(404, 'Not Found')
                
        except Exception as e:
            print(f"POST request error: {e}")
            self.send_error(500, 'Internal Server Error')
    
    def serve_html(self):
        """Serve embedded HTML page (BB10 standards - single file deployment)"""
        try:
            self.send_response(200)
            self.send_header('Content-Type', 'text/html; charset=utf-8')
            self.send_header('Cache-Control', 'max-age=300')  # 5 minute cache
            self.send_header('X-Content-Type-Options', 'nosniff')
            self.end_headers()
            self.wfile.write(HTML_CONTENT.encode('utf-8'))
            
        except Exception as e:
            print(f"Error serving HTML: {e}")
            self.send_error(500, 'Error loading page')
    
    def send_json(self, data, status_code=200):
        """Send JSON response with proper headers (BB10 standards)"""
        try:
            self.send_response(status_code)
            self.send_header('Content-Type', 'application/json; charset=utf-8')
            self.send_header('Cache-Control', 'no-cache, no-store, must-revalidate')
            self.send_header('Pragma', 'no-cache')
            self.send_header('Expires', '0')
            self.send_header('X-Content-Type-Options', 'nosniff')
            self.end_headers()
            
            # Compact JSON for performance (BB10 standard)
            json_str = json.dumps(data, separators=(',', ':'), ensure_ascii=False)
            self.wfile.write(json_str.encode('utf-8'))
            
        except Exception as e:
            print(f"Error sending JSON: {e}")
            # Fallback error response
            try:
                self.send_error(500, 'JSON encoding error')
            except:
                pass
    
    def handle_status_api(self, config):
        """Handle status API request (BB10 standards)"""
        try:
            if not config.get('RCSERVER') or not config.get('RCTOKEN') or not config.get('RCID'):
                self.send_json({
                    'status': 'error', 
                    'connected': False, 
                    'message': 'Configuration incomplete'
                })
                return
            
            # Test connection with a quick API call
            result = make_rocketchat_request('me', config)
            if result.get('success'):
                self.send_json({
                    'status': 'success',
                    'connected': True,
                    'message': 'Connected to RocketChat',
                    'server': config['RCSERVER'],
                    'user': result.get('user', {}).get('username', 'Unknown')
                })
            else:
                self.send_json({
                    'status': 'error',
                    'connected': False,
                    'message': f"Connection failed: {result.get('error', 'Unknown error')}",
                    'server': config['RCSERVER']
                })
                
        except Exception as e:
            print(f"Status API error: {e}")
            self.send_json({
                'status': 'error',
                'connected': False,
                'message': f'Status check failed: {str(e)}'
            })
    
    def handle_rooms_api(self, config):
        """Handle rooms API request with caching (BB10 standards)"""
        global cache
        now = time.time()
        
        # Use cached rooms if fresh
        if cache['rooms'] and (now - cache['rooms_time']) < CACHE_DURATION:
            self.send_json(cache['rooms'])
            return
        
        if not config.get('RCSERVER') or not config.get('RCTOKEN'):
            self.send_json({'status': 'error', 'message': 'Missing config'})
            return
        
        private_groups = []
        direct_messages = []
        
        # Get user info once
        user_info = get_user_info(config)
        my_username = user_info.get('username', '')
        
        # Parallel requests would be better, but keep it simple
        # Get private groups (limit for speed) - sorted by recent activity
        groups_result = make_rocketchat_request('groups.list?count=20&sort={"lm":-1}', config)
        if groups_result.get('success'):
            for group in groups_result.get('groups', []):
                # Get last message timestamp for sorting
                last_message = group.get('lm', group.get('_updatedAt', ''))
                private_groups.append({
                    'id': group.get('_id'),
                    'name': group.get('name'),
                    'display': f"🔒{group.get('name')}",
                    'type': 'private_group',
                    'last_activity': last_message
                })
        
        # Get direct messages (limit for speed) - sorted by recent activity  
        ims_result = make_rocketchat_request('im.list?count=20&sort={"lm":-1}', config)
        if ims_result.get('success'):
            for im in ims_result.get('ims', []):
                room_id = im.get('_id', '')
                username = 'Unknown'
                other_person = 'Unknown'
                
                # First, get the other person's name for fallback
                usernames = im.get('usernames', [])
                if usernames and len(usernames) >= 2:
                    for uname in usernames:
                        if uname != my_username and uname:
                            other_person = uname
                            break
                
                # Now get the username of who sent the LAST message
                if room_id:
                    # Get the most recent message to see who sent it
                    messages_result = make_rocketchat_request(f'im.messages?roomId={room_id}&count=1', config)
                    if messages_result.get('success'):
                        messages = messages_result.get('messages', [])
                        if messages:
                            last_msg = messages[0]
                            last_sender = last_msg.get('u', {}).get('username', '')
                            if last_sender:
                                username = last_sender
                            else:
                                username = other_person
                        else:
                            username = other_person
                    else:
                        username = other_person
                else:
                    username = other_person
                
                # Fallback if still unknown
                if username == 'Unknown' and usernames:
                    username = usernames[0] if usernames[0] != my_username else (usernames[1] if len(usernames) > 1 else usernames[0])
                
                # Get last message timestamp for sorting
                last_message = im.get('lm', im.get('_updatedAt', ''))
                
                # Show who sent the last message, but keep the room info for the other person
                display_name = f"@{username}" if username != 'Unknown' else f"@{other_person}"
                
                direct_messages.append({
                    'id': im.get('_id'),
                    'name': other_person,  # Keep other person for sending messages
                    'display': display_name,  # Show last sender
                    'type': 'dm',
                    'last_activity': last_message,
                    'last_sender': username  # Track who sent last message
                })
        
        # Sort both by most recent activity (already sorted by API, but ensure it)
        def get_timestamp(item):
            try:
                activity = item.get('last_activity', '')
                if isinstance(activity, dict) and '$date' in activity:
                    return activity['$date']
                elif isinstance(activity, str):
                    # Parse ISO date string
                    import datetime
                    return datetime.datetime.fromisoformat(activity.replace('Z', '+00:00')).timestamp() * 1000
                return 0
            except:
                return 0
        
        private_groups.sort(key=get_timestamp, reverse=True)
        direct_messages.sort(key=get_timestamp, reverse=True)
        
        result = {
            'status': 'success',
            'private_groups': private_groups,
            'direct_messages': direct_messages,
            'total_private': len(private_groups),
            'total_dms': len(direct_messages)
        }
        
        # Cache the result
        cache['rooms'] = result
        cache['rooms_time'] = now
        
        self.send_json(result)
    
    def handle_messages_api(self, config):
        """Handle messages API request with caching (BB10 standards)"""
        global cache
        
        if not config.get('RCSERVER') or not config.get('RCTOKEN'):
            self.send_json({'status': 'error', 'message': 'Missing config'})
            return
        
        # Parse query parameters
        query = urllib.parse.urlparse(self.path).query
        params = urllib.parse.parse_qs(query)
        room_id = params.get('room_id', [''])[0]
        room_type = params.get('room_type', ['p'])[0]
        
        if not room_id:
            self.send_json({'status': 'error', 'message': 'Missing room_id'})
            return
        
        now = time.time()
        cache_key = f"{room_id}_{room_type}"
        
        # Use cached messages if fresh
        if (cache_key in cache['messages'] and 
            (now - cache['messages'][cache_key]['time']) < MESSAGE_CACHE_DURATION):
            self.send_json(cache['messages'][cache_key]['data'])
            return
        
        # Choose endpoint - fewer messages for speed
        if room_type == 'd':
            endpoint = f'im.messages?roomId={room_id}&count=10'  # Reduced count
        elif room_type == 'p':
            endpoint = f'groups.messages?roomId={room_id}&count=10'
        else:
            endpoint = f'channels.messages?roomId={room_id}&count=10'
        
        messages_result = make_rocketchat_request(endpoint, config)
        
        if not messages_result.get('success'):
            self.send_json({'status': 'error', 'message': 'Failed to fetch messages'})
            return
        
        # Fast message processing
        formatted_messages = []
        for msg in messages_result.get('messages', []):
            ts = msg.get('ts', {})
            formatted_time = 'Now'
            timestamp_raw = 0
            
            # Simplified time formatting for speed
            if isinstance(ts, dict) and '$date' in ts:
                try:
                    timestamp = ts['$date']
                    if isinstance(timestamp, (int, float)):
                        timestamp_raw = timestamp
                        # Simple time format
                        import datetime
                        dt = datetime.datetime.fromtimestamp(timestamp / 1000)
                        formatted_time = dt.strftime('%H:%M')  # Just time, not date
                except:
                    pass
            
            user = msg.get('u', {})
            formatted_messages.append({
                'id': msg.get('_id'),
                'username': user.get('username', 'User'),
                'text': msg.get('msg', ''),
                'time': formatted_time,
                'timestamp_raw': timestamp_raw
            })
        
        # Quick sort
        formatted_messages.sort(key=lambda x: x.get('timestamp_raw', 0), reverse=True)
        
        result = {
            'status': 'success',
            'room_id': room_id,
            'messages': formatted_messages,
            'count': len(formatted_messages)
        }
        
        # Cache the result
        cache['messages'][cache_key] = {
            'data': result,
            'time': now
        }
        
        self.send_json(result)
    
    def handle_send_message_api(self, config):
        """Handle send message API request (BB10 standards)"""
        if not config.get('RCSERVER') or not config.get('RCTOKEN'):
            self.send_json({'status': 'error', 'message': 'Missing config'})
            return
        
        try:
            content_length = int(self.headers.get('Content-Length', 0))
            post_data = self.rfile.read(content_length)
            data = json.loads(post_data.decode('utf-8'))
            
            room_name = data.get('room_name')
            room_type = data.get('room_type', 'p')
            message_text = data.get('message')
            
            if not room_name or not message_text:
                self.send_json({'status': 'error', 'message': 'Missing data'})
                return
            
            # Format channel
            if room_type == 'd':
                channel = f"@{room_name}"
            elif room_type == 'p':
                channel = room_name
            else:
                channel = f"#{room_name}"
            
            # Send message
            send_data = {'channel': channel, 'text': message_text}
            result = make_rocketchat_request('chat.postMessage', config, method='POST', data=send_data)
            
            if result.get('success'):
                # Clear message cache for this room to force refresh
                room_id = data.get('room_id', '')
                cache_key = f"{room_id}_{room_type}"
                if cache_key in cache['messages']:
                    del cache['messages'][cache_key]
                
                self.send_json({'status': 'success', 'message': 'Sent'})
            else:
                self.send_json({'status': 'error', 'message': 'Send failed'})
                
        except Exception as e:
            self.send_json({'status': 'error', 'message': str(e)})
    
    def handle_send_dm_api(self, config):
        """Handle send direct message API request"""
        if not config.get('RCSERVER') or not config.get('RCTOKEN'):
            self.send_json({'success': False, 'error': 'Missing configuration'})
            return
        
        try:
            content_length = int(self.headers.get('Content-Length', 0))
            post_data = self.rfile.read(content_length)
            data = json.loads(post_data.decode('utf-8'))
            
            room_id = data.get('roomId')
            message_text = data.get('message')
            
            if not room_id or not message_text:
                self.send_json({'success': False, 'error': 'Missing roomId or message'})
                return
            
            # Send direct message using im.sendMessage endpoint
            send_data = {'roomId': room_id, 'text': message_text}
            endpoint = 'im.sendMessage'
            
            print(f"[API] Sending DM to room {room_id}: {message_text[:50]}...")
            result = make_rocketchat_request(endpoint, config, method='POST', data=send_data)
            
            if result.get('success'):
                # Clear message cache for this room to force refresh
                cache_key = f"im_messages_{room_id}"
                if cache_key in cache['messages']:
                    del cache['messages'][cache_key]
                
                self.send_json({'success': True, 'message': 'Direct message sent successfully'})
            else:
                error_msg = result.get('error', 'Failed to send direct message')
                self.send_json({'success': False, 'error': error_msg})
                
        except Exception as e:
            print(f"[API] Error sending DM: {e}")
            self.send_json({'success': False, 'error': str(e)})
    
    def handle_send_group_message_api(self, config):
        """Handle send group message API request"""
        if not config.get('RCSERVER') or not config.get('RCTOKEN'):
            self.send_json({'success': False, 'error': 'Missing configuration'})
            return
        
        try:
            content_length = int(self.headers.get('Content-Length', 0))
            post_data = self.rfile.read(content_length)
            data = json.loads(post_data.decode('utf-8'))
            
            room_id = data.get('roomId')
            message_text = data.get('message')
            
            if not room_id or not message_text:
                self.send_json({'success': False, 'error': 'Missing roomId or message'})
                return
            
            # Send group message using groups.sendMessage endpoint
            send_data = {'roomId': room_id, 'text': message_text}
            endpoint = 'groups.sendMessage'
            
            print(f"[API] Sending group message to room {room_id}: {message_text[:50]}...")
            result = make_rocketchat_request(endpoint, config, method='POST', data=send_data)
            
            if result.get('success'):
                # Clear message cache for this room to force refresh
                cache_key = f"groups_messages_{room_id}"
                if cache_key in cache['messages']:
                    del cache['messages'][cache_key]
                
                self.send_json({'success': True, 'message': 'Group message sent successfully'})
            else:
                error_msg = result.get('error', 'Failed to send group message')
                self.send_json({'success': False, 'error': error_msg})
                
        except Exception as e:
            print(f"[API] Error sending group message: {e}")
            self.send_json({'success': False, 'error': str(e)})
    
    def handle_config_api(self, config):
        """API: Get current configuration (non-sensitive data only)"""
        try:
            safe_config = {}
            # Only return non-sensitive config
            if config.get('RCSERVER'):
                safe_config['RCSERVER'] = config['RCSERVER']
            if config.get('RC_CHANNEL'):
                safe_config['RC_CHANNEL'] = config['RC_CHANNEL']
            
            self.send_json({
                'status': 'success',
                'config': safe_config
            })
        except Exception as e:
            self.send_json({'status': 'error', 'message': str(e)})
    
    def handle_save_config_api(self, config):
        """API: Save configuration to .env file"""
        try:
            content_length = int(self.headers.get('Content-Length', 0))
            post_data = self.rfile.read(content_length)
            data = json.loads(post_data.decode('utf-8'))
            
            # Read existing config from .env file
            config_file = os.path.join(BASE_DIR, '.env')
            existing_config = {}
            
            # Load existing .env file if it exists
            if os.path.exists(config_file):
                try:
                    with open(config_file, 'r') as f:
                        for line in f:
                            line = line.strip()
                            if line and not line.startswith('#') and '=' in line:
                                key, value = line.split('=', 1)
                                existing_config[key.strip()] = value.strip()
                except Exception as e:
                    print(f"Error reading existing config: {e}")
            
            # Update with new values (validate and clean input)
            allowed_keys = ['RCSERVER', 'RCTOKEN', 'RCID', 'RC_CHANNEL']
            updated = False
            
            print(f"[CONFIG] Received data keys: {list(data.keys())}")
            print(f"[CONFIG] Allowed keys: {allowed_keys}")
            
            for key, value in data.items():
                if key in allowed_keys:
                    clean_value = str(value).strip()
                    if clean_value:  # Only save non-empty values
                        existing_config[key] = clean_value
                        updated = True
                        print(f"[CONFIG] Updated {key} in config")
                else:
                    print(f"[CONFIG] Ignoring key '{key}' - not in allowed keys")
            
            if not updated:
                self.send_json({
                    'status': 'error',
                    'message': 'No valid configuration provided'
                })
                return
            
            # Validate required fields
            if not existing_config.get('RCSERVER'):
                self.send_json({
                    'status': 'error',
                    'message': 'Server URL is required'
                })
                return
            
            if not existing_config.get('RCTOKEN'):
                self.send_json({
                    'status': 'error',
                    'message': 'Auth Token is required'
                })
                return
                
            if not existing_config.get('RCID'):
                self.send_json({
                    'status': 'error',
                    'message': 'User ID is required'
                })
                return
            
            # Write configuration to .env file
            try:
                with open(config_file, 'w') as f:
                    f.write("# RocketChat Configuration for BB10 Navigator\n")
                    f.write(f"# Generated: {time.strftime('%Y-%m-%d %H:%M:%S')}\n")
                    f.write("\n")
                    
                    # Write in a specific order for clarity
                    key_order = ['RCSERVER', 'RCTOKEN', 'RCID', 'RC_CHANNEL']
                    for key in key_order:
                        if key in existing_config:
                            f.write(f"{key}={existing_config[key]}\n")
                    
                    # Write any other keys that might exist
                    for key, value in existing_config.items():
                        if key not in key_order:
                            f.write(f"{key}={value}\n")
                
                print(f"Configuration saved to {config_file}")
                
            except Exception as e:
                self.send_json({
                    'status': 'error',
                    'message': f'Failed to write config file: {str(e)}'
                })
                return
            
            # Clear all caches to force reload with new config
            global cache
            cache['config'] = None
            cache['config_time'] = 0
            cache['rooms'] = None
            cache['rooms_time'] = 0
            cache['user_info'] = None
            cache['user_time'] = 0
            cache['messages'] = {}  # Clear message cache too
            
            # Test the new configuration
            new_config = load_config()
            test_result = make_rocketchat_request('me', new_config)
            
            if test_result.get('success'):
                self.send_json({
                    'status': 'success',
                    'message': 'Configuration saved and tested successfully!',
                    'server': new_config.get('RCSERVER', ''),
                    'connected': True
                })
            else:
                self.send_json({
                    'status': 'success',
                    'message': 'Configuration saved, but connection test failed. Please check your credentials.',
                    'server': new_config.get('RCSERVER', ''),
                    'connected': False,
                    'test_error': test_result.get('error', 'Unknown error')
                })
            
        except json.JSONDecodeError:
            self.send_json({
                'status': 'error',
                'message': 'Invalid JSON data received'
            })
        except Exception as e:
            print(f"Save config error: {e}")
            self.send_json({
                'status': 'error',
                'message': f'Configuration save failed: {str(e)}'
            })
    
    def handle_login_api(self):
        """API: Login with username/password and automatically save tokens"""
        try:
            content_length = int(self.headers.get('Content-Length', 0))
            post_data = self.rfile.read(content_length)
            data = json.loads(post_data.decode('utf-8'))
            
            server_url = data.get('server_url', '').strip()
            username = data.get('username', '').strip()
            password = data.get('password', '').strip()
            
            if not server_url or not username or not password:
                self.send_json({
                    'status': 'error',
                    'message': 'Server URL, username, and password are required'
                })
                return
            
            # Ensure server URL has proper format
            if not server_url.startswith('http'):
                server_url = 'https://' + server_url
            
            print(f"[LOGIN] Attempting login to {server_url} with username: {username}")
            
            # Perform RocketChat login
            login_result = self.rocketchat_login(server_url, username, password)
            
            if login_result.get('success'):
                # Extract tokens from login response
                auth_token = login_result.get('data', {}).get('authToken')
                user_id = login_result.get('data', {}).get('userId')
                user_info = login_result.get('data', {}).get('me', {})
                
                if not auth_token or not user_id:
                    self.send_json({
                        'status': 'error',
                        'message': 'Login succeeded but failed to get tokens from response'
                    })
                    return
                
                print(f"[LOGIN] Login successful! User: {user_info.get('username', 'Unknown')}")
                
                # Save configuration automatically
                config_data = {
                    'RCSERVER': server_url,
                    'RCTOKEN': auth_token,
                    'RCID': user_id
                }
                
                # Save to .env file
                config_file = os.path.join(BASE_DIR, '.env')
                try:
                    with open(config_file, 'w') as f:
                        f.write("# RocketChat Configuration - Auto-generated from login\n")
                        f.write(f"# Generated: {time.strftime('%Y-%m-%d %H:%M:%S')}\n")
                        f.write(f"# User: {user_info.get('username', 'Unknown')}\n")
                        f.write("\n")
                        f.write(f"RCSERVER={server_url}\n")
                        f.write(f"RCTOKEN={auth_token}\n")
                        f.write(f"RCID={user_id}\n")
                    
                    print(f"[LOGIN] Configuration saved to {config_file}")
                    
                    # Clear caches to force reload
                    global cache
                    cache['config'] = None
                    cache['config_time'] = 0
                    cache['rooms'] = None
                    cache['rooms_time'] = 0
                    cache['user_info'] = None
                    cache['user_time'] = 0
                    cache['messages'] = {}
                    
                    self.send_json({
                        'status': 'success',
                        'message': f'Successfully logged in as {user_info.get("username", "Unknown")}',
                        'user': {
                            'username': user_info.get('username'),
                            'name': user_info.get('name'),
                            'email': user_info.get('emails', [{}])[0].get('address') if user_info.get('emails') else None
                        },
                        'server': server_url
                    })
                    
                except Exception as e:
                    print(f"[LOGIN] Error saving config: {e}")
                    self.send_json({
                        'status': 'error',
                        'message': f'Login successful but failed to save configuration: {str(e)}'
                    })
            else:
                error_msg = login_result.get('error', 'Unknown login error')
                print(f"[LOGIN] Login failed: {error_msg}")
                self.send_json({
                    'status': 'error',
                    'message': f'Login failed: {error_msg}'
                })
                
        except json.JSONDecodeError:
            self.send_json({
                'status': 'error',
                'message': 'Invalid JSON data received'
            })
        except Exception as e:
            print(f"[LOGIN] Login API error: {e}")
            self.send_json({
                'status': 'error',
                'message': f'Login request failed: {str(e)}'
            })
    
    def rocketchat_login(self, server_url, username, password):
        """Perform RocketChat login and return auth tokens"""
        try:
            login_url = f"{server_url}/api/v1/login"
            
            # Prepare login data
            login_data = {
                'user': username,
                'password': password
            }
            
            # Create request
            data = json.dumps(login_data).encode('utf-8')
            headers = {
                'Content-Type': 'application/json',
                'User-Agent': 'BB10RocketChatNavigator/1.0'
            }
            
            req = urllib.request.Request(login_url, data=data, headers=headers)
            req.get_method = lambda: 'POST'
            
            # SSL context for BB10 compatibility
            ssl_context = ssl.create_default_context()
            ssl_context.check_hostname = False
            ssl_context.verify_mode = ssl.CERT_NONE
            
            # Make request
            response = urllib.request.urlopen(req, timeout=REQUEST_TIMEOUT, context=ssl_context)
            result = response.read().decode('utf-8')
            json_result = json.loads(result)
            
            print(f"[LOGIN] RocketChat login response: success={json_result.get('success')}")
            return json_result
            
        except urllib.error.HTTPError as e:
            error_body = e.read().decode('utf-8') if e.fp else 'No error details'
            try:
                error_json = json.loads(error_body)
                error_msg = error_json.get('error', error_json.get('message', f'HTTP {e.code}'))
            except:
                error_msg = f'HTTP {e.code}: {e.reason}'
            
            print(f"[LOGIN] HTTP Error: {e.code} - {error_msg}")
            return {'success': False, 'error': error_msg}
            
        except urllib.error.URLError as e:
            print(f"[LOGIN] URL Error: {e.reason}")
            return {'success': False, 'error': f'Connection error: {e.reason}'}
            
        except socket.timeout:
            print(f"[LOGIN] Timeout during login")
            return {'success': False, 'error': 'Login request timeout'}
            
        except json.JSONDecodeError as e:
            print(f"[LOGIN] JSON decode error: {e}")
            return {'success': False, 'error': 'Invalid response from server'}
            
        except Exception as e:
            print(f"[LOGIN] General error: {e}")
            return {'success': False, 'error': str(e)}

class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    """Threaded TCP Server for BB10 applications (following BB10 standards)"""
    allow_reuse_address = True
    daemon_threads = True
    timeout = 30  # 30 second timeout for connections

def run_server(port=PORT):
    """Run the BB10 RocketChat Navigator server (BB10 standards)"""
    try:
        config = load_config()
        
        print("=" * 60)
        print("BB10 RocketChat Navigator")
        print("=" * 60)
        print(f"Port: {port}")
        print(f"Server: {config.get('RCSERVER', 'Not configured')}")
        print(f"Base Directory: {BASE_DIR}")
        print("")
        print("Features:")
        print("- Optimized caching system")
        print("- BB10 compatible UI/UX")
        print("- Real-time messaging")
        print("- Private groups & DMs")
        print("")
        print("Performance optimizations:")
        print(f"- Room cache: {CACHE_DURATION}s")
        print(f"- Message cache: {MESSAGE_CACHE_DURATION}s") 
        print(f"- Config cache: {CONFIG_CACHE_DURATION}s")
        print(f"- Request timeout: {REQUEST_TIMEOUT}s")
        print("")
        print(f"🚀 Starting server on http://localhost:{port}")
        print("📱 Optimized for BlackBerry Passport")
        print("⏹️  Press Ctrl+C to stop")
        print("=" * 60)
        
        with ThreadedTCPServer(("", port), RocketChatHandler) as httpd:
            httpd.serve_forever()
            
    except KeyboardInterrupt:
        print("\n" + "=" * 60)
        print("👋 Shutting down BB10 RocketChat Navigator")
        print("=" * 60)
    except Exception as e:
        print(f"❌ Server error: {e}")
        sys.exit(1)

if __name__ == "__main__":
    run_server()
