/**
 * Filename: CircleWebDemo.js
 * Origin Date: 2025-04-03
 * Description: This file contains the main logic for the SmartCardReader web application.
 * It handles the WebSocket connection to the smart card reader, manages the UI elements,
 * and processes user commands.
 */

// Import the SmartCardReader library for smart card interactions
import SmartCardReader from './SmartCardReader.js';

// Initialize the SmartCardReader instance with the WebSocket server URL
const smartCardReader = new SmartCardReader('ws://127.0.0.1:55002');
let readerCount = 1; // Tracks the number of reader boxes for unique IDs

/**
 * Formats an input field’s APDU or control command as uppercase hex with spaces.
 * @param {HTMLInputElement} inputElement - Input element to format.
 * @example
 * // Input: '00a40400' → Output: '00 A4 04 00'
 */
function formatAPDUCommand(inputElement) {
        const initialCursorPosition = inputElement.selectionStart;
        const userCommand = inputElement.value.toUpperCase();
        const cleanCommand = userCommand.replace(/[^0-9A-F]/g, '');
        const formattedCommand = cleanCommand.replace(/(.{2})(?!$)/g, '$1 ');
   
        // Count invalid characters before cursor
        const charsBeforeCursor = userCommand.slice(0, initialCursorPosition);
        const invalidCharsBeforeCursor = (charsBeforeCursor.match(/[^0-9A-F]/g) || []).length;
   
        // Count valid characters before cursor
        const validCharsBeforeCursor = charsBeforeCursor.replace(/[^0-9A-F]/g, '').length;
   
        // Calculate spaces added before cursor
        const addSpaceBeforeCursor = validCharsBeforeCursor >= 1 ? Math.floor((validCharsBeforeCursor - 1) / 2) : 0;
   
        // Calculate new cursor position
        const newCursorPosition = initialCursorPosition - invalidCharsBeforeCursor + addSpaceBeforeCursor;
   
        inputElement.value = formattedCommand;
        inputElement.setSelectionRange(newCursorPosition, newCursorPosition);
}

/**
 * Sets up event handlers for a reader box’s interactive elements.
 * @param {number} readerNumber - Unique identifier for the reader box.
 */
function setupReaderHandlers(readerNumber) {
    // DOM elements for the reader box
    const apduInput = document.getElementById(`APDUcommandInput${readerNumber}`);
    const sendApduBtn = document.getElementById(`sendAPDUCommandButton${readerNumber}`);
    const escapeInput = document.getElementById(`EscapecommandInput${readerNumber}`);
    const sendEscapeBtn = document.getElementById(`sendEscapeCommandButton${readerNumber}`);
    const connectBtn = document.getElementById(`connectButton${readerNumber}`);
    const refreshBtn = document.getElementById(`refreshButton${readerNumber}`);
    const deleteBtn = document.getElementById(`deleteButton${readerNumber}`);
    const readerDropdown = document.getElementById(`readerDropdown${readerNumber}`);
    const responseDiv = document.getElementById(`response${readerNumber}`);

    // Populate reader dropdown on initialization
    smartCardReader.refreshReader(`readerDropdown${readerNumber}`);

    // Format APDU/Escape inputs as uppercase hex with spaces
    apduInput?.addEventListener('input', function () {
        formatAPDUCommand(this);
    });
    escapeInput?.addEventListener('input', function () {
        formatAPDUCommand(this);
    });

    // Send APDU command
    sendApduBtn?.addEventListener("click", async () => {
        const command = apduInput.value.trim();
        if (!command) return alert('Please enter an APDU command');
        await smartCardReader.sendAPDUcommandWithUI(command, `readerDropdown${readerNumber}`);
    });

    // Send Escape command
    sendEscapeBtn?.addEventListener("click", async () => {
        const command = escapeInput.value.trim();
        if (!command) return alert('Please enter an Escape command');
        await smartCardReader.sendControlcommandWithUI(command, `readerDropdown${readerNumber}`);
    });

    // Toggle connect/disconnect
    connectBtn?.addEventListener("click", async () => {
        const isDirectMode = document.getElementById(`directMode${readerNumber}`).checked;
        const isT0Protocol = document.getElementById(`t0protocol${readerNumber}`).checked;
        const mode = isDirectMode ? 'direct' : 'shared';
        const protocol = isT0Protocol ? 't0' : 't1';
        const readerName = readerDropdown.value;

        if (!readerName) return alert('Please select a reader first!');

        try {
            if (connectBtn.textContent.trim() === 'Connect') {
                await smartCardReader.connectWithUI(`readerDropdown${readerNumber}`, mode, protocol);
            } else {
                await smartCardReader.disconnectWithUI(`readerDropdown${readerNumber}`, mode);
            }
            // Update button states based on mode
            sendApduBtn.disabled = mode === 'direct';
            sendEscapeBtn.disabled = mode !== 'direct';
        } catch (error) {
            responseDiv.textContent = error.message;
            console.error('Connection error:', error);
        }
    });

    // Refresh reader list
    refreshBtn?.addEventListener('click', () => {
        smartCardReader.refreshReader(`readerDropdown${readerNumber}`);
    });

    // Delete reader box
    deleteBtn?.addEventListener("click", () => {
        if (confirm(`Delete Reader ${readerNumber}?`)) {
            deleteReaderBox(readerNumber);
        }
    });
}

/**
 * Populates the reader info table with real-time data from the WebSocket.
 * @param {Array} readers - Array of reader objects {readername, status, atr}.
 */
function populateReaderInfoBox(readers) {
    const tableBody = document.querySelector('#readerInfoTable tbody');
    tableBody.innerHTML = ''; // Clear existing rows
    readers.forEach(reader => {
        const row = document.createElement('tr');
        row.innerHTML = `
            <td>${reader.readername}</td>
            <td>${reader.status === 'direct connected' ? '-' : (reader.atr || 'No card detected')}</td>
            <td>${reader.status || 'Disconnected'}</td>
        `;
        tableBody.appendChild(row);
    });
}

// Listen for WebSocket reader updates
window.addEventListener('readerUpdate', (event) => {
    populateReaderInfoBox(event.detail);
});

/**
 * Handles dark mode toggle functionality.
 */
document.addEventListener("DOMContentLoaded", () => {
    const toggleSwitch = document.getElementById("darkModeToggle");
    const body = document.body;

    // Load saved theme
    if (localStorage.getItem("theme") === "dark") {
        body.classList.add("dark-mode");
        toggleSwitch.checked = true;
    }

    // Toggle theme on switch change
    toggleSwitch.addEventListener("change", () => {
        body.classList.toggle("dark-mode", toggleSwitch.checked);
        localStorage.setItem("theme", toggleSwitch.checked ? "dark" : "light");
    });
});

// Add reader box on button click
document.getElementById("addReaderButton").addEventListener("click", addReaderBox);

/**
 * Deletes a reader box and disconnects if necessary.
 * @param {number} readerNumber - Reader box ID to delete.
 */
function deleteReaderBox(readerNumber) {
    const readerBox = document.getElementById(`readerBox${readerNumber}`);
    if (!readerBox) return console.warn(`Reader box ${readerNumber} not found`);

    const connectBtn = document.getElementById(`connectButton${readerNumber}`);
    const readerDropdown = document.getElementById(`readerDropdown${readerNumber}`);
    if (connectBtn?.textContent.trim() === 'Disconnect' && readerDropdown.value) {
        smartCardReader.disconnect(readerDropdown.value).catch(error =>
            console.error(`Error disconnecting reader ${readerNumber}:`, error)
        );
    }
    readerBox.remove();
    console.log(`Reader box ${readerNumber} deleted`);
}

/**
 * Adds a new reader box to the UI with controls.
 */
async function addReaderBox() {
    const readerContainer = document.getElementById("readerContainer");
    const currentReaderNumber = readerCount++;

    const readerBox = document.createElement("div");
    readerBox.id = `readerBox${currentReaderNumber}`;
    readerBox.className = "reader-box";
    readerBox.innerHTML = `
        <button id="deleteButton${currentReaderNumber}" class="delete-button" title="Delete Reader">×</button>
        <h2 class="section-title">Reader ${currentReaderNumber}</h2>
        <label for="readerDropdown${currentReaderNumber}">Select Reader:</label>
        <select id="readerDropdown${currentReaderNumber}">
            <option value="" disabled selected>Select a reader</option>
        </select>
        <button id="refreshButton${currentReaderNumber}">Refresh Readers</button>
        <div class="radio-group">
            <span class="radio-text">Connection Mode:</span>
            <label class="radio-label">
                <input type="radio" id="sharedMode${currentReaderNumber}" name="mode${currentReaderNumber}" value="shared" checked>
                Shared Mode
            </label>
            <label class="radio-label">
                <input type="radio" id="directMode${currentReaderNumber}" name="mode${currentReaderNumber}" value="direct">
                Direct Mode
            </label>
        </div>
        <div class="radio-group">
            <span class="radio-text">Protocol:</span>
            <label class="radio-label">
                <input type="radio" id="t0protocol${currentReaderNumber}" name="protocol${currentReaderNumber}" value="t0" checked>
                T0
            </label>
            <label class="radio-label">
                <input type="radio" id="t1protocol${currentReaderNumber}" name="protocol${currentReaderNumber}" value="t1">
                T1
            </label>
            <button id="connectButton${currentReaderNumber}">Connect</button>
        </div>
        <div class="command-group">
            <label for="APDUcommandInput${currentReaderNumber}">APDU Command:</label>
            <input type="text" id="APDUcommandInput${currentReaderNumber}" placeholder="Enter APDU command">
            <button id="sendAPDUCommandButton${currentReaderNumber}">Send Command</button>
        </div>
        <div class="command-group">
            <label for="EscapecommandInput${currentReaderNumber}">Escape Command:</label>
            <input type="text" id="EscapecommandInput${currentReaderNumber}" placeholder="Enter Escape command">
            <button id="sendEscapeCommandButton${currentReaderNumber}">Send Escape Command</button>
        </div>
        <div id="response-group">
            <div id="response${currentReaderNumber}">Response will appear here.</div>
        </div>
    `;

    readerContainer.appendChild(readerBox);
    setupReaderHandlers(currentReaderNumber);
}
// Initialize app on load
window.onload = () => {
    addReaderBox(); // Add initial reader box
};