// SeaweedFS Dashboard JavaScript
// Global variables
let bucketToDelete = '';
// Initialize dashboard when DOM is loaded
document.addEventListener('DOMContentLoaded', function() {
    initializeDashboard();
    initializeEventHandlers();
    setupFormValidation();
    setupFileManagerEventHandlers();
    
    // Initialize delete button visibility on file browser page
    if (window.location.pathname === '/files') {
        updateDeleteSelectedButton();
    }
});
function initializeDashboard() {
    // Set up HTMX event listeners
    setupHTMXListeners();
    
    // Initialize tooltips
    initializeTooltips();
    
    // Set up periodic refresh
    setupAutoRefresh();
    
    // Set active navigation
    setActiveNavigation();
    
    // Set up submenu behavior
    setupSubmenuBehavior();
}
// HTMX event listeners
function setupHTMXListeners() {
    // Show loading indicator on requests
    document.body.addEventListener('htmx:beforeRequest', function(evt) {
        showLoadingIndicator();
    });
    
    // Hide loading indicator on completion
    document.body.addEventListener('htmx:afterRequest', function(evt) {
        hideLoadingIndicator();
    });
    
    // Handle errors
    document.body.addEventListener('htmx:responseError', function(evt) {
        handleHTMXError(evt);
    });
}
// Initialize Bootstrap tooltips
function initializeTooltips() {
    var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
    var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
        return new bootstrap.Tooltip(tooltipTriggerEl);
    });
}
// Set up auto-refresh for dashboard data
function setupAutoRefresh() {
    // Refresh dashboard data every 30 seconds
    setInterval(function() {
        if (window.location.pathname === '/dashboard') {
            htmx.trigger('#dashboard-content', 'refresh');
        }
    }, 30000);
}
// Set active navigation item
function setActiveNavigation() {
    const currentPath = window.location.pathname;
    const navLinks = document.querySelectorAll('.sidebar .nav-link');
    
    navLinks.forEach(function(link) {
        const href = link.getAttribute('href');
        let isActive = false;
        
        if (href === currentPath) {
            isActive = true;
        } else if (currentPath === '/' && href === '/admin') {
            isActive = true;
        } else if (currentPath.startsWith('/s3/') && href === '/s3/buckets') {
            isActive = true;
        }
        // Note: Removed the problematic cluster condition that was highlighting all submenu items
        
        if (isActive) {
            link.classList.add('active');
        } else {
            link.classList.remove('active');
        }
    });
}
// Set up submenu behavior
function setupSubmenuBehavior() {
    const currentPath = window.location.pathname;
    
    // If we're on a cluster page, expand the cluster submenu
    if (currentPath.startsWith('/cluster/')) {
        const clusterSubmenu = document.getElementById('clusterSubmenu');
        if (clusterSubmenu) {
            clusterSubmenu.classList.add('show');
            
            // Update the parent toggle button state
            const toggleButton = document.querySelector('[data-bs-target="#clusterSubmenu"]');
            if (toggleButton) {
                toggleButton.classList.remove('collapsed');
                toggleButton.setAttribute('aria-expanded', 'true');
            }
        }
    }
    
    // If we're on an object store page, expand the object store submenu
    if (currentPath.startsWith('/object-store/')) {
        const objectStoreSubmenu = document.getElementById('objectStoreSubmenu');
        if (objectStoreSubmenu) {
            objectStoreSubmenu.classList.add('show');
            
            // Update the parent toggle button state
            const toggleButton = document.querySelector('[data-bs-target="#objectStoreSubmenu"]');
            if (toggleButton) {
                toggleButton.classList.remove('collapsed');
                toggleButton.setAttribute('aria-expanded', 'true');
            }
        }
    }
    
    // If we're on a maintenance page, expand the maintenance submenu
    if (currentPath.startsWith('/maintenance')) {
        const maintenanceSubmenu = document.getElementById('maintenanceSubmenu');
        if (maintenanceSubmenu) {
            maintenanceSubmenu.classList.add('show');
            
            // Update the parent toggle button state
            const toggleButton = document.querySelector('[data-bs-target="#maintenanceSubmenu"]');
            if (toggleButton) {
                toggleButton.classList.remove('collapsed');
                toggleButton.setAttribute('aria-expanded', 'true');
            }
        }
    }
    
    // Prevent submenu from collapsing when clicking on submenu items
    const clusterSubmenuLinks = document.querySelectorAll('#clusterSubmenu .nav-link');
    clusterSubmenuLinks.forEach(function(link) {
        link.addEventListener('click', function(e) {
            // Don't prevent the navigation, just stop the collapse behavior
            e.stopPropagation();
        });
    });
    
    const objectStoreSubmenuLinks = document.querySelectorAll('#objectStoreSubmenu .nav-link');
    objectStoreSubmenuLinks.forEach(function(link) {
        link.addEventListener('click', function(e) {
            // Don't prevent the navigation, just stop the collapse behavior
            e.stopPropagation();
        });
    });
    
    const maintenanceSubmenuLinks = document.querySelectorAll('#maintenanceSubmenu .nav-link');
    maintenanceSubmenuLinks.forEach(function(link) {
        link.addEventListener('click', function(e) {
            // Don't prevent the navigation, just stop the collapse behavior
            e.stopPropagation();
        });
    });
    
    // Handle the main cluster toggle
    const clusterToggle = document.querySelector('[data-bs-target="#clusterSubmenu"]');
    if (clusterToggle) {
        clusterToggle.addEventListener('click', function(e) {
            e.preventDefault();
            
            const submenu = document.getElementById('clusterSubmenu');
            const isExpanded = submenu.classList.contains('show');
            
            if (isExpanded) {
                // Collapse
                submenu.classList.remove('show');
                this.classList.add('collapsed');
                this.setAttribute('aria-expanded', 'false');
            } else {
                // Expand
                submenu.classList.add('show');
                this.classList.remove('collapsed');
                this.setAttribute('aria-expanded', 'true');
            }
        });
    }
    
    // Handle the main object store toggle
    const objectStoreToggle = document.querySelector('[data-bs-target="#objectStoreSubmenu"]');
    if (objectStoreToggle) {
        objectStoreToggle.addEventListener('click', function(e) {
            e.preventDefault();
            
            const submenu = document.getElementById('objectStoreSubmenu');
            const isExpanded = submenu.classList.contains('show');
            
            if (isExpanded) {
                // Collapse
                submenu.classList.remove('show');
                this.classList.add('collapsed');
                this.setAttribute('aria-expanded', 'false');
            } else {
                // Expand
                submenu.classList.add('show');
                this.classList.remove('collapsed');
                this.setAttribute('aria-expanded', 'true');
            }
        });
    }
    
    // Handle the main maintenance toggle
    const maintenanceToggle = document.querySelector('[data-bs-target="#maintenanceSubmenu"]');
    if (maintenanceToggle) {
        maintenanceToggle.addEventListener('click', function(e) {
            e.preventDefault();
            
            const submenu = document.getElementById('maintenanceSubmenu');
            const isExpanded = submenu.classList.contains('show');
            
            if (isExpanded) {
                // Collapse
                submenu.classList.remove('show');
                this.classList.add('collapsed');
                this.setAttribute('aria-expanded', 'false');
            } else {
                // Expand
                submenu.classList.add('show');
                this.classList.remove('collapsed');
                this.setAttribute('aria-expanded', 'true');
            }
        });
    }
}
// Loading indicator functions
function showLoadingIndicator() {
    const indicator = document.getElementById('loading-indicator');
    if (indicator) {
        indicator.style.display = 'block';
    }
    
    // Add loading class to body
    document.body.classList.add('loading');
}
function hideLoadingIndicator() {
    const indicator = document.getElementById('loading-indicator');
    if (indicator) {
        indicator.style.display = 'none';
    }
    
    // Remove loading class from body
    document.body.classList.remove('loading');
}
// Handle HTMX errors
function handleHTMXError(evt) {
    console.error('HTMX Request Error:', evt.detail);
    
    // Show error toast or message
    showErrorMessage('Request failed. Please try again.');
    
    hideLoadingIndicator();
}
// Utility functions
function showErrorMessage(message) {
    // Create toast element
    const toast = document.createElement('div');
    toast.className = 'toast align-items-center text-white bg-danger border-0';
    toast.setAttribute('role', 'alert');
    toast.setAttribute('aria-live', 'assertive');
    toast.setAttribute('aria-atomic', 'true');
    
    toast.innerHTML = `
        
    `;
    
    // Add to toast container or create one
    let toastContainer = document.getElementById('toast-container');
    if (!toastContainer) {
        toastContainer = document.createElement('div');
        toastContainer.id = 'toast-container';
        toastContainer.className = 'toast-container position-fixed top-0 end-0 p-3';
        toastContainer.style.zIndex = '1055';
        document.body.appendChild(toastContainer);
    }
    
    toastContainer.appendChild(toast);
    
    // Show toast
    const bsToast = new bootstrap.Toast(toast);
    bsToast.show();
    
    // Remove toast element after it's hidden
    toast.addEventListener('hidden.bs.toast', function() {
        toast.remove();
    });
}
function showSuccessMessage(message) {
    // Similar to showErrorMessage but with success styling
    const toast = document.createElement('div');
    toast.className = 'toast align-items-center text-white bg-success border-0';
    toast.setAttribute('role', 'alert');
    toast.setAttribute('aria-live', 'assertive');
    toast.setAttribute('aria-atomic', 'true');
    
    toast.innerHTML = `
        
    `;
    
    let toastContainer = document.getElementById('toast-container');
    if (!toastContainer) {
        toastContainer = document.createElement('div');
        toastContainer.id = 'toast-container';
        toastContainer.className = 'toast-container position-fixed top-0 end-0 p-3';
        toastContainer.style.zIndex = '1055';
        document.body.appendChild(toastContainer);
    }
    
    toastContainer.appendChild(toast);
    
    const bsToast = new bootstrap.Toast(toast);
    bsToast.show();
    
    toast.addEventListener('hidden.bs.toast', function() {
        toast.remove();
    });
}
// Format bytes for display
function formatBytes(bytes, decimals = 2) {
    if (bytes === 0) return '0 Bytes';
    
    const k = 1024;
    const dm = decimals < 0 ? 0 : decimals;
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
    
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    
    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
// Format numbers with commas
function formatNumber(num) {
    return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
// Helper function to format disk types for CSV export
function formatDiskTypes(diskTypesText) {
    // Remove any HTML tags and clean up the text
    return diskTypesText.replace(/<[^>]*>/g, '').replace(/\s+/g, ' ').trim();
}
// Confirm action dialogs
function confirmAction(message, callback) {
    if (confirm(message)) {
        callback();
    }
}
// Global error handler
window.addEventListener('error', function(e) {
    console.error('Global error:', e.error);
    showErrorMessage('An unexpected error occurred.');
});
// Export functions for global use
window.Dashboard = {
    showErrorMessage,
    showSuccessMessage,
    formatBytes,
    formatNumber,
    confirmAction
}; 
// Initialize event handlers
function initializeEventHandlers() {
    // S3 Bucket Management
    const createBucketForm = document.getElementById('createBucketForm');
    if (createBucketForm) {
        createBucketForm.addEventListener('submit', handleCreateBucket);
    }
    // Delete bucket buttons
    document.addEventListener('click', function(e) {
        if (e.target.closest('.delete-bucket-btn')) {
            const button = e.target.closest('.delete-bucket-btn');
            const bucketName = button.getAttribute('data-bucket-name');
            confirmDeleteBucket(bucketName);
        }
        
        // Quota management buttons
        if (e.target.closest('.quota-btn')) {
            const button = e.target.closest('.quota-btn');
            const bucketName = button.getAttribute('data-bucket-name');
            const currentQuota = parseInt(button.getAttribute('data-current-quota')) || 0;
            const quotaEnabled = button.getAttribute('data-quota-enabled') === 'true';
            showQuotaModal(bucketName, currentQuota, quotaEnabled);
        }
    });
    // Quota form submission
    const quotaForm = document.getElementById('quotaForm');
    if (quotaForm) {
        quotaForm.addEventListener('submit', handleUpdateQuota);
    }
    // Enable quota checkbox for create bucket form
    const enableQuotaCheckbox = document.getElementById('enableQuota');
    if (enableQuotaCheckbox) {
        enableQuotaCheckbox.addEventListener('change', function() {
            const quotaSettings = document.getElementById('quotaSettings');
            if (this.checked) {
                quotaSettings.style.display = 'block';
            } else {
                quotaSettings.style.display = 'none';
            }
        });
    }
    // Enable quota checkbox for quota modal
    const quotaEnabledCheckbox = document.getElementById('quotaEnabled');
    if (quotaEnabledCheckbox) {
        quotaEnabledCheckbox.addEventListener('change', function() {
            const quotaSizeSettings = document.getElementById('quotaSizeSettings');
            if (this.checked) {
                quotaSizeSettings.style.display = 'block';
            } else {
                quotaSizeSettings.style.display = 'none';
            }
        });
    }
}
// Setup form validation
function setupFormValidation() {
    // Bucket name validation
    const bucketNameInput = document.getElementById('bucketName');
    if (bucketNameInput) {
        bucketNameInput.addEventListener('input', validateBucketName);
    }
}
// S3 Bucket Management Functions
// Handle create bucket form submission
async function handleCreateBucket(event) {
    event.preventDefault();
    
    const form = event.target;
    const formData = new FormData(form);
    const bucketData = {
        name: formData.get('name'),
        region: formData.get('region') || 'us-east-1',
        quota_enabled: formData.get('quota_enabled') === 'on',
        quota_size: parseInt(formData.get('quota_size')) || 0,
        quota_unit: formData.get('quota_unit') || 'MB'
    };
    try {
        const response = await fetch('/api/s3/buckets', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(bucketData)
        });
        const result = await response.json();
        if (response.ok) {
            // Success
            showAlert('success', `Bucket "${bucketData.name}" created successfully!`);
            
            // Close modal
            const modal = bootstrap.Modal.getInstance(document.getElementById('createBucketModal'));
            modal.hide();
            
            // Reset form
            form.reset();
            
            // Refresh the page after a short delay
            setTimeout(() => {
                location.reload();
            }, 1500);
        } else {
            // Error
            showAlert('danger', result.error || 'Failed to create bucket');
        }
    } catch (error) {
        console.error('Error creating bucket:', error);
        showAlert('danger', 'Network error occurred while creating bucket');
    }
}
// Validate bucket name input
function validateBucketName(event) {
    const input = event.target;
    const value = input.value;
    const isValid = /^[a-z0-9.-]+$/.test(value) && value.length >= 3 && value.length <= 63;
    
    if (value.length > 0 && !isValid) {
        input.setCustomValidity('Bucket name must contain only lowercase letters, numbers, dots, and hyphens (3-63 characters)');
    } else {
        input.setCustomValidity('');
    }
}
// Confirm bucket deletion
function confirmDeleteBucket(bucketName) {
    bucketToDelete = bucketName;
    document.getElementById('deleteBucketName').textContent = bucketName;
    
    const modal = new bootstrap.Modal(document.getElementById('deleteBucketModal'));
    modal.show();
}
// Delete bucket
async function deleteBucket() {
    if (!bucketToDelete) {
        return;
    }
    try {
        const response = await fetch(`/api/s3/buckets/${bucketToDelete}`, {
            method: 'DELETE'
        });
        const result = await response.json();
        if (response.ok) {
            // Success
            showAlert('success', `Bucket "${bucketToDelete}" deleted successfully!`);
            
            // Close modal
            const modal = bootstrap.Modal.getInstance(document.getElementById('deleteBucketModal'));
            modal.hide();
            
            // Refresh the page after a short delay
            setTimeout(() => {
                location.reload();
            }, 1500);
        } else {
            // Error
            showAlert('danger', result.error || 'Failed to delete bucket');
        }
    } catch (error) {
        console.error('Error deleting bucket:', error);
        showAlert('danger', 'Network error occurred while deleting bucket');
    }
    bucketToDelete = '';
}
// Refresh buckets list
function refreshBuckets() {
    location.reload();
}
// Export bucket list
function exportBucketList() {
    // Get table data
    const table = document.getElementById('bucketsTable');
    if (!table) return;
    const rows = Array.from(table.querySelectorAll('tbody tr'));
    const data = rows.map(row => {
        const cells = row.querySelectorAll('td');
        if (cells.length < 5) return null; // Skip empty state row
        
        return {
            name: cells[0].textContent.trim(),
            created: cells[1].textContent.trim(),
            objects: cells[2].textContent.trim(),
            size: cells[3].textContent.trim(),
            quota: cells[4].textContent.trim()
        };
    }).filter(item => item !== null);
    // Convert to CSV
    const csv = [
        ['Name', 'Created', 'Objects', 'Size', 'Quota'].join(','),
        ...data.map(row => [
            row.name,
            row.created,
            row.objects,
            row.size,
            row.quota
        ].join(','))
    ].join('\n');
    // Download CSV
    const blob = new Blob([csv], { type: 'text/csv' });
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `seaweedfs-buckets-${new Date().toISOString().split('T')[0]}.csv`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    window.URL.revokeObjectURL(url);
}
// Show alert message
function showAlert(type, message) {
    // Remove existing alerts
    const existingAlerts = document.querySelectorAll('.alert-floating');
    existingAlerts.forEach(alert => alert.remove());
    // Create new alert
    const alert = document.createElement('div');
    alert.className = `alert alert-${type} alert-dismissible fade show alert-floating`;
    alert.style.cssText = `
        position: fixed;
        top: 20px;
        right: 20px;
        z-index: 9999;
        min-width: 300px;
        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    `;
    
    alert.innerHTML = `
        ${message}
        
                    Drop files here to upload 
                    Release to upload files to this directory
                 
            `;
            overlay.style.cssText = `
                position: absolute;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background: rgba(255, 255, 255, 0.9);
                border: 2px dashed #007bff;
                border-radius: 0.375rem;
                z-index: 1000;
                display: flex;
                align-items: center;
                justify-content: center;
            `;
            dropZone.style.position = 'relative';
            dropZone.appendChild(overlay);
        }
    }
    
    function unhighlight(e) {
        dropZone.classList.remove('drag-over');
        const overlay = dropZone.querySelector('.drag-overlay');
        if (overlay) {
            overlay.remove();
        }
    }
    
    function handleDrop(e) {
        const dt = e.dataTransfer;
        const files = dt.files;
        
        if (files.length > 0) {
            // Open upload modal and set files
            const fileInput = document.getElementById('fileInput');
            if (fileInput) {
                // Create a new FileList-like object
                const fileArray = Array.from(files);
                
                // Set files to input (this is a bit tricky with file inputs)
                const dataTransfer = new DataTransfer();
                fileArray.forEach(file => dataTransfer.items.add(file));
                fileInput.files = dataTransfer.files;
                
                // Update preview and show modal
                updateFileListPreview();
                const modal = new bootstrap.Modal(uploadModal);
                modal.show();
            }
        }
    }
}
// Update file list preview when files are selected
function updateFileListPreview() {
    const fileInput = document.getElementById('fileInput');
    const fileListPreview = document.getElementById('fileListPreview');
    const selectedFilesList = document.getElementById('selectedFilesList');
    
    if (!fileInput.files || fileInput.files.length === 0) {
        fileListPreview.style.display = 'none';
        return;
    }
    
    const files = Array.from(fileInput.files);
    const totalSize = files.reduce((sum, file) => sum + file.size, 0);
    
    let html = `
        ${files.length} file(s) selected 
        Total: ${formatBytes(totalSize)} 
    
`;
    
    files.forEach((file, index) => {
        const fileIcon = getFileIconByName(file.name);
        html += `
            
                ${file.name} 
            
            ${formatBytes(file.size)} 
         `;
    });
    
    selectedFilesList.innerHTML = html;
    fileListPreview.style.display = 'block';
}
// Get file icon based on file name/extension
function getFileIconByName(fileName) {
    const ext = fileName.split('.').pop().toLowerCase();
    
    switch (ext) {
        case 'jpg':
        case 'jpeg':
        case 'png':
        case 'gif':
        case 'bmp':
        case 'svg':
            return 'fa-image';
        case 'mp4':
        case 'avi':
        case 'mov':
        case 'wmv':
        case 'flv':
            return 'fa-video';
        case 'mp3':
        case 'wav':
        case 'flac':
        case 'aac':
            return 'fa-music';
        case 'pdf':
            return 'fa-file-pdf';
        case 'doc':
        case 'docx':
            return 'fa-file-word';
        case 'xls':
        case 'xlsx':
            return 'fa-file-excel';
        case 'ppt':
        case 'pptx':
            return 'fa-file-powerpoint';
        case 'txt':
        case 'md':
            return 'fa-file-text';
        case 'zip':
        case 'rar':
        case '7z':
        case 'tar':
        case 'gz':
            return 'fa-file-archive';
        case 'js':
        case 'ts':
        case 'html':
        case 'css':
        case 'json':
        case 'xml':
            return 'fa-file-code';
        default:
            return 'fa-file';
    }
}
// Quota Management Functions
// Show quota management modal
function showQuotaModal(bucketName, currentQuotaMB, quotaEnabled) {
    document.getElementById('quotaBucketName').value = bucketName;
    document.getElementById('quotaEnabled').checked = quotaEnabled;
    
    // Convert quota to appropriate unit and set values
    const quotaBytes = currentQuotaMB * 1024 * 1024; // Convert MB to bytes
    const { size, unit } = convertBytesToBestUnit(quotaBytes);
    
    document.getElementById('quotaSizeMB').value = size;
    document.getElementById('quotaUnitMB').value = unit;
    
    // Show/hide quota size settings based on enabled state
    const quotaSizeSettings = document.getElementById('quotaSizeSettings');
    if (quotaEnabled) {
        quotaSizeSettings.style.display = 'block';
    } else {
        quotaSizeSettings.style.display = 'none';
    }
    
    const modal = new bootstrap.Modal(document.getElementById('manageQuotaModal'));
    modal.show();
}
// Convert bytes to the best unit (TB, GB, or MB)
function convertBytesToBestUnit(bytes) {
    if (bytes === 0) {
        return { size: 0, unit: 'MB' };
    }
    
    // Check if it's a clean TB value
    if (bytes >= 1024 * 1024 * 1024 * 1024 && bytes % (1024 * 1024 * 1024 * 1024) === 0) {
        return { size: bytes / (1024 * 1024 * 1024 * 1024), unit: 'TB' };
    }
    
    // Check if it's a clean GB value
    if (bytes >= 1024 * 1024 * 1024 && bytes % (1024 * 1024 * 1024) === 0) {
        return { size: bytes / (1024 * 1024 * 1024), unit: 'GB' };
    }
    
    // Default to MB
    return { size: bytes / (1024 * 1024), unit: 'MB' };
}
// Handle quota update form submission
async function handleUpdateQuota(event) {
    event.preventDefault();
    
    const form = event.target;
    const formData = new FormData(form);
    const bucketName = document.getElementById('quotaBucketName').value;
    
    const quotaData = {
        quota_enabled: formData.get('quota_enabled') === 'on',
        quota_size: parseInt(formData.get('quota_size')) || 0,
        quota_unit: formData.get('quota_unit') || 'MB'
    };
    try {
        const response = await fetch(`/api/s3/buckets/${bucketName}/quota`, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(quotaData)
        });
        const result = await response.json();
        if (response.ok) {
            // Success
            showAlert('success', `Quota for bucket "${bucketName}" updated successfully!`);
            
            // Close modal
            const modal = bootstrap.Modal.getInstance(document.getElementById('manageQuotaModal'));
            modal.hide();
            
            // Refresh the page after a short delay
            setTimeout(() => {
                location.reload();
            }, 1500);
        } else {
            // Error
            showAlert('danger', result.error || 'Failed to update bucket quota');
        }
    } catch (error) {
        console.error('Error updating bucket quota:', error);
        showAlert('danger', 'Network error occurred while updating bucket quota');
    }
}
// Show file viewer modal
function showFileViewer(data) {
    const file = data.file;
    const content = data.content || '';
    const viewable = data.viewable !== false;
    
    // Create modal HTML
    const modalHtml = `
        
            
                
                    
                    
                        ${viewable ? createFileViewerContent(file, content) : createNonViewableContent(data.reason || 'File cannot be viewed')}
                    
                    
                 
             
         
    `;
    
    // Remove existing modal if any
    const existingModal = document.getElementById('fileViewerModal');
    if (existingModal) {
        existingModal.remove();
    }
    
    // Add modal to DOM
    document.body.insertAdjacentHTML('beforeend', modalHtml);
    
    // Show modal
    const modal = new bootstrap.Modal(document.getElementById('fileViewerModal'));
    modal.show();
    
    // Clean up when modal is hidden
    document.getElementById('fileViewerModal').addEventListener('hidden.bs.modal', function () {
        this.remove();
    });
}
// Create file viewer content based on file type
function createFileViewerContent(file, content) {
    if (file.mime.startsWith('image/')) {
        return `
            
        `;
    } else if (file.mime.startsWith('text/') || file.mime === 'application/json' || file.mime === 'application/javascript') {
        const language = getLanguageFromMime(file.mime, file.name);
        return `
            
                
                     
            
            ${escapeHtml(content)}
                
             
        `;
    } else {
        return createNonViewableContent('This file type cannot be previewed in the browser.');
    }
}
// Create non-viewable content message
function createNonViewableContent(reason) {
    return `
        
            Cannot preview file 
            ${reason}
         
    `;
}
// Get language for syntax highlighting
function getLanguageFromMime(mime, filename) {
    // First check MIME type
    switch (mime) {
        case 'application/json': return 'json';
        case 'application/javascript': return 'javascript';
        case 'text/html': return 'html';
        case 'text/css': return 'css';
        case 'application/xml': return 'xml';
        case 'text/typescript': return 'typescript';
        case 'text/x-python': return 'python';
        case 'text/x-go': return 'go';
        case 'text/x-java': return 'java';
        case 'text/x-c': return 'c';
        case 'text/x-c++': return 'cpp';
        case 'text/x-c-header': return 'c';
        case 'text/x-shellscript': return 'bash';
        case 'text/x-php': return 'php';
        case 'text/x-ruby': return 'ruby';
        case 'text/x-perl': return 'perl';
        case 'text/x-rust': return 'rust';
        case 'text/x-swift': return 'swift';
        case 'text/x-kotlin': return 'kotlin';
        case 'text/x-scala': return 'scala';
        case 'text/x-dockerfile': return 'dockerfile';
        case 'text/yaml': return 'yaml';
        case 'text/csv': return 'csv';
        case 'text/sql': return 'sql';
        case 'text/markdown': return 'markdown';
    }
    
    // Fallback to file extension
    const ext = filename.split('.').pop().toLowerCase();
    switch (ext) {
        case 'js': case 'mjs': return 'javascript';
        case 'ts': return 'typescript';
        case 'py': return 'python';
        case 'go': return 'go';
        case 'java': return 'java';
        case 'cpp': case 'cc': case 'cxx': case 'c++': return 'cpp';
        case 'c': return 'c';
        case 'h': case 'hpp': return 'c';
        case 'sh': case 'bash': case 'zsh': case 'fish': return 'bash';
        case 'php': return 'php';
        case 'rb': return 'ruby';
        case 'pl': return 'perl';
        case 'rs': return 'rust';
        case 'swift': return 'swift';
        case 'kt': return 'kotlin';
        case 'scala': return 'scala';
        case 'yml': case 'yaml': return 'yaml';
        case 'md': case 'markdown': return 'markdown';
        case 'sql': return 'sql';
        case 'csv': return 'csv';
        case 'dockerfile': return 'dockerfile';
        case 'gitignore': case 'gitattributes': return 'text';
        case 'env': return 'bash';
        case 'cfg': case 'conf': case 'ini': case 'properties': return 'ini';
        default: return 'text';
    }
}
// Show properties modal
function showPropertiesModal(properties) {
    // Create modal HTML
    const modalHtml = `
        
            
                
                    
                    
                        ${createPropertiesContent(properties)}
                    
                    
                 
             
         
    `;
    
    // Remove existing modal if any
    const existingModal = document.getElementById('propertiesModal');
    if (existingModal) {
        existingModal.remove();
    }
    
    // Add modal to DOM
    document.body.insertAdjacentHTML('beforeend', modalHtml);
    
    // Show modal
    const modal = new bootstrap.Modal(document.getElementById('propertiesModal'));
    modal.show();
    
    // Clean up when modal is hidden
    document.getElementById('propertiesModal').addEventListener('hidden.bs.modal', function () {
        this.remove();
    });
}
// Create properties content
function createPropertiesContent(properties) {
    let html = `
        
            
                
                    Name: ${properties.name} Full Path: ${properties.full_path}Type: ${properties.is_directory ? 'Directory' : 'File'} Size: ${properties.size_formatted || formatBytes(properties.size || 0)} MIME Type: ${properties.mime_type || 'Unknown'} 
             
            
                
    `;
    
    if (properties.modified_time) {
        html += `Modified: ${properties.modified_time} Created: ${properties.created_time} 
                
                
                    Mode: ${properties.file_mode_formatted || properties.file_mode}UID: ${properties.uid || 'N/A'} GID: ${properties.gid || 'N/A'} 
             
         
    `;
    
    // Add TTL information if available
    if (properties.ttl_seconds && properties.ttl_seconds > 0) {
        html += `
            
                
                    
                        TTL: ${properties.ttl_formatted || properties.ttl_seconds + ' seconds'} 
                 
             
        `;
    }
    
    // Add chunk information if available
    if (properties.chunks && properties.chunks.length > 0) {
        html += `
            
                
                    
                        
                            
                                
                                    File ID 
                                    Offset 
                                    Size 
                                    ETag 
                                 
                             
                            
        `;
        
        properties.chunks.forEach(chunk => {
            html += `
                                
                                    ${chunk.file_id}${formatBytes(chunk.offset)} 
                                    ${formatBytes(chunk.size)} 
                                    ${chunk.e_tag || 'N/A'} 
            `;
        });
        
        html += `
                             
                        
                     
                 
             
        `;
    }
    
    // Add extended attributes if available
    if (properties.extended && Object.keys(properties.extended).length > 0) {
        html += `
            
                
                    
        `;
        
        Object.entries(properties.extended).forEach(([key, value]) => {
            html += `${key}: ${value} 
                 
             
        `;
    }
    
    return html;
}
// Utility function to escape HTML
function escapeHtml(text) {
    var map = {
        '&': '&',
        '<': '<',
        '>': '>',
        '"': '"',
        "'": '''
    };
    return text.replace(/[&<>"']/g, function(m) { return map[m]; });
}
// ============================================================================
// USER MANAGEMENT FUNCTIONS
// ============================================================================
// Global variables for user management
let currentEditingUser = '';
let currentAccessKeysUser = '';
// User Management Functions
async function handleCreateUser() {
    const form = document.getElementById('createUserForm');
    const formData = new FormData(form);
    
    // Get selected actions
    const actionsSelect = document.getElementById('actions');
    const selectedActions = Array.from(actionsSelect.selectedOptions).map(option => option.value);
    
    const userData = {
        username: formData.get('username'),
        email: formData.get('email'),
        actions: selectedActions,
        generate_key: formData.get('generateKey') === 'on'
    };
    
    try {
        const response = await fetch('/api/users', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(userData)
        });
        
        if (response.ok) {
            const result = await response.json();
            showSuccessMessage('User created successfully');
            
            // Show the created access key if generated
            if (result.user && result.user.access_key) {
                showNewAccessKeyModal(result.user);
            }
            
            // Close modal and refresh page
            const modal = bootstrap.Modal.getInstance(document.getElementById('createUserModal'));
            modal.hide();
            form.reset();
            setTimeout(() => window.location.reload(), 1000);
        } else {
            const error = await response.json();
            showErrorMessage('Failed to create user: ' + (error.error || 'Unknown error'));
        }
    } catch (error) {
        console.error('Error creating user:', error);
        showErrorMessage('Failed to create user: ' + error.message);
    }
}
async function editUser(username) {
    currentEditingUser = username;
    
    try {
        const response = await fetch(`/api/users/${username}`);
        if (response.ok) {
            const user = await response.json();
            
            // Populate edit form
            document.getElementById('editUsername').value = username;
                document.getElementById('editEmail').value = user.email || '';
            
            // Set selected actions
            const actionsSelect = document.getElementById('editActions');
            Array.from(actionsSelect.options).forEach(option => {
                option.selected = user.actions && user.actions.includes(option.value);
            });
            
            // Show modal
            const modal = new bootstrap.Modal(document.getElementById('editUserModal'));
            modal.show();
        } else {
            showErrorMessage('Failed to load user details');
        }
    } catch (error) {
        console.error('Error loading user:', error);
        showErrorMessage('Failed to load user details');
    }
}
async function handleUpdateUser() {
    const form = document.getElementById('editUserForm');
    const formData = new FormData(form);
    
    // Get selected actions
    const actionsSelect = document.getElementById('editActions');
    const selectedActions = Array.from(actionsSelect.selectedOptions).map(option => option.value);
    
    const userData = {
        email: formData.get('email'),
        actions: selectedActions
    };
    
    try {
        const response = await fetch(`/api/users/${currentEditingUser}`, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(userData)
        });
        
        if (response.ok) {
            showSuccessMessage('User updated successfully');
            
            // Close modal and refresh page
            const modal = bootstrap.Modal.getInstance(document.getElementById('editUserModal'));
            modal.hide();
            setTimeout(() => window.location.reload(), 1000);
        } else {
            const error = await response.json();
            showErrorMessage('Failed to update user: ' + (error.error || 'Unknown error'));
        }
    } catch (error) {
        console.error('Error updating user:', error);
        showErrorMessage('Failed to update user: ' + error.message);
    }
}
function confirmDeleteUser(username) {
    confirmAction(
        `Are you sure you want to delete user "${username}"? This action cannot be undone.`,
        () => deleteUserConfirmed(username)
    );
}
function deleteUser(username) {
    confirmDeleteUser(username);
}
async function deleteUserConfirmed(username) {
    try {
        const response = await fetch(`/api/users/${username}`, {
            method: 'DELETE'
        });
        
        if (response.ok) {
            showSuccessMessage('User deleted successfully');
            setTimeout(() => window.location.reload(), 1000);
        } else {
            const error = await response.json();
            showErrorMessage('Failed to delete user: ' + (error.error || 'Unknown error'));
        }
    } catch (error) {
        console.error('Error deleting user:', error);
        showErrorMessage('Failed to delete user: ' + error.message);
    }
}
async function showUserDetails(username) {
    try {
        const response = await fetch(`/api/users/${username}`);
        if (response.ok) {
            const user = await response.json();
            
            const content = createUserDetailsContent(user);
            document.getElementById('userDetailsContent').innerHTML = content;
            
            const modal = new bootstrap.Modal(document.getElementById('userDetailsModal'));
            modal.show();
        } else {
            showErrorMessage('Failed to load user details');
        }
    } catch (error) {
        console.error('Error loading user details:', error);
        showErrorMessage('Failed to load user details');
    }
}
function createUserDetailsContent(user) {
    return `
        
            
                Basic Information 
                
                    
                        Username: ${escapeHtml(user.username)} 
                     
                    
                        Email: ${escapeHtml(user.email || 'Not set')} 
                     
                
             
            
                Permissions 
                
                    ${user.actions && user.actions.length > 0 ? 
                        user.actions.map(action => `${action} `).join('') :
                        'No permissions assigned '
                    }
                
                
                Access Keys 
                ${user.access_keys && user.access_keys.length > 0 ? 
                    createAccessKeysTable(user.access_keys) :
                    '
No access keys
'
                }
            
 
         
    `;
}
function createAccessKeysTable(accessKeys) {
    return `
        
            
                
                    
                        Access Key 
                        Created 
                     
                 
                
                    ${accessKeys.map(key => `
                        
                            ${key.access_key}${new Date(key.created_at).toLocaleDateString()} 
                         
                    `).join('')}
                 
            
         
    `;
}
async function manageAccessKeys(username) {
    currentAccessKeysUser = username;
    document.getElementById('accessKeysUsername').textContent = username;
    
    await loadAccessKeys(username);
    
    const modal = new bootstrap.Modal(document.getElementById('accessKeysModal'));
    modal.show();
}
async function loadAccessKeys(username) {
    try {
        const response = await fetch(`/api/users/${username}`);
        if (response.ok) {
            const user = await response.json();
            
            const content = createAccessKeysManagementContent(user.access_keys || []);
            document.getElementById('accessKeysContent').innerHTML = content;
        } else {
            document.getElementById('accessKeysContent').innerHTML = 'Failed to load access keys
';
        }
    } catch (error) {
        console.error('Error loading access keys:', error);
        document.getElementById('accessKeysContent').innerHTML = 'Error loading access keys
';
    }
}
function createAccessKeysManagementContent(accessKeys) {
    if (accessKeys.length === 0) {
        return 'No access keys found. Create one to get started.
';
    }
    
    return `
        
            
                
                    
                        Access Key 
                        Secret Key 
                        Created 
                        Actions 
                     
                 
                
                    ${accessKeys.map(key => `
                        
                            
                                ${key.access_key}
                                
                                     
                             
                            
                                ••••••••••••••••
                                
                                     
                             
                            ${new Date(key.created_at).toLocaleDateString()} 
                            
                                
                                     
                             
                         
                    `).join('')}
                 
            
         
    `;
}
async function createAccessKey() {
    if (!currentAccessKeysUser) {
        showErrorMessage('No user selected');
        return;
    }
    
    try {
        const response = await fetch(`/api/users/${currentAccessKeysUser}/access-keys`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            }
        });
        
        if (response.ok) {
            const result = await response.json();
            showSuccessMessage('Access key created successfully');
            
            // Show the new access key
            showNewAccessKeyModal(result.access_key);
            
            // Reload access keys
            await loadAccessKeys(currentAccessKeysUser);
        } else {
            const error = await response.json();
            showErrorMessage('Failed to create access key: ' + (error.error || 'Unknown error'));
        }
    } catch (error) {
        console.error('Error creating access key:', error);
        showErrorMessage('Failed to create access key: ' + error.message);
    }
}
function confirmDeleteAccessKey(accessKeyId) {
    confirmAction(
        `Are you sure you want to delete access key "${accessKeyId}"? This action cannot be undone.`,
        () => deleteAccessKeyConfirmed(accessKeyId)
    );
}
async function deleteAccessKeyConfirmed(accessKeyId) {
    try {
        const response = await fetch(`/api/users/${currentAccessKeysUser}/access-keys/${accessKeyId}`, {
            method: 'DELETE'
        });
        
        if (response.ok) {
            showSuccessMessage('Access key deleted successfully');
            
            // Reload access keys
            await loadAccessKeys(currentAccessKeysUser);
        } else {
            const error = await response.json();
            showErrorMessage('Failed to delete access key: ' + (error.error || 'Unknown error'));
        }
    } catch (error) {
        console.error('Error deleting access key:', error);
        showErrorMessage('Failed to delete access key: ' + error.message);
    }
}
function showSecretKey(accessKey, secretKey) {
    const content = `
        
            Access Key Details:  These credentials provide access to your object storage. Keep them secure and don't share them.
        
        
        
    `;
    
    showModal('Access Key Details', content);
}
function showNewAccessKeyModal(accessKeyData) {
    const content = `
        
            Success!  Your new access key has been created.
        
        
            Important:  These credentials provide access to your object storage. Keep them secure and don't share them. You can view them again through the user management interface if needed.
        
        
        
    `;
    
    showModal('New Access Key Created', content);
}
function showModal(title, content) {
    // Create a dynamic modal
    const modalId = 'dynamicModal_' + Date.now();
    const modalHtml = `
        
    `;
    
    // Add modal to body
    document.body.insertAdjacentHTML('beforeend', modalHtml);
    
    // Show modal
    const modal = new bootstrap.Modal(document.getElementById(modalId));
    modal.show();
    
    // Remove modal from DOM when hidden
    document.getElementById(modalId).addEventListener('hidden.bs.modal', function() {
        this.remove();
    });
}