#!/usr/bin/env node
/**
 * SaltyFace Web App Server — Serves static HTML/JS to Chromium kiosk
 *
 * Lightweight HTTP server for SaltyFace web UI
 * - Runs on localhost:3000 (configurable)
 * - Serves public/ directory
 * - Enables CORS for ROS bridge WebSocket
 * - Suitable for systemd service or ROS2 launch
 *
 * Usage:
 *   node server.js [--port 3000] [--host 127.0.0.1]
 */

const http = require('http');
const fs = require('fs');
const path = require('path');
const url = require('url');

// Configuration
const PORT = parseInt(process.argv.find(arg => arg.startsWith('--port='))?.split('=')[1] || 3000);
const HOST = process.argv.find(arg => arg.startsWith('--host='))?.split('=')[1] || '0.0.0.0';
const PUBLIC_DIR = path.join(__dirname, 'public');

// MIME types
const MIME_TYPES = {
    '.html': 'text/html; charset=utf-8',
    '.js': 'application/javascript; charset=utf-8',
    '.css': 'text/css; charset=utf-8',
    '.json': 'application/json',
    '.png': 'image/png',
    '.jpg': 'image/jpeg',
    '.gif': 'image/gif',
    '.svg': 'image/svg+xml',
    '.woff': 'font/woff',
    '.woff2': 'font/woff2',
    '.ttf': 'font/ttf',
};

// HTTP server
const server = http.createServer((req, res) => {
    // CORS headers for ROS bridge
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, HEAD, OPTIONS');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

    if (req.method === 'OPTIONS') {
        res.writeHead(200);
        res.end();
        return;
    }

    // Parse request URL
    const parsedUrl = url.parse(req.url, true);
    let pathname = parsedUrl.pathname;

    // Default to index.html for root
    if (pathname === '/') {
        pathname = '/index.html';
    }

    // Security: prevent directory traversal
    const filePath = path.normalize(path.join(PUBLIC_DIR, pathname));
    if (!filePath.startsWith(PUBLIC_DIR)) {
        res.writeHead(403, { 'Content-Type': 'text/plain' });
        res.end('Access denied');
        return;
    }

    // Check if file exists
    fs.stat(filePath, (err, stats) => {
        if (err || !stats.isFile()) {
            // File not found
            console.log(`[SaltyFace] 404 ${pathname}`);
            res.writeHead(404, { 'Content-Type': 'text/plain' });
            res.end('File not found');
            return;
        }

        // Determine MIME type
        const ext = path.extname(filePath).toLowerCase();
        const mimeType = MIME_TYPES[ext] || 'application/octet-stream';

        // Serve file
        res.writeHead(200, {
            'Content-Type': mimeType,
            'Content-Length': stats.size,
            'Cache-Control': 'public, max-age=3600',
        });

        fs.createReadStream(filePath).pipe(res);
        console.log(`[SaltyFace] 200 ${pathname} (${mimeType})`);
    });
});

// Start server
server.listen(PORT, HOST, () => {
    console.log(`
╔═══════════════════════════════════════════════════════════╗
║  SaltyFace Web App Server — Running                       ║
║  URL: http://${HOST === '0.0.0.0' ? 'localhost' : HOST}:${PORT}         │
║  Root: ${PUBLIC_DIR}        │
║  Serving SaltyFace UI for Chromium kiosk                  ║
╚═══════════════════════════════════════════════════════════╝
    `);
});

// Graceful shutdown
process.on('SIGINT', () => {
    console.log('\n[SaltyFace] Shutting down...');
    server.close(() => {
        console.log('[SaltyFace] Server closed');
        process.exit(0);
    });
});

process.on('SIGTERM', () => {
    console.log('[SaltyFace] Received SIGTERM, shutting down...');
    server.close(() => {
        console.log('[SaltyFace] Server closed');
        process.exit(0);
    });
});

// Error handling
process.on('uncaughtException', (err) => {
    console.error('[SaltyFace] Uncaught exception:', err);
    process.exit(1);
});
