there current source code for my Dream Operating Environment , single file version. it's an example of what is possible with gemini.

 <!--
  Copyright (c) 2026 Nicholas Paul Wilde. All rights reserved.
  DreamOS Server Edition - Modular Microkernel Loader
-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>DreamOS Gold - Server Edition</title>
    <style>
/* Basic Reset & Body */
body, html {
    margin: 0;
    padding: 0;
    height: 100%;
    width: 100%;
    overflow: hidden;
    font-family: 'Consolas', 'Courier New', monospace;
    background-color: #010115; /* Dark blue background */
    color: #c0c0c0;
}

/* Desktop Area */
#desktop {
    position: relative;
    width: 100%;
    height: calc(100% - 30px); /* Full height minus taskbar */
}

/* Taskbar */
#taskbar {
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 30px;
    background-color: #1c1c1c;
    border-top: 1px solid #444;
    display: flex;
    align-items: center;
    padding: 0 5px;
    box-sizing: border-box;
    z-index: 1000;
}

#start-btn {
    background-color: #333;
    border: 1px solid #555;
    color: white;
    padding: 2px 10px;
    cursor: pointer;
}

#start-menu {
    position: fixed;
    bottom: 30px;
    left: 0;
    background-color: #2a2a2a;
    border: 1px solid #555;
    padding: 5px;
    z-index: 999;
}
#start-menu ul { list-style: none; margin: 0; padding: 0; }
#start-menu li { padding: 5px 10px; cursor: pointer; }
#start-menu li:hover { background-color: #444; }

.taskbar-divider {
    width: 1px;
    height: 20px;
    background-color: #444;
    margin: 0 10px;
}

#clock {
    margin-left: auto;
    padding-right: 10px;
}

#vdd-status {
    padding-right: 10px;
}

/* App Windows */
.app-window {
    position: absolute;
    top: 50px;
    left: 50px;
    width: 600px;
    height: 400px;
    background-color: #1e1e1e;
    border: 1px solid #555;
    box-shadow: 5px 5px 15px rgba(0,0,0,0.5);
    display: flex;
    flex-direction: column;
    z-index: 100;
}

.window-header {
    background-color: #333;
    color: white;
    padding: 5px;
    cursor: move; /* For future drag functionality */
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.window-controls {
    display: flex;
    gap: 3px;
}

.window-controls button {
    background-color: #555;
    color: white;
    border: 1px solid #777;
    width: 20px;
    height: 20px;
    line-height: 18px;
    text-align: center;
    padding: 0;
    font-family: 'Consolas', 'Courier New', monospace;
    cursor: pointer;
}

.window-close-btn {
    background-color: #c00;
    color: white;
    border: none;
    width: 20px;
    height: 20px;
    cursor: pointer;
}

.window-content {
    flex-grow: 1;
    padding: 10px;
    overflow: auto;
    display: flex;
    flex-direction: column;
}

/* Terminal Specific */
#terminal-window {
    width: 80vw;
    height: 80vh;
    top: 10vh;
    left: 10vw;
}
.app-window.minimized {
    display: none;
}

#output {
    flex-grow: 1;
    white-space: pre-wrap;
    word-break: break-all;
}

#prompt {
    display: flex;
}

#command-input {
    flex-grow: 1;
    border: none;
    background: transparent;
    color: #c0c0c0;
    font-family: inherit;
    font-size: inherit;
    outline: none;
}

.prompt { color: #00aa00; }

/* Editor & IDE Specific */
.editor-area, #js-ide-code {
    width: 100%;
    height: 100%;
    flex-grow: 1;
    background-color: #282c34;
    color: #abb2bf;
    border: none;
    font-family: inherit;
    resize: none;
    box-sizing: border-box;
}

.editor-toolbar, .ide-toolbar {
    padding-bottom: 10px;
    display: flex;
    gap: 10px;
    align-items: center;
}
.editor-toolbar input, .ide-toolbar input {
    flex-grow: 1;
    background-color: #333;
    border: 1px solid #555;
    color: white;
    padding: 2px;
}
.editor-toolbar button, .ide-toolbar button {
    background-color: #444;
    border: 1px solid #666;
    color: white;
    padding: 2px 8px;
}

#editor-status-bar, #dreamscript-ide-output {
    height: 40px;
    background-color: #222;
    padding: 5px;
    overflow-y: auto;
    margin-top: 5px;
    white-space: pre-wrap;
}

/* DreamScript IDE Syntax Highlighting */
.ide-editor-container {
    position: relative;
    flex-grow: 1;
    background-color: #282c34; /* Background on container */
}

/* Both textarea and pre need to be layered */
.ide-editor-container > textarea,
.ide-editor-container > pre {
    margin: 0;
    padding: 5px;
    box-sizing: border-box;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border: none;
    font-family: inherit;
    font-size: inherit;
    line-height: 1.4; /* Adjust for best line-to-line match */
    white-space: pre;
    word-break: normal;
    overflow-wrap: break-word;
    background: transparent; /* Both are transparent */
}

/* The actual textarea is on top, but its text is invisible */
#dreamscript-ide-code {
    z-index: 1;
    color: transparent;
    caret-color: white; /* Make the cursor visible */
    resize: none;
}

/* The highlighting <pre> is underneath and not interactive */
#dreamscript-ide-highlighting {
    z-index: 0;
    pointer-events: none;
}

/* Utility */
.hidden {
    display: none !important;
}

/* Main Frame for apps */
#main-frame {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border: none;
    z-index: 50;
}

#vdd-overlay {
    position: fixed;
    top: 0;
    right: 0;
    background: rgba(0,0,0,0.5);
    color: lime;
    padding: 2px 5px;
    font-size: 10px;
    z-index: 2000;
}

.app-window.maximized {
    top: 0 !important;
    left: 0 !important;
    width: 100% !important;
    height: 100% !important;
    border: none;
    box-shadow: none;
}

#taskbar-apps {
    display: flex;
    height: 100%;
    align-items: center;
    gap: 5px;
    margin-left: 5px;
}

.taskbar-item {
    background-color: #4a4a4a;
    color: white;
    padding: 4px 12px;
    border: 1px solid #666;
    cursor: pointer;
    font-size: 12px;
    white-space: nowrap;
    border-radius: 2px;
}

/* Syntax highlighting colors for DreamScript */
.ds-keyword { color: #569cd6; font-weight: bold; }
.ds-string { color: #ce9178; }
.ds-comment { color: #6a9955; font-style: italic; }
.ds-linenumber { color: #608b4e; }
.ds-variable { color: #9cdcfe; }
.ds-number { color: #b5cea8; }

/* DreamScript IDE Help Window Content */
#dreamscript-help-content {
    background-color: #fdfdfd;
    color: #111;
    padding: 15px;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    line-height: 1.6;
}
#dreamscript-help-content h2, #dreamscript-help-content h3 {
    border-bottom: 1px solid #ccc;
    padding-bottom: 5px;
    margin-top: 20px;
    color: #005a9e;
}
#dreamscript-help-content pre {
    background-color: #e7e7e7;
    padding: 10px;
    border-radius: 3px;
    font-family: 'Consolas', 'Courier New', monospace;
    white-space: pre-wrap;
    margin: 10px 0;
}
#dreamscript-help-content .toc {
    background-color: #f0f0f0;
    border: 1px solid #ddd;
    padding: 10px 20px;
}
#dreamscript-help-content a {
    color: #0066cc;
    text-decoration: none;
}
#dreamscript-help-content a:hover {
    text-decoration: underline;
}

/* Main Help Window Content */
#help-content {
    background-color: #fdfdfd;
    color: #111;
    padding: 15px;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    line-height: 1.6;
}
#help-content h2, #help-content h3 {
    border-bottom: 1px solid #ccc;
    padding-bottom: 5px;
    margin-top: 20px;
    color: #005a9e;
}
#help-content pre {
    background-color: #e7e7e7;
    padding: 10px;
    border-radius: 3px;
    font-family: 'Consolas', 'Courier New', monospace;
    white-space: pre-wrap;
    margin: 10px 0;
}
#help-content .toc {
    background-color: #f0f0f0;
    border: 1px solid #ddd;
    padding: 10px 20px;
}
#help-content a {
    color: #0066cc;
    text-decoration: none;
}
#help-content a:hover { text-decoration: underline; }

/* Chess Game */
#chess-status-bar {
    text-align: center;
    padding-bottom: 10px;
    font-weight: bold;
}
#chessboard-container {
    flex-grow: 1;
    display: flex;
    align-items: center;
    justify-content: center;
}
#chessboard {
    display: grid;
    grid-template-columns: repeat(8, 5vh);
    grid-template-rows: repeat(8, 5vh);
    width: 40vh;
    height: 40vh;
    border: 2px solid #333;
}
.chess-square {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 3.5vh;
    cursor: pointer;
}
.chess-square.light { background-color: #f0d9b5; color: black; }
.chess-square.dark { background-color: #b58863; color: black; }
.chess-square.selected { background-color: #6a9955 !important; }
.chess-square .legal-move-dot {
    width: 30%;
    height: 30%;
    background-color: rgba(0, 0, 0, 0.2);
    border-radius: 50%;
}
.chess-toolbar {
    padding-top: 10px;
    display: flex;
    justify-content: center;
}
/* Responsive Design for Mobile Devices */
@media (max-width: 768px) {
    /* Make all app windows take up most of the screen */
    .app-window {
        width: 98vw;
        height: calc(100% - 5px); /* Almost full height */
        top: 2px;
        left: 1vw;
        box-shadow: none; /* Remove shadow on mobile for performance */
    }

    /* Ensure the terminal specifically fills the screen */
    #terminal-window {
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        border: none;
    }

    /* Make start menu items a bit bigger for touch */
    #start-menu li {
        padding: 10px 15px;
        font-size: 16px;
    }
}

/* Adventure Game App */
#adventure-window .window-content {
    background-color: #000;
    color: #0f0;
    padding: 5px;
}

#adventure-output {
    flex-grow: 1;
    overflow-y: auto;
    white-space: pre-wrap;
    margin-bottom: 10px;
}

#adventure-input {
    border: none;
    background-color: #111;
    color: #0f0;
    width: 100%;
    padding: 5px;
    box-sizing: border-box;
    font-family: inherit;
}
.room-title { color: #fff; font-weight: bold; }
.room-desc { color: #0f0; }
.command-echo { color: #888; }

    </style>
</head>
<body>
    <div id="desktop">
        <!-- VDD Overlay -->
        <div id="vdd-overlay">VDD_STAT: Loading...</div>

        <!-- Main IFrame for external apps -->
        <iframe id="main-frame" src="about:blank"></iframe>

        <!-- Terminal Window -->
        <div id="terminal-window" class="app-window">
            <div class="window-header">
                <span>DreamShell</span>
                <div class="window-controls">
                    <button class="window-minimize-btn">_</button>
                    <button class="window-maximize-btn">[]</button>
                    <button class="window-close-btn">X</button>
                </div>
            </div>
            <div class="window-content">
                <div id="output">
                    <div>DreamOS [Version 10.0.2026] (c) 2026 Nicholas Paul Wilde. All rights reserved.</div>
                </div>
                <div id="prompt">
                    <span id="prompt-text">C:\></span>
                    <input type="text" id="command-input" autocomplete="off" spellcheck="false" />
                </div>
            </div>
        </div>

        <!-- Text Editor App Window -->
        <div id="text-editor-window" class="app-window hidden">
            <div class="window-header">
                <span>Notepad</span>
                <div class="window-controls">
                    <button class="window-minimize-btn">_</button>
                    <button class="window-maximize-btn">[]</button>
                    <button class="window-close-btn">X</button>
                </div>
            </div>
            <div class="window-content">
                <div class="editor-toolbar">
                    <input type="text" id="editor-filename" placeholder="C:\path\to\file.txt">
                    <button id="editor-load-btn">Load</button>
                    <button id="editor-save-btn">Save</button>
                </div>
                <textarea id="editor-content-area" class="editor-area"></textarea>
                <div id="editor-status-bar">Ready</div>
            </div>
        </div>

        <!-- DreamScript IDE App Window -->
        <div id="dreamscript-ide-window" class="app-window hidden">
            <div class="window-header">
                <span>DreamScript IDE</span>
                <div class="window-controls">
                    <button class="window-minimize-btn">_</button>
                    <button class="window-maximize-btn">[]</button>
                    <button class="window-close-btn">X</button>
                </div>
            </div>
            <div class="window-content">
                <div class="ide-toolbar">
                    <input type="text" id="dreamscript-ide-filename" placeholder="C:\path\to\program.ds">
                    <button id="dreamscript-ide-load-btn">Load</button>
                    <button id="dreamscript-ide-save-btn">Save</button>
                    <button id="dreamscript-ide-help-btn">Help</button>
                    <button id="dreamscript-ide-execute-btn">Run</button>
                </div>
                <div class="ide-editor-container">
                    <textarea id="dreamscript-ide-code" spellcheck="false"></textarea>
                    <pre id="dreamscript-ide-highlighting" aria-hidden="true"><code></code></pre>
                </div>
                <div id="dreamscript-ide-output">Output...</div>
            </div>
        </div>

        <!-- DreamScript IDE Help Window -->
        <div id="dreamscript-help-window" class="app-window hidden">
            <div class="window-header">
                <span>DreamScript Language Help</span>
                <div class="window-controls">
                    <button class="window-minimize-btn">_</button>
                    <button class="window-maximize-btn">[]</button>
                    <button class="window-close-btn">X</button>
                </div>
            </div>
            <div class="window-content" id="dreamscript-help-content">
                <!-- Help content is injected by basic.js -->
            </div>
        </div>

        <!-- Chess App Window -->
        <div id="chess-window" class="app-window hidden">
            <div class="window-header">
                <span>Chess</span>
                <div class="window-controls">
                    <button class="window-minimize-btn">_</button>
                    <button class="window-maximize-btn">[]</button>
                    <button class="window-close-btn">X</button>
                </div>
            </div>
            <div class="window-content">
                <div id="chess-status-bar">New game. White to move.</div>
                <div id="chessboard-container">
                    <div id="chessboard"></div>
                </div>
                <div class="chess-toolbar">
                    <button id="chess-new-game-btn">New Game</button>
                </div>
            </div>
        </div>

        <!-- Adventure Game App Window -->
        <div id="adventure-window" class="app-window hidden">
            <div class="window-header">
                <span>Adventure</span>
                <div class="window-controls">
                    <button class="window-minimize-btn">_</button>
                    <button class="window-maximize-btn">[]</button>
                    <button class="window-close-btn">X</button>
                </div>
            </div>
            <div class="window-content">
                <div id="adventure-output"></div>
                <input type="text" id="adventure-input" autocomplete="off" spellcheck="false" />
            </div>
        </div>

        <!-- Main Help Window -->
        <div id="help-window" class="app-window hidden">
            <div class="window-header">
                <span>DreamOS Help</span>
                <div class="window-controls">
                    <button class="window-minimize-btn">_</button>
                    <button class="window-maximize-btn">[]</button>
                    <button class="window-close-btn">X</button>
                </div>
            </div>
            <div class="window-content" id="help-content">
                <!-- Help content is injected by help.js -->
            </div>
        </div>
    </div>

    <div id="taskbar">
        <button id="start-btn">Start</button>
        <div id="taskbar-apps"></div>
        <div id="start-menu" class="hidden">
            <ul>
                <li id="start-menu-nwhome">NW_Home</li>
                <li id="start-menu-fleagrass">Fleagrass</li>
                <li id="start-menu-dalnet">Dal.net Chat</li>
                <li id="start-menu-console">Console</li>
                <li id="start-menu-notepad">Notepad</li>
                <li id="start-menu-dreamscript">DreamScript IDE</li>
                <li id="start-menu-chess">Chess</li>
                <li id="start-menu-adventure">Text Adventure</li>
                <li id="start-menu-reboot">Reboot</li>
            </ul>
        </div>
        <div class="taskbar-divider"></div>
        <span id="vdd-status">WDDM:OK</span>
        <span id="clock">00:00</span>
    </div>

    <script>
/*
 * Copyright (c) 2026 Nicholas Paul Wilde. All rights reserved.
 * DREAMOS HAL - Hardware Abstraction Layer (Server/Web Edition)
 */
window.HAL = {
    /**
     * sysCall: The only authorized bridge to hardware.
     * In this standalone web version, logic is handled locally or mocked.
     */
    sysCall: (task, data) => {
        if (window.Android && window.Android.sysCall) {
            return window.Android.sysCall(task, data);
        }

        // Mock hardware responses for pure web deployment
        if (task === "get_hw_id") return "HW_DREAMOS_V1_STANDALONE";
        return "MODE_STANDALONE_WEB";
    },

    getPowerStatus: () => {
        return { gpu: "Web-Accelerated VDD", vram: "Shared Browser Memory", status: "OK" };
    }
};

/*
 * Copyright (c) 2026 Nicholas Paul Wilde. All rights reserved.
 * DREAMOS VFS - Virtual File System Module
 * -----------------------------------------
 * Strictly virtualized C:\ drive modeled after Windows Server.
 */
window.VFS = (() => {
    const CURRENT_VFS_NAME_KEY = 'dreamos_vfs_current_name';
    let VFS_STORAGE_KEY;
    let PATH_STORAGE_KEY;
    let vfsName;
    
    // Default structure for a fresh install or a reset.
    const getDefaultFs = () => ({
        "c:": { type: "dir", name: "C:", metadata: { createdAt: new Date().toISOString(), modifiedAt: new Date().toISOString() } },
        "c:\\inetpub": { type: "dir", name: "inetpub", metadata: { createdAt: new Date().toISOString(), modifiedAt: new Date().toISOString() } },
        "c:\\inetpub\\wwwroot": { type: "dir", name: "wwwroot", metadata: { createdAt: new Date().toISOString(), modifiedAt: new Date().toISOString() } },
        "c:\\inetpub\\wwwroot\\site_logs.txt": {
            type: "file",
            name: "site_logs.txt",
            content: "DreamOS Server Deployment Log\n-----------------------------\nStatus: Online\nArchitecture: Microkernel JS\nHAL: Virtualized",
            metadata: {
                createdAt: new Date().toISOString(),
                modifiedAt: new Date().toISOString(),
                size: 146
            }
        },
        "c:\\inetpub\\wwwroot\\adventure.json": {
            type: "file",
            name: "adventure.json",
            content: JSON.stringify({
                "startRoom": "clearing",
                "rooms": {
                    "clearing": {
                        "name": "Forest Clearing",
                        "desc": "You are in a sun-dappled clearing. A path leads east into the darker woods. A strange, monolithic server hums quietly in the center of the clearing.",
                        "exits": { "east": "path" }
                    },
                    "path": {
                        "name": "Winding Path",
                        "desc": "A narrow path winds through ancient, moss-covered trees. The air is cool and smells of damp earth. The path continues to the east, and the clearing is to the west.",
                        "exits": { "west": "clearing" }
                    }
                }
            }, null, 2),
            metadata: {
                createdAt: new Date().toISOString(),
                modifiedAt: new Date().toISOString(),
                size: 500 // Approximate size
            }
        },
        "c:\\inetpub\\wwwroot\\adventure.ds": {
            type: "file",
            name: "adventure.ds",
            content: `' DreamScript Adventure!

DIM currentRoom = "clearing"

WHILE 1=1
    PRINT ""
    IF currentRoom = "clearing" THEN
        PRINT "You are in a sun-dappled clearing. A path leads east."
    ELSEIF currentRoom = "path" THEN
        PRINT "You are on a winding path. The clearing is west."
    END IF
    
    INPUT "What now?>", command$
    
    IF command$ = "east" AND currentRoom = "clearing" THEN
        currentRoom = "path"
    ELSEIF command$ = "west" AND currentRoom = "path" THEN
        currentRoom = "clearing"
    ELSE
        PRINT "You can't do that."
    END IF
WEND
`,
            metadata: {
                createdAt: new Date().toISOString(),
                modifiedAt: new Date().toISOString(),
                size: 600
            }
        },
        "c:\\dreamos": { type: "dir", name: "DreamOS", metadata: { createdAt: new Date().toISOString(), modifiedAt: new Date().toISOString() } },
        "c:\\dreamos\\system32": { type: "dir", name: "System32", metadata: { createdAt: new Date().toISOString(), modifiedAt: new Date().toISOString() } },
        "c:\\dreamos\\system32\\dir.ds": {
            type: "file",
            name: "dir.ds",
            content: `' The "dir" command, implemented in DreamScript.\nSYSCALL "VFS.getPath"\nDIM currentPath = RESULT\nSYSCALL "VFS.getDirectoryListing", currentPath\nPRINT RESULT`,
            metadata: {
                createdAt: new Date().toISOString(),
                modifiedAt: new Date().toISOString(),
                size: 150
            }
        },
        "c:\\python312": { type: "dir", name: "Python312", metadata: { createdAt: new Date().toISOString(), modifiedAt: new Date().toISOString() } },
        "c:\\python312\\python.exe": {
            type: "file",
            name: "python.exe",
            content: "BINARY_EXEC",
            metadata: {
                createdAt: new Date().toISOString(),
                modifiedAt: new Date().toISOString(),
                size: 11
            }
        }
    });

    let fs;
    let currentPath;

    // Private function to save the current state to LocalStorage.
    const _persist = () => {
        try {
            localStorage.setItem(VFS_STORAGE_KEY, JSON.stringify(fs));
            localStorage.setItem(PATH_STORAGE_KEY, currentPath);
        } catch (e) {
            console.error(`Failed to save VFS '${vfsName}' to LocalStorage:`, e);
        }
    };

    // Load state from LocalStorage or initialize with defaults.
    const _load = () => {
        console.log('[DreamOS Debug] VFS: Loading from localStorage...');
        const storedFs = localStorage.getItem(VFS_STORAGE_KEY);
        const storedPath = localStorage.getItem(PATH_STORAGE_KEY);

        let fsNeedsInit = true;
        // When loading, ensure all keys are canonical (lowercase)
        if (storedFs) {
            try {
                console.log('[DreamOS Debug] VFS: Found existing FS in localStorage.');
                const loadedFs = JSON.parse(storedFs);
                fs = {};
                for (const key in loadedFs) {
                    fs[key.toLowerCase()] = loadedFs[key];
                }
                fsNeedsInit = false;
            } catch (e) {
                console.warn('[DreamOS Debug] VFS: Failed to parse VFS from localStorage. Data may be corrupt. Resetting to default FS.', e);
            }
        }

        if (fsNeedsInit) {
            console.log('[DreamOS Debug] VFS: No valid FS found or data was corrupt. Initializing with default.');
            fs = {};
            const defaultFs = getDefaultFs();
            for (const key in defaultFs) {
                fs[key.toLowerCase()] = defaultFs[key];
            }
        }
        // Ensure currentPath is also canonical (lowercase)
        currentPath = (storedPath || "C:\\inetpub\\wwwroot").toLowerCase();
        console.log(`[DreamOS Debug] VFS: Path set to "${currentPath}".`);

        // If the FS was not in storage OR if we just re-initialized it, persist it.
        if (!storedFs || fsNeedsInit) {
            console.log('[DreamOS Debug] VFS: Persisting default/re-initialized FS to localStorage.');
            _persist();
        }
    };

    const _initVfs = () => {
        console.log('[DreamOS Debug] VFS: Initializing...');
        vfsName = localStorage.getItem(CURRENT_VFS_NAME_KEY) || 'default';
        VFS_STORAGE_KEY = `dreamos_vfs_${vfsName}`;
        PATH_STORAGE_KEY = `dreamos_vfs_path_${vfsName}`;
        console.log(`[DreamOS Debug] VFS: Active VFS instance is '${vfsName}'.`);
        _load();
    };

    // Initialize the file system on module load.
    _initVfs();

    /**
     * Normalizes a given path relative to a base path, handling '..' and '.'
     * and ensuring consistent '\' separators.
     * @param {string} basePath The current working directory (e.g., "C:\inetpub\wwwroot").
     * @param {string} targetPath The path to normalize (e.g., "..\logs", "C:\Windows\System32").
     * @returns {string} The normalized absolute path (e.g., "C:\inetpub\logs").
     */
    const _normalizePath = (basePath, targetPath) => {
        let pathParts;
        let currentPathArray;

        // Handle absolute paths
        if (targetPath.match(/^c:\\/i)) { // Starts with C:\ or c:\
            pathParts = targetPath.substring(3).split('\\').filter(p => p !== '');
            currentPathArray = []; // Start fresh from root
        } else if (targetPath.match(/^c:/i)) { // Just C:
            pathParts = [];
            currentPathArray = []; // Start fresh from root
        } else { // Relative path
            currentPathArray = basePath.substring(2).split('\\').filter(p => p !== '');
            pathParts = targetPath.split('\\').filter(p => p !== '');
        }

        for (const part of pathParts) {
            if (part === '..') {
                if (currentPathArray.length > 0) {
                    currentPathArray.pop();
                }
            } else if (part !== '.') {
                currentPathArray.push(part);
            }
        }

        let normalized = "C:";
        if (currentPathArray.length > 0) {
            normalized += "\\" + currentPathArray.join('\\');
        }
        return normalized;
    };

    const _listVfs = () => {
        const vfsNames = new Set();
        for (let i = 0; i < localStorage.length; i++) {
            const key = localStorage.key(i);
            if (key.startsWith('dreamos_vfs_') && key !== CURRENT_VFS_NAME_KEY) {
                const name = key.startsWith('dreamos_vfs_path_')
                    ? key.substring('dreamos_vfs_path_'.length)
                    : key.substring('dreamos_vfs_'.length);
                vfsNames.add(name);
            }
        }
        return Array.from(vfsNames);
    };

    const _switchVfs = (newName) => {
        if (!newName || typeof newName !== 'string' || newName.trim() === '') {
            return { success: false, message: "Invalid VFS name." };
        }
        // Sanitize name to prevent issues
        const cleanName = newName.trim().replace(/\s+/g, '_');
        localStorage.setItem(CURRENT_VFS_NAME_KEY, cleanName);
        return { success: true, message: `Switched to VFS '${cleanName}'. System will reboot.` };
    };

    const _deleteVfs = (nameToDelete) => {
        if (!nameToDelete || typeof nameToDelete !== 'string' || nameToDelete.trim() === '') {
            return { success: false, message: "Invalid VFS name." };
        }
        const cleanName = nameToDelete.trim();
        if (cleanName === vfsName) {
            return { success: false, message: `Error: Cannot delete the currently active VFS ('${cleanName}').` };
        }
        if (cleanName === 'default') {
            return { success: false, message: "Error: Cannot delete the 'default' VFS." };
        }

        const vfsKey = `dreamos_vfs_${cleanName}`;
        const pathKey = `dreamos_vfs_path_${cleanName}`;

        if (localStorage.getItem(vfsKey) === null && localStorage.getItem(pathKey) === null) {
            return { success: false, message: `Error: VFS '${cleanName}' not found.` };
        }

        localStorage.removeItem(vfsKey);
        localStorage.removeItem(pathKey);

        return { success: true, message: `VFS '${cleanName}' deleted.` };
    };

    const _renameVfs = (oldName, newName) => {
        if (!oldName || !newName || typeof oldName !== 'string' || typeof newName !== 'string') {
            return { success: false, message: "Invalid VFS names provided." };
        }
        const cleanOldName = oldName.trim();
        const cleanNewName = newName.trim().replace(/\s+/g, '_');

        if (cleanOldName === vfsName) {
            return { success: false, message: `Error: Cannot rename the currently active VFS ('${cleanOldName}').` };
        }
        if (cleanOldName === 'default') {
            return { success: false, message: "Error: Cannot rename the 'default' VFS." };
        }
        if (cleanNewName === 'default' || cleanNewName === '') {
            return { success: false, message: "Error: Invalid new name." };
        }

        const oldVfsKey = `dreamos_vfs_${cleanOldName}`;
        const oldPathKey = `dreamos_vfs_path_${cleanOldName}`;
        const newVfsKey = `dreamos_vfs_${cleanNewName}`;
        const newPathKey = `dreamos_vfs_path_${cleanNewName}`;

        const vfsData = localStorage.getItem(oldVfsKey);
        if (vfsData === null) {
            return { success: false, message: `Error: Source VFS '${cleanOldName}' not found.` };
        }
        if (localStorage.getItem(newVfsKey) !== null || localStorage.getItem(newPathKey) !== null) {
            return { success: false, message: `Error: Destination VFS '${cleanNewName}' already exists.` };
        }

        const pathData = localStorage.getItem(oldPathKey);

        localStorage.setItem(newVfsKey, vfsData);
        if (pathData !== null) {
            localStorage.setItem(newPathKey, pathData);
        }

        localStorage.removeItem(oldVfsKey);
        localStorage.removeItem(oldPathKey);

        return { success: true, message: `VFS '${cleanOldName}' renamed to '${cleanNewName}'.` };
    };

    const _copyVfs = (sourceName, destName) => {
        if (!sourceName || !destName || typeof sourceName !== 'string' || typeof destName !== 'string') {
            return { success: false, message: "Invalid VFS names provided." };
        }
        const cleanSourceName = sourceName.trim();
        const cleanDestName = destName.trim().replace(/\s+/g, '_');

        if (cleanSourceName === cleanDestName) {
            return { success: false, message: "Error: Source and destination names cannot be the same." };
        }

        const sourceVfsKey = `dreamos_vfs_${cleanSourceName}`;
        const sourcePathKey = `dreamos_vfs_path_${cleanSourceName}`;
        const destVfsKey = `dreamos_vfs_${cleanDestName}`;
        const destPathKey = `dreamos_vfs_path_${cleanDestName}`;

        const vfsData = localStorage.getItem(sourceVfsKey);
        if (vfsData === null) {
            return { success: false, message: `Error: Source VFS '${cleanSourceName}' not found.` };
        }
        if (localStorage.getItem(destVfsKey) !== null || localStorage.getItem(destPathKey) !== null) {
            return { success: false, message: `Error: Destination VFS '${cleanDestName}' already exists.` };
        }

        const pathData = localStorage.getItem(sourcePathKey);

        localStorage.setItem(destVfsKey, vfsData);
        if (pathData !== null) {
            localStorage.setItem(destPathKey, pathData);
        }

        return { success: true, message: `VFS '${cleanSourceName}' copied to '${cleanDestName}'.` };
    };

    const _getDirectoryListing = (path) => {
        const canonicalPath = _normalizePath(currentPath, path).toLowerCase();
        if (!fs[canonicalPath] || fs[canonicalPath].type !== 'dir') {
            return "The system cannot find the path specified.";
        }

        const children = [];
        for (const [fullPathKey, entry] of Object.entries(fs)) {
            let isDirectChild = false;
            if (canonicalPath === 'c:') {
                if (fullPathKey.startsWith('c:\\') && fullPathKey.split('\\').length === 2) {
                    isDirectChild = true;
                }
            } else if (fullPathKey.startsWith(canonicalPath + '\\')) {
                const relativePath = fullPathKey.substring(canonicalPath.length + 1);
                if (relativePath && !relativePath.includes('\\')) {
                    isDirectChild = true;
                }
            }
            if (isDirectChild) {
                children.push(entry);
            }
        }

        if (children.length === 0) return "File Not Found";

        let output = ` Directory of ${canonicalPath.toUpperCase()}\n\n`;
        let totalFiles = 0;
        let totalSize = 0;
        let totalDirs = 0;

        const formatDosDate = (isoString) => {
            if (!isoString) return ' '.repeat(20);
            const d = new Date(isoString);
            const month = (d.getMonth() + 1).toString().padStart(2, '0');
            const day = d.getDate().toString().padStart(2, '0');
            const year = d.getFullYear();
            let hours = d.getHours();
            const minutes = d.getMinutes().toString().padStart(2, '0');
            const ampm = hours >= 12 ? 'PM' : 'AM';
            hours = hours % 12;
            hours = hours ? hours : 12; // the hour '0' should be '12'
            const strHours = hours.toString().padStart(2, ' ');
            return `${month}/${day}/${year}  ${strHours}:${minutes} ${ampm}`;
        };

        children.forEach(entry => {
            const dateStr = formatDosDate(entry.metadata?.modifiedAt);
            if (entry.type === "dir") {
                output += `${dateStr}  <DIR>          ${entry.name}\n`;
                totalDirs++;
            } else {
                const size = entry.metadata?.size || 0;
                const sizeStr = size.toLocaleString().padStart(12);
                output += `${dateStr}  ${sizeStr} ${entry.name}\n`;
                totalFiles++;
                totalSize += size;
            }
        });
        output += `\n               ${totalFiles} File(s) ${totalSize.toLocaleString()} bytes`;
        output += `\n               ${totalDirs} Dir(s)`;
        return output;
    };

    return {
        getPath: () => currentPath, // Returns canonical (lowercase) path
        setPath: (path) => {
            currentPath = path.toLowerCase(); // Ensure path is always canonical
            _persist();
        },
        normalizePath: _normalizePath, // Returns path with input casing, but canonical form is lowercase
        exists: (path) => {
            const canonicalPath = _normalizePath(currentPath, path).toLowerCase();
            return fs[canonicalPath] ? canonicalPath : null; // Returns the canonical key if it exists
        },
        getEntry: (canonicalPath) => fs[canonicalPath], // Expects a canonical (lowercase) path
        getAllEntries: () => fs, // Returns entries with lowercase keys
        readFile: (path) => {
            const canonicalPath = _normalizePath(currentPath, path).toLowerCase();
            const entry = fs[canonicalPath]; // Directly look up using canonical path

            if (entry) {
                if (entry.type === "file") {
                    // Return the original path for user feedback, but content from canonical entry
                    return { success: true, path: _normalizePath(currentPath, path), content: entry.content };
                } else if (entry.type === "dir") {
                    return { success: false, message: `Error: '${path}' is a directory.` };
                }
            }
            return { success: false, message: "Error: The system cannot find the file specified." };
        },
        writeFile: (path, content) => {
            const resolvedPath = _normalizePath(currentPath, path); // Path with input casing
            const canonicalResolvedPath = resolvedPath.toLowerCase(); // Canonical key for storage

            const lastSlash = canonicalResolvedPath.lastIndexOf('\\');
            const parentDirCanonical = (lastSlash > 2) ? canonicalResolvedPath.substring(0, lastSlash) : "c:";

            if (!fs[parentDirCanonical] || fs[parentDirCanonical].type !== 'dir') {
                return { success: false, message: "Error: The system cannot find the path specified." };
            }

            const filename = resolvedPath.substring(resolvedPath.lastIndexOf('\\') + 1); // Keep original casing for name property
            const now = new Date().toISOString();
            const existingEntry = fs[canonicalResolvedPath];

            if (existingEntry) {
                if (existingEntry.type === 'dir') {
                    return { success: false, message: `Error: Cannot write to '${path}'. It is a directory.` };
                }
                // Update existing file
                existingEntry.content = content;
                if (!existingEntry.metadata) {
                    // For backward compatibility with files created before metadata existed
                    existingEntry.metadata = { createdAt: now };
                }
                existingEntry.metadata.modifiedAt = now;
                existingEntry.metadata.size = content.length;
            } else {
                // Create new file
                fs[canonicalResolvedPath] = {
                    type: "file",
                    name: filename,
                    content: content,
                    metadata: {
                        createdAt: now,
                        modifiedAt: now,
                        size: content.length
                    }
                };
            }

            _persist(); // Save changes to LocalStorage
            return { success: true, message: `File saved: ${resolvedPath}` }; // Return resolvedPath for user feedback
        },
        makeDirectory: (path) => {
            const resolvedPath = _normalizePath(currentPath, path);
            const canonicalResolvedPath = resolvedPath.toLowerCase();

            if (fs[canonicalResolvedPath]) {
                return { success: false, message: "A subdirectory or file with that name already exists." };
            }

            const lastSlash = canonicalResolvedPath.lastIndexOf('\\');
            const parentDirCanonical = (lastSlash > 2) ? canonicalResolvedPath.substring(0, lastSlash) : "c:";

            if (!fs[parentDirCanonical] || fs[parentDirCanonical].type !== 'dir') {
                return { success: false, message: "The system cannot find the path specified." };
            }

            const dirname = resolvedPath.substring(resolvedPath.lastIndexOf('\\') + 1);
            const now = new Date().toISOString();

            fs[canonicalResolvedPath] = { type: "dir", name: dirname, metadata: { createdAt: now, modifiedAt: now } };
            _persist();
            return { success: true, message: "" };
        },
        format: () => {
            try {
                localStorage.removeItem(VFS_STORAGE_KEY);
                localStorage.removeItem(PATH_STORAGE_KEY);
                // Re-initialize the file system to its default state.
                _initVfs();
            } catch (e) {
                console.error(`Failed to format VFS '${vfsName}':`, e);
            }
        },
        listVfs: _listVfs,
        switchVfs: _switchVfs,
        deleteVfs: _deleteVfs,
        renameVfs: _renameVfs,
        copyVfs: _copyVfs,
        getCurrentVfsName: () => vfsName,
        getDirectoryListing: _getDirectoryListing
    };
})();

/*
 * Copyright (c) 2026 Nicholas Paul Wilde. All rights reserved.
 * DREAMOS WINDOW MANAGER (win.sys.js)
 */
window.WindowManager = (() => {
    let highestZ = 100;
    let taskbarAppsContainer;

    // The main initialization function for the window manager.
    const init = () => {
        taskbarAppsContainer = document.getElementById('taskbar-apps');
        if (!taskbarAppsContainer) {
            console.error("Window Manager Error: Taskbar container '#taskbar-apps' not found.");
            return;
        }

        // Find all elements with the class 'app-window' and make them behave like windows.
        document.querySelectorAll('.app-window').forEach(windowEl => {
            _makeDraggable(windowEl);
            _setupWindowControls(windowEl);
        });
    };

    // Private function to make a window draggable by its header.
    const _makeDraggable = (windowEl) => {
        const header = windowEl.querySelector('.window-header');
        let offsetX, offsetY;

        const onMouseDown = (e) => {
            // Bring window to the front when clicked.
            _bringToFront(windowEl);

            // Don't start dragging if a button in the header was clicked.
            if (e.target.closest('.window-controls')) return;

            // Don't drag if the window is maximized.
            if (windowEl.classList.contains('maximized')) return;

            offsetX = e.clientX - windowEl.offsetLeft;
            offsetY = e.clientY - windowEl.offsetTop;

            document.addEventListener('mousemove', onMouseMove);
            document.addEventListener('mouseup', onMouseUp);
        };

        const onMouseMove = (e) => {
            windowEl.style.left = `${e.clientX - offsetX}px`;
            windowEl.style.top = `${e.clientY - offsetY}px`;
        };

        const onMouseUp = () => {
            document.removeEventListener('mousemove', onMouseMove);
            document.removeEventListener('mouseup', onMouseUp);
        };

        header.addEventListener('mousedown', onMouseDown);
    };

    // Private function to set up the minimize, maximize, and close buttons.
    const _setupWindowControls = (windowEl) => {
        windowEl.addEventListener('mousedown', () => _bringToFront(windowEl));

        const windowId = windowEl.id;
        const title = windowEl.querySelector('.window-header span').textContent;

        const minBtn = windowEl.querySelector('.window-minimize-btn');
        const maxBtn = windowEl.querySelector('.window-maximize-btn');
        const closeBtn = windowEl.querySelector('.window-close-btn');

        if (minBtn) {
            minBtn.addEventListener('click', () => TaskbarManager.add(windowEl, title));
        }

        if (maxBtn) {
            maxBtn.addEventListener('click', () => windowEl.classList.toggle('maximized'));
        }

        if (closeBtn) {
            closeBtn.addEventListener('click', () => {
                // Special case for the terminal: minimize instead of closing to preserve the session.
                if (windowId === 'terminal-window') {
                    TaskbarManager.add(windowEl, title);
                } else {
                    windowEl.classList.add('hidden');
                    TaskbarManager.remove(windowId);
                }
            });
        }
    };

    // Private function to bring a window to the top of the stack.
    const _bringToFront = (windowEl) => {
        highestZ++;
        windowEl.style.zIndex = highestZ;
    };

    // An internal object to manage minimized windows on the taskbar.
    const TaskbarManager = {
        minimizedWindows: {},

        add: (windowEl, title) => {
            const windowId = windowEl.id;
            if (TaskbarManager.minimizedWindows[windowId]) return; // Already on taskbar.

            const taskbarItem = document.createElement('div');
            taskbarItem.className = 'taskbar-item';
            taskbarItem.textContent = title;
            taskbarItem.dataset.window = windowId;

            taskbarItem.addEventListener('click', () => {
                TaskbarManager.restore(windowId);
            });

            taskbarAppsContainer.appendChild(taskbarItem);
            TaskbarManager.minimizedWindows[windowId] = taskbarItem;
            windowEl.classList.add('minimized');
        },

        restore: (windowId) => {
            const windowEl = document.getElementById(windowId);
            const taskbarItem = TaskbarManager.minimizedWindows[windowId];

            if (windowEl && taskbarItem) {
                windowEl.classList.remove('minimized');
                taskbarItem.remove();
                delete TaskbarManager.minimizedWindows[windowId];
                
                _bringToFront(windowEl);

                // If it's the terminal, focus the input.
                if (windowId === 'terminal-window') {
                    const input = document.getElementById('command-input');
                    if (input) input.focus();
                }
            }
        },
        
        remove: (windowId) => {
            const taskbarItem = TaskbarManager.minimizedWindows[windowId];
            if (taskbarItem) {
                taskbarItem.remove();
                delete TaskbarManager.minimizedWindows[windowId];
            }
        }
    };

    // The public API for the WindowManager.
    return {
        init: init,
        focusOrRestore: (windowId) => {
            const windowEl = document.getElementById(windowId);
            if (!windowEl) return;

            if (windowEl.classList.contains('minimized')) {
                TaskbarManager.restore(windowId);
            } else {
                _bringToFront(windowEl);
            }
        }
    };
})();
/*
 * Copyright (c) 2026 Nicholas Paul Wilde. All rights reserved.
 * DREAMOS CLUSTER - WebRTC Distributed Computing Module
 */

window.DreamCluster = (() => {
    // The address of your signaling server.
    // When loading the page over HTTPS, the WebSocket must also be secure (WSS).
    // Browsers block insecure WebSocket (ws://) connections from secure pages.
    const SIGNALING_SERVER_URL = 'wss://mars.fleagrass.com:1874';
    let ws; // This will hold our WebSocket connection.
    let peers = {}; // An object to store all our peer connections.
    let localId = 'peer_' + Math.random().toString(36).substr(2, 9); // A random, unique ID for this browser session.
    let onMessageCallback; // A function to call when we receive data from a peer.
    let encryptionKey; // This will hold the password for simple encryption.

    // Configuration for the RTCPeerConnection. This includes STUN servers.
    // STUN servers are public utilities that help browsers figure out their public IP address
    // so they can connect even if they are behind a home router (NAT).
    const peerConnectionConfig = {
        'iceServers': [
            { 'urls': 'stun:stun.stunprotocol.org:3478' },
            { 'urls': 'stun:stun.l.google.com:19302' },
        ]
    };

    // This function starts the connection to the signaling server.
    const init = (key, statusCallback) => {
        console.log('[DreamOS Debug] DreamCluster: Initializing...');
        if (!key) {
            console.error("Cluster initialization failed: An encryption key is required.");
            if (statusCallback) statusCallback({ connected: false, message: "Cluster initialization failed: An encryption key is required." });
            return;
        }
        encryptionKey = key;

        ws = new WebSocket(SIGNALING_SERVER_URL);

        // When the connection to the signaling server is open...
        ws.onopen = () => {
            console.log("Connected to signaling server.");
            if (statusCallback) statusCallback({ connected: true, message: "Successfully connected to cluster signaling server." });
            // ...we announce our presence to everyone else by sending our unique ID.
            ws.send(JSON.stringify({ type: 'new-peer', id: localId }));
        };

        // This function runs every time we get a message from the signaling server.
        ws.onmessage = (event) => {
            const msg = JSON.parse(event.data);
            console.log("Signaling message received:", msg);

            // If a new peer announces itself (and it's not us)...
            if (msg.type === 'new-peer' && msg.id !== localId) {
                // ...we will try to connect to it by creating and sending an "offer".
                const peerConnection = getOrCreatePeerConnection(msg.id);

                // As the initiator of this connection, we create the data channel.
                // The other peer will receive this via its 'ondatachannel' event.
                console.log("Creating data channel for peer:", msg.id);
                const dataChannel = peerConnection.createDataChannel('dreamos-data');
                // Store the data channel so we can use it later.
                peers[msg.id].dataChannel = dataChannel;
                setupDataChannelEvents(dataChannel, msg.id);

                peerConnection.createOffer()
                    .then(offer => peerConnection.setLocalDescription(offer))
                    .then(() => {
                        console.log("Sending offer to peer:", msg.id);
                        ws.send(JSON.stringify({
                            type: 'offer',
                            sdp: peerConnection.localDescription,
                            senderId: localId,
                            receiverId: msg.id
                        }));
                    })
                    .catch(e => console.error("Offer creation failed:", e));
            }
            // If we receive an "offer" from another peer...
            else if (msg.type === 'offer' && msg.receiverId === localId) {
                // ...we create an "answer" and send it back.
                const peerConnection = getOrCreatePeerConnection(msg.senderId);
                peerConnection.setRemoteDescription(new RTCSessionDescription(msg.sdp))
                    .then(() => peerConnection.createAnswer())
                    .then(answer => peerConnection.setLocalDescription(answer))
                    .then(() => {
                        console.log("Sending answer to peer:", msg.senderId);
                        ws.send(JSON.stringify({
                            type: 'answer',
                            sdp: peerConnection.localDescription,
                            senderId: localId,
                            receiverId: msg.senderId
                        }));
                    })
                    .catch(e => console.error("Answer creation failed:", e));
            }
            // If we receive an "answer" from a peer we sent an offer to...
            else if (msg.type === 'answer' && msg.receiverId === localId) {
                // ...we complete the connection setup.
                getOrCreatePeerConnection(msg.senderId).setRemoteDescription(new RTCSessionDescription(msg.sdp))
                    .catch(e => console.error("setRemoteDescription failed:", e));
            }
            // An "ICE candidate" is a potential network path. Peers exchange them to find the best way to connect.
            else if (msg.type === 'ice-candidate' && msg.receiverId === localId) {
                const candidate = new RTCIceCandidate(msg.candidate);
                getOrCreatePeerConnection(msg.senderId).addIceCandidate(candidate)
                    .catch(e => console.error("addIceCandidate failed:", e));
            }
        };

        ws.onerror = (error) => {
            console.error("Signaling server connection error:", error);
            if (statusCallback) statusCallback({ connected: false, message: "Error: Could not connect to cluster signaling server." });
        };
    };

    // A helper function to get an existing peer connection or create a new one.
    const getOrCreatePeerConnection = (peerId) => {
        if (!peers[peerId]) {
            console.log(`Creating new peer connection for ${peerId}`);
            const pc = new RTCPeerConnection(peerConnectionConfig);

            // Add a listener to log connection state changes for debugging.
            pc.onconnectionstatechange = (event) => {
                console.log(`Connection state with ${peerId} changed to: ${pc.connectionState}`);
            };

            // This event fires when our browser finds a network path (an ICE candidate).
            // We need to send this to the other peer through the signaling server.
            pc.onicecandidate = (event) => {
                if (event.candidate) {
                    ws.send(JSON.stringify({
                        type: 'ice-candidate',
                        candidate: event.candidate,
                        senderId: localId,
                        receiverId: peerId
                    }));
                }
            };

            // This event fires when the *other* peer opens a data channel to us.
            pc.ondatachannel = (event) => {
                console.log(`Data channel connection established with ${peerId}`);
                peers[peerId].dataChannel = event.channel;
                setupDataChannelEvents(event.channel, peerId);
            };

            peers[peerId] = { connection: pc, dataChannel: null };
        }
        return peers[peerId].connection;
    };

    // Sets up events for a data channel (either one we created or one we received).
    const setupDataChannelEvents = (dataChannel, peerId) => {
        dataChannel.onopen = () => console.log(`Data channel with ${peerId} is open!`);
        dataChannel.onclose = () => console.log(`Data channel with ${peerId} is closed.`);
        dataChannel.onmessage = (event) => {
            console.log(`Message from ${peerId}:`, event.data);
            // Decrypt the message before passing it on.
            const decryptedMessage = _xorCipher(event.data, encryptionKey);
            if (onMessageCallback) {
                onMessageCallback(decryptedMessage);
            }
        };
    };

    // Sends a message to all connected peers.
    const broadcast = (message) => {
        let count = 0;
        for (const peerId in peers) {
            const dataChannel = peers[peerId].dataChannel;
            if (dataChannel && dataChannel.readyState === 'open') {
                // Encrypt the message before sending.
                const encryptedMessage = _xorCipher(message, encryptionKey);
                dataChannel.send(encryptedMessage);
                count++;
            }
        }
        return `Message broadcast to ${count} peer(s).`;
    };

    // Gets the current status of the cluster.
    const getStatus = () => {
        if (!ws || ws.readyState !== WebSocket.OPEN) {
            return "Cluster status: Disconnected from signaling server.";
        }
        const peerIds = Object.keys(peers);
        const connectedPeers = peerIds.filter(id => peers[id].dataChannel && peers[id].dataChannel.readyState === 'open');
        let status = `Cluster status: Connected to signaling server.\n`;
        status += `Local Peer ID: ${localId}\n`;
        status += `Discovered Peers: ${peerIds.length}\n`;
        status += `Connected Peers: ${connectedPeers.length}`;
        if (connectedPeers.length > 0) {
            status += ` (${connectedPeers.join(', ')})`;
        }
        return status;
    };

    // Allows other parts of the OS to listen for messages from peers.
    const setOnMessage = (callback) => {
        onMessageCallback = callback;
    };

    // A simple XOR cipher for "encryption". This is NOT secure for real-world use.
    // It works by combining the message with the key. The same function is used
    // to encrypt and decrypt.
    const _xorCipher = (text, key) => {
        let result = '';
        for (let i = 0; i < text.length; i++) {
            // We get the character code (a number) for the message character and the key character.
            // The '%' (modulo) operator makes the key repeat if it's shorter than the message.
            const charCode = text.charCodeAt(i) ^ key.charCodeAt(i % key.length);
            result += String.fromCharCode(charCode);
        }
        return result;
    };

    // Expose the public functions.
    return {
        init,
        broadcast,
        getStatus,
        setOnMessage
    };
})();
/*
 * Copyright (c) 2026 Nicholas Paul Wilde. All rights reserved.
 * DREAMOS KERNEL - Command Processing & Logic Module
 * --------------------------------------------------
 * Handles the logic for the shell and coordinates between VFS and HAL.
 */
window.Kernel = (() => {

    /**
     * Python Emulator Logic (Python License Applies)
     */
    const runPython = (code) => {
        if (!code) return "Python 3.12.2 (DreamOS JS-Kernel)\nType \"help\", \"copyright\" for more info.\n>>>";
        if (code.toLowerCase().startsWith("print(")) {
            // This regex now correctly handles single or double quotes and captures only the content.
            const match = code.match(/print\((?:"([^"]*)"|'([^']*)')\)/i);
            // The result will be in either the first or second capture group.
            return match ? (match[1] !== undefined ? match[1] : match[2]) : "SyntaxError: invalid syntax";
        }
        return `Traceback (most recent call last):\n  NameError: name '${code}' is not defined`;
    };

    const internalWriteFile = (path, content) => {
        if (!path || content === undefined) {
            return { success: false, message: "Error: Path and content required." };
        }

        const resolved = VFS.normalizePath(VFS.getPath(), path);
        return VFS.writeFile(resolved, content);
    };

    const internalReadFile = (path) => {
        return VFS.readFile(VFS.normalizePath(VFS.getPath(), path));
    };

    return {
        /**
         * The primary command execution engine.
         */
        execute: (input) => {
            console.log(`[DreamOS Debug] Kernel: Executing command: "${input}"`);
            const parts = input.trim().split(/\s+/);
            const cmd = parts[0].toLowerCase();
            const args = parts.slice(1).join(" ");

            switch (cmd) {
                case "ver":
                    return "DreamOS [Version 10.0.2026] (Server Port)\n(c) 2026 Nicholas Paul Wilde. Runs on any modern web browser.\nMicrosoft Windows is a registered trademark of Microsoft Corporation.";

                case "pwd":
                    return VFS.getPath();

                case "whoami":
                    return "DREAMOS\\nicholas_paul_wilde";

                case "dir":
                case "ls":
                    {
                        const dirScript = internalReadFile("c:\\dreamos\\system32\\dir.ds");
                        if (dirScript.success) {
                            // The output from runSync has an extra newline at the end, so trim it.
                            return DreamScriptInterpreter.runSync(dirScript.content).trim();
                        } else {
                            return "Error: dir.ds command not found. " + (dirScript.message || "");
                        }
                    }

                case "cd":
                    if (!args) return "";
                    const searchPath = VFS.normalizePath(VFS.getPath(), args);
                    const actualPath = VFS.exists(searchPath);
                    if (actualPath && VFS.getEntry(actualPath).type === "dir") { // actualPath is now canonical (lowercase)
                        VFS.setPath(actualPath);
                        return "";
                    }
                    return "The system cannot find the path specified.";

                case "type":
                case "cat":
                    const targetFile = VFS.normalizePath(VFS.getPath(), args);
                    const actualFile = VFS.exists(targetFile); // actualFile is now canonical (lowercase)
                    if (actualFile && VFS.getEntry(actualFile).type === "file") {
                        return VFS.getEntry(actualFile).content;
                    }
                    return "The system cannot find the file specified.";

                case "edit": {
                    const targetPath = VFS.normalizePath(VFS.getPath(), args);
                    // If no file is specified, just open a blank editor
                    if (!args) {
                        return { signal: "KERNEL_SIGNAL_OPEN_EDITOR", path: '', content: '' };
                    }

                    const actualFile = VFS.exists(targetPath); // actualFile is now canonical (lowercase)
                    let content = '';
                    // Use actual path to preserve casing, or target path for new file
                    let path = actualFile || targetPath;

                    if (actualFile && VFS.getEntry(actualFile).type === "file") {
                        content = VFS.getEntry(actualFile).content;
                    } else if (actualFile && VFS.getEntry(actualFile).type === "dir") {
                        return `Error: '${args}' is a directory.`;
                    }

                    return { signal: "KERNEL_SIGNAL_OPEN_EDITOR", path: path, content: content };
                }
                case "python":
                    if (args.toLowerCase().startsWith("-c ")) {
                        return runPython(args.substring(3).replace(/^["']|["']$/g, ""));
                    }
                    return runPython("");

                case "msg":
                    if (!args) return "Usage: msg <message>";
                    alert(args);
                    return ""; // Return empty string so nothing is printed to the console

                case "reset":
                    const resetMessage = "WARNING: This will erase all data on the virtual file system.\n\nThis is useful if your files have become corrupted or if a new version of DreamOS requires a clean slate.\n\nAre you sure you want to proceed?";
                    if (confirm(resetMessage)) {
                        VFS.format();
                        setTimeout(() => location.reload(), 1500);
                        return "Resetting virtual file system... Success. System will now reboot.";
                    }
                    return "Reset operation cancelled.";

                case "mkdir":
                case "md":
                    if (!args) {
                        return "The syntax of the command is incorrect.";
                    }
                    const mkdirResult = VFS.makeDirectory(args);
                    return mkdirResult.success ? "" : mkdirResult.message;

                case "dreamscript":
                case "basic":
                    return { signal: "KERNEL_SIGNAL_OPEN_DREAMSCRIPT_IDE" };

                case "adventure":
                    return { signal: "KERNEL_SIGNAL_OPEN_ADVENTURE" };

                case "chess":
                    return { signal: "KERNEL_SIGNAL_OPEN_CHESS" };

                case "cluster": {
                    const subCmd = (args.split(' ')[0] || '').toLowerCase();
                    const subArgs = args.split(' ').slice(1).join(' ');

                    switch (subCmd) {
                        case 'status':
                            return DreamCluster.getStatus();
                        case 'broadcast':
                            if (!subArgs) return "Usage: cluster broadcast <message>";
                            return DreamCluster.broadcast(subArgs);
                        default:
                            return `DreamOS Cluster Management\nUsage:\n  cluster status      - Show network status.\n  cluster broadcast   - Send a message to all peers.`;
                    }
                }

                case "music": {
                    if (!window.musicControls) {
                        return "Music controls are not available.";
                    }
                    const subCmd = (args || '').toLowerCase();
                    switch (subCmd) {
                        case 'play':
                        case 'unpause':
                            window.musicControls.play();
                            return "Playing music.";
                        case 'pause':
                        case 'stop':
                            window.musicControls.pause();
                            return "Music paused.";
                        case 'skip':
                        case 'next':
                            window.musicControls.skip();
                            return "Skipping to next song.";
                        default:
                            return "Usage: music <play|pause|skip>";
                    }
                }
                case "vfs": {
                    const subCmdParts = args.split(/\s+/);
                    const subCmd = (subCmdParts[0] || '').toLowerCase();
                    const arg1 = subCmdParts[1];
                    const arg2 = subCmdParts[2];

                    switch (subCmd) {
                        case 'list':
                            const vfsList = VFS.listVfs();
                            const currentVfs = VFS.getCurrentVfsName();
                            if (vfsList.length === 0) {
                                return `No VFS instances found. Current is '${currentVfs}'.`;
                            }
                            let vfsOutput = "Available VFS instances:\n";
                            vfsList.forEach(name => {
                                vfsOutput += `  ${name}` + (name === currentVfs ? ' (current)' : '') + '\n';
                            });
                            return vfsOutput.trim();

                        case 'use':
                        case 'switch':
                            if (!arg1) return "Usage: vfs use <name>";
                            const result = VFS.switchVfs(arg1);
                            if (result.success) setTimeout(() => location.reload(), 1000);
                            return result.message;

                        case 'current':
                            return `Current VFS is: '${VFS.getCurrentVfsName()}'`;

                        case 'copy':
                        case 'cp':
                            if (!arg1 || !arg2) return "Usage: vfs copy <source_name> <destination_name>";
                            return VFS.copyVfs(arg1, arg2).message;

                        case 'rename':
                        case 'mv':
                            if (!arg1 || !arg2) return "Usage: vfs rename <old_name> <new_name>";
                            return VFS.renameVfs(arg1, arg2).message;

                        case 'delete':
                        case 'rm':
                            if (!arg1) return "Usage: vfs delete <name>";
                            return VFS.deleteVfs(arg1).message;

                        default:
                            return `VFS Management Command\nUsage:\n  vfs list          - List all VFS instances.\n  vfs use <name>    - Switch to a different VFS instance.\n  vfs current       - Show the current VFS name.\n  vfs copy <src> <dest> - Copy a VFS instance.\n  vfs rename <old> <new> - Rename a VFS instance.\n  vfs delete <name> - Delete a VFS instance.`;
                    }
                }
                case "help":
                    return { signal: "KERNEL_SIGNAL_OPEN_HELP" };

                case "cls":
                case "clear":
                    return "KERNEL_SIGNAL_CLS";

                case "":
                    return "";

                default:
                    // If no JS command matches, try passing to HAL (Native hardware fallback)
                    return HAL.sysCall("execute_cmd", input);
            }
        },
        writeFile: internalWriteFile,
        readFile: internalReadFile
    };
})();

/*
 * Copyright (c) 2026 Nicholas Paul Wilde. All rights reserved.
 * DREAMOS EDIT - Simple Text Editor App
 */
window.EditApp = (() => {
    // Define variables for DOM elements. They will be assigned after the DOM is loaded.
    let textEditorWindow, editorFilename, editorContentArea, editorLoadBtn, editorSaveBtn, editorStatusBar;

    /**
     * Initializes the module by caching DOM elements and setting up event listeners.
     * This function is called once the DOM is fully loaded.
     */
    const init = () => {
        console.log('[DreamOS Debug] EditApp: Initializing...');
        // Get references to the editor's DOM elements
        textEditorWindow = document.getElementById('text-editor-window');
        editorFilename = document.getElementById('editor-filename');
        editorContentArea = document.getElementById('editor-content-area');
        editorLoadBtn = document.getElementById('editor-load-btn');
        editorSaveBtn = document.getElementById('editor-save-btn');
        editorStatusBar = document.getElementById('editor-status-bar');

        // Event listener for Save button
        editorSaveBtn.addEventListener('click', onSave);

        // Event listener for Load button
        editorLoadBtn.addEventListener('click', onLoad);
        console.log('[DreamOS Debug] EditApp: Initialized successfully.');
    };

    /**
     * Opens the text editor window and initializes it with content and path.
     * @param {string} path - The file path to display in the filename input.
     * @param {string} content - The content to load into the editor.
     */
    const open = (path = '', content = '') => {
        console.log(`[DreamOS Debug] EditApp: Opening with path: "${path}"`);
        // Ensure init has run
        if (!textEditorWindow) {
            console.error("Editor not initialized. DOM may not be ready.");
            return;
        }
        textEditorWindow.classList.remove('hidden');
        editorFilename.value = path;
        editorContentArea.value = content;
        editorStatusBar.innerText = path ? `Loaded ${path}` : 'Ready';
        editorContentArea.focus();
    };

    const onSave = () => {
        const path = editorFilename.value;
        const content = editorContentArea.value;
        if (!path) {
            editorStatusBar.innerText = "Error: Filename is required to save.";
            return;
        }
        const result = Kernel.writeFile(path, content);
        editorStatusBar.innerText = result.message;
    };

    const onLoad = () => {
        const path = editorFilename.value;
        if (!path) {
            editorStatusBar.innerText = "Error: Filename is required to load.";
            return;
        }
        const result = Kernel.readFile(path);
        if (result.success) {
            editorContentArea.value = result.content;
            editorStatusBar.innerText = `Successfully loaded ${result.path}`;
        } else {
            editorStatusBar.innerText = result.message;
        }
    };

    // Expose the public API for the EditApp module
    return {
        open: open,
        init: init
    };
})();
/*
 * Copyright (c) 2026 Nicholas Paul Wilde. All rights reserved.
 * DREAMOS DREAMSCRIPT - A simple scripting language interpreter and IDE
 */

window.DreamScriptInterpreter = (() => {
    // --- Interpreter State ---
    let state = {};

    const resetState = () => {
        state = {
            lines: [],
            pc: 0, // Program Counter
            scopes: [{}], // Scope stack, global scope is at the bottom
            loopStack: [], // For tracking WHILE/WEND loops
            subroutines: {}, // To store SUB definitions
            callStack: [], // For CALL/END SUB flow
            isWaitingForInput: false,
            inputVarName: null,
            onOutput: () => {},
            onPrompt: () => {},
            onEnd: () => {},
        };
    };

    // --- Callbacks for async operations ---
    let onOutput, onPrompt, onEnd;

    // --- Scope Management ---
    const getCurrentScope = () => state.scopes[state.scopes.length - 1];
    const getVariable = (name) => {
        const varName = name.toUpperCase();
        for (let i = state.scopes.length - 1; i >= 0; i--) {
            if (Object.prototype.hasOwnProperty.call(state.scopes[i], varName)) {
                return state.scopes[i][varName];
            }
        }
        return undefined;
    };
    const setVariable = (name, value) => {
        const varName = name.toUpperCase();
        for (let i = state.scopes.length - 1; i >= 0; i--) {
            if (Object.prototype.hasOwnProperty.call(state.scopes[i], varName)) {
                state.scopes[i][varName] = value;
                return;
            }
        }
        // If not found, declare in current scope
        getCurrentScope()[varName] = value;
    };

    // --- Expression Evaluation ---
    const evaluate = (expression) => {
        // Note: This is a simple left-to-right evaluator.
        // It does NOT respect standard operator precedence (e.g., 1 + 2 * 3 is 9, not 7).
        // It does NOT support parentheses. This should be improved in the future.
        expression = String(expression).trim();

        // Tokenize the expression by spaces, but keep quoted strings together.
        const tokens = expression.match(/"[^"]*"|\S+/g) || [];
        if (tokens.length === 0) return "";

        // First pass: resolve variables to their values
        const values = tokens.map(token => {
            if (token.startsWith('"') && token.endsWith('"')) return token.substring(1, token.length - 1);
            if (!isNaN(token) && token.trim() !== '') return parseFloat(token);
            const value = getVariable(token);
            if (value !== undefined) return value;
            return token; // Keep operators and unresolved tokens as strings
        });

        if (values.length === 1) return values[0];

        // Second pass: evaluate expressions from left to right
        let result = values[0];
        for (let i = 1; i < values.length; i += 2) {
            const op = values[i];
            const right = values[i+1];
            if (right === undefined) throw new Error(`Syntax error in expression near operator '${op}'`);

            switch(op) {
                case '+': result = result + right; break;
                case '-': result = result - right; break;
                case '*': result = result * right; break;
                case '/': result = result / right; break;
                case '=': result = result == right; break;
                case '<>': result = result != right; break;
                case '>': result = result > right; break;
                case '<': result = result < right; break;
                case '>=': result = result >= right; break;
                case '<=': result = result <= right; break;
                default: throw new Error(`Unknown operator or invalid expression: ${op}`);
            }
        }
        return result;
    };

    // --- Pre-computation and Execution ---
    const _scanForSubroutines = () => {
        state.subroutines = {};
        let currentSub = null;
        let subStart = -1;
        let depth = 0;

        for (let i = 0; i < state.lines.length; i++) {
            const uLine = state.lines[i].trim().toUpperCase();
            if (uLine.startsWith('SUB ')) {
                if (depth === 0) { // Only top-level SUBs
                    currentSub = uLine.substring(4).trim();
                    subStart = i;
                }
                depth++;
            } else if (uLine === 'END SUB') {
                depth--;
                if (depth === 0 && currentSub) {
                    state.subroutines[currentSub] = { startPc: subStart + 1 };
                    currentSub = null;
                }
            }
        }
        if (depth !== 0) throw new Error(`Mismatched SUB/END SUB blocks.`);
    };

    // --- Main Execution Logic ---
    const run = (code, outputCb, promptCb, endCb) => {
        console.log('[DreamOS Debug] DreamScriptInterpreter: Running code...');
        resetState();
        state.lines = code.split('\n').map(line => line.trim());
        _scanForSubroutines(); // Scan for subroutines after lines are loaded.
        state.onOutput = outputCb;
        state.onPrompt = promptCb;
        state.onEnd = endCb;
        resume();
    };

    const resume = (inputValue) => {
        if (state.isWaitingForInput) {
            const value = (inputValue === null || inputValue === "" || isNaN(inputValue)) ? inputValue : parseFloat(inputValue);
            setVariable(state.inputVarName, value);
            state.isWaitingForInput = false;
        }

        // Loop indefinitely until paused for input or script ends
        while (true) {
            if (state.pc >= state.lines.length) {
                console.log('[DreamOS Debug] DreamScriptInterpreter: End of script.');
                if (state.onEnd) state.onEnd();
                return;
            }

            const line = state.lines[state.pc];
            const uLine = line.toUpperCase();
            let command = uLine.split(/\s+/)[0];

            try {
                // --- Pre-execution command handling (loops, etc.) ---
                if (command === 'WEND') {
                    if (state.loopStack.length > 0) {
                        const loop = state.loopStack[state.loopStack.length - 1];
                        if (evaluate(loop.condition)) {
                            state.pc = loop.startPc; // Jump back to line after WHILE
                            continue;
                        } else {
                            state.loopStack.pop(); // End of loop
                        }
                    }
                }

                // --- Regular statement execution ---
                if (line === '' || uLine.startsWith("'") || command === 'REM') {
                    // Skip comments and empty lines
                } else if (command === 'PRINT') {
                    const expr = line.substring(5).trim();
                    state.onOutput(evaluate(expr));
                } else if (command === 'INPUT') {
                    const inputParts = line.match(/INPUT\s*(?:"([^"]*)")?,\s*([A-Z_][A-Z0-9_$\s]*)/i);
                    if (!inputParts) throw new Error('Syntax error in INPUT');
                    
                    const [, promptMsg = '? ', varName] = inputParts;
                    state.isWaitingForInput = true;
                    state.inputVarName = varName.trim();
                    state.onPrompt(promptMsg);
                    return; // PAUSE EXECUTION
                } else if (command === 'DIM') {
                    const varName = line.substring(3).trim().split(' ')[0];
                    setVariable(varName, null);
                } else if (uLine.startsWith('IF ')) {
                    const match = line.match(/IF\s+(.*)\s+THEN/i);
                    if (!match) throw new Error(`Syntax error in IF: ${line}`);
                    if (!evaluate(match[1])) {
                        // Condition is false, skip to ELSE or END IF
                        let depth = 1;
                        while (state.pc < state.lines.length - 1) {
                            state.pc++;
                            const nextLine = state.lines[state.pc].trim().toUpperCase();
                            if (nextLine.startsWith('IF ')) depth++;
                            else if (nextLine === 'END IF') depth--;
                            else if (depth === 1 && (nextLine === 'ELSE' || nextLine.startsWith('ELSEIF '))) {
                                state.pc--; // Let the next loop iteration handle the ELSE/ELSEIF
                                break;
                            }
                            if (depth === 0) {
                                state.pc--; // Found END IF, let next loop handle line after it
                                break;
                            }
                        }
                    }
                } else if (uLine === 'ELSE' || uLine.startsWith('ELSEIF ')) {
                    // If we reach an ELSE, it means the IF was true, so skip to END IF
                    let depth = 1;
                    while (state.pc < state.lines.length - 1) {
                        state.pc++;
                        const nextLine = state.lines[state.pc].trim().toUpperCase();
                        if (nextLine.startsWith('IF ')) depth++;
                        else if (nextLine === 'END IF') depth--;
                        if (depth === 0) {
                            state.pc--;
                            break;
                        }
                    }
                } else if (uLine === 'END IF') {
                    // Do nothing, just moves to next line
                } else if (uLine.startsWith('WHILE ')) {
                    const condition = line.substring(5).trim();
                    if (evaluate(condition)) {
                        state.loopStack.push({ startPc: state.pc + 1, condition: condition });
                    } else {
                        // Skip to WEND
                        let depth = 1;
                        while (state.pc < state.lines.length - 1) {
                            state.pc++;
                            const nextLine = state.lines[state.pc].trim().toUpperCase();
                            if (nextLine.startsWith('WHILE ')) depth++;
                            else if (nextLine === 'WEND') depth--;
                            if (depth === 0) break;
                        }
                    }
                } else if (uLine.startsWith('SUB ')) {
                    // This is a definition, skip to its corresponding END SUB
                    let depth = 1;
                    while (state.pc < state.lines.length - 1) {
                        state.pc++;
                        const nextLine = state.lines[state.pc].toUpperCase();
                        if (nextLine.startsWith('SUB ')) depth++;
                        else if (nextLine === 'END SUB') depth--;
                        if (depth === 0) break;
                    }
                } else if (command === 'CALL') {
                    const subName = line.substring(5).trim().toUpperCase();
                    if (!state.subroutines[subName]) {
                        throw new Error(`Subroutine not found: ${subName}`);
                    }
                    state.callStack.push(state.pc); // Push current address for return
                    state.scopes.push({}); // New scope for the subroutine
                    state.pc = state.subroutines[subName].startPc;
                    continue; // Jump to subroutine, do not increment pc
                } else if (command === 'END SUB') {
                    if (state.callStack.length === 0) {
                        throw new Error('END SUB without CALL');
                    }
                    state.scopes.pop(); // Pop subroutine's scope
                    state.pc = state.callStack.pop(); // Pop return address
                } else if (command === 'SYSCALL') {
                    // SYSCALL "Module.function", arg1, "arg2", ...
                    // The result is stored in the 'RESULT' variable.
                    const argString = line.substring(7).trim();
                    const parts = argString.match(/(?:[^,"]+|"[^"]*")+/g) || [];
                    if (parts.length === 0) throw new Error("SYSCALL requires a function path.");

                    const funcPath = evaluate(parts[0]);
                    const args = parts.slice(1).map(arg => evaluate(arg));

                    const pathParts = funcPath.split('.');
                    let context = window;
                    let func = pathParts.reduce((obj, part) => {
                        context = obj; // Keep track of the object before the final function
                        return obj ? obj[part] : undefined;
                    }, window);

                    if (typeof func !== 'function') throw new Error(`SYSCALL error: '${funcPath}' is not a function.`);
                    setVariable('RESULT', func.apply(context, args));
                } else {
                    // Default to assignment
                    const assignmentMatch = line.match(/^(.+?)\s*=\s*(.+)$/);
                    if (assignmentMatch) {
                        const lhs = assignmentMatch[1].trim();
                        const rhs = assignmentMatch[2].trim();
                        setVariable(lhs, evaluate(rhs));
                    } else {
                        throw new Error(`Unknown command: ${command}`);
                    }
                }
            } catch (e) {
                const errorMsg = `RUNTIME ERROR (line ${state.pc + 1}): ${e.message}`;
                console.error(errorMsg);
                state.onOutput(errorMsg);
                if (state.onEnd) state.onEnd();
                return; // Halt execution
            }

            state.pc++; // Move to the next line
        }
    };

    // For the IDE, a synchronous runner that uses prompt()
    const runSync = (code) => {
        let syncOutput = '';
        run(
            code,
            (text) => { syncOutput += text + '\n'; }, // onOutput
            (promptMsg) => { // onPrompt
                const userInput = prompt(promptMsg);
                // Immediately resume with the input
                resume(userInput);
            },
            () => {} // onEnd
        );
        return syncOutput;
    };

    const interpreter_init = () => {
        if (window.DreamCluster) {
            console.log('[DreamOS Debug] DreamScriptInterpreter: Setting up cluster message listener.');
            // This part is not fully integrated with the new async model yet.
        }
    };

    return { run, resume, runSync, init: interpreter_init };
})();

window.DreamScriptApp = (() => {
    let ideWindow, codeArea, outputArea, runBtn, saveBtn, loadBtn, filenameInput, helpBtn, highlightingEl, helpWindow, helpContent;

    const DREAMSCRIPT_HELP_HTML = `
        <div class="toc">
            <h3>Table of Contents</h3>
            <ul>
                <li><a href="#intro">Introduction</a></li>
                <li><a href="#comments">Comments</a></li>
                <li><a href="#variables">Variables & Assignment</a></li>
                <li><a href="#control-flow">Control Flow</a></li>
                <li><a href="#io">Input/Output</a></li>
                <li><a href="#subs">Subroutines</a></li>
                <li><a href="#syscall">System Calls</a></li>
                <li><a href="#cluster">Cluster Commands</a></li>
            </ul>
        </div>

        <h2 id="intro">Introduction</h2>
        <p>DreamScript is a modern, structured scripting language for DreamOS. It does not use line numbers and supports modern control flow.</p>

        <h2 id="comments">Comments</h2>
        <p>Comments are ignored by the interpreter and are used for code documentation.</p>
        <pre><code>' This is a comment
REM This is also a comment</code></pre>

        <h2 id="variables">Variables & Assignment</h2>
        <p>Variables hold data. They can be explicitly declared with <code>DIM</code> or implicitly on first assignment.</p>
        <h3>Declaration</h3>
        <pre><code>DIM my_variable</code></pre>
        <h3>Operators</h3>
        <p>Supports <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code> for numbers, and <code>+</code> for string concatenation. Expressions are evaluated left-to-right without operator precedence.</p>
        <h3>Assignment</h3>
        <pre><code>my_variable = 10
my_string = "Hello, World!"</code></pre>

        <h2 id="control-flow">Control Flow</h2>
        <p>Control the order of execution.</p>
        <h3>IF...THEN...ELSE</h3>
        <pre><code>IF a = 10 THEN
    PRINT "a is 10"
ELSEIF a = 20 THEN
    PRINT "a is 20"
ELSE
    PRINT "a is something else"
END IF</code></pre>
        <h3>WHILE...WEND Loop</h3>
        <pre><code>DIM i = 0
WHILE i < 5
    PRINT i
    i = i + 1
WEND</code></pre>

        <h2 id="io">Input/Output</h2>
        <h3>PRINT</h3>
        <p>Displays text or variable values to the output panel.</p>
        <pre><code>PRINT "Hello"
PRINT my_variable</code></pre>
        <h3>INPUT</h3>
        <p>Prompts the user for input and stores it in a variable.</p>
        <pre><code>INPUT "What is your name?", user_name</code></pre>

        <h2 id="subs">Subroutines</h2>
        <p>Define reusable blocks of code. They have their own variable scope.</p>
        <pre><code>PRINT "Calling sub..."
CALL MySub
PRINT "Returned from sub."

SUB MySub
  PRINT "Inside the subroutine!"
END SUB</code></pre>

        <h2 id="syscall">System Calls</h2>
        <p>Execute underlying JavaScript functions. The return value is placed in the special <code>RESULT</code> variable.</p>
        <pre><code>SYSCALL "VFS.readFile", "c:\\boot.ini"
PRINT RESULT</code></pre>

        <h2 id="cluster">Cluster Commands</h2>
        <p>Interact with the DreamOS cluster network.</p>
        <h3>CLUSTER BROADCAST</h3>
        <p>Sends a message to all connected peers.</p>
        <pre><code>CLUSTER BROADCAST "Hello everyone!"</code></pre>
        <h3>PEEKMSG$</h3>
        <p>A special read-only variable that retrieves the oldest message from the incoming network queue. It returns an empty string if no messages are waiting.</p>
        <pre><code>' This is not fully supported in the async interpreter yet
DIM msg = PEEKMSG$
PRINT msg</code></pre>
    `;

    const updateHighlighting = () => {
        const code = codeArea.value;
        const escapedCode = code.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');

        const tokenRegex = new RegExp(
            `(?<comment>'.*|REM.*)|` + // Comments
            `(?<string>".*?")|` + // Strings
            `(?<keyword>\\b(?:PRINT|INPUT|IF|THEN|ELSEIF|ELSE|END IF|FOR|TO|STEP|NEXT|WHILE|WEND|DIM|SUB|END SUB|FUNCTION|END FUNCTION|CLASS|END CLASS|NEW|CALL|CLUSTER|BROADCAST|PEEKMSG\\$)\\b)|` + // Keywords
            `(?<number>\\b\\d+(?:\\.\\d+)?\\b)|` + // Numbers
            `(?<variable>\\b[A-Z_][A-Z0-9_]*\\$?\\b)`, // Variables
            'gim'
        );

        const highlightedCode = escapedCode.replace(tokenRegex, (match, ...args) => {
            const groups = args[args.length - 1];
            for (const tokenType in groups) {
                if (groups[tokenType]) {
                    // Use 'ds-' prefix for DreamScript styles
                    return `<span class="ds-${tokenType}">${groups[tokenType]}</span>`;
                }
            }
            return match;
        });

        highlightingEl.querySelector('code').innerHTML = highlightedCode;
    };

    const syncScroll = () => {
        highlightingEl.scrollTop = codeArea.scrollTop;
        highlightingEl.scrollLeft = codeArea.scrollLeft;
    };

    const init = () => {
        console.log('[DreamOS Debug] DreamScriptApp: Initializing...');
        ideWindow = document.getElementById('dreamscript-ide-window');
        codeArea = document.getElementById('dreamscript-ide-code');
        outputArea = document.getElementById('dreamscript-ide-output');
        highlightingEl = document.getElementById('dreamscript-ide-highlighting');
        runBtn = document.getElementById('dreamscript-ide-execute-btn');
        saveBtn = document.getElementById('dreamscript-ide-save-btn');
        loadBtn = document.getElementById('dreamscript-ide-load-btn');
        filenameInput = document.getElementById('dreamscript-ide-filename');
        helpBtn = document.getElementById('dreamscript-ide-help-btn');
        helpWindow = document.getElementById('dreamscript-help-window');
        helpContent = document.getElementById('dreamscript-help-content');

        runBtn.addEventListener('click', onRun);
        saveBtn.addEventListener('click', onSave);
        loadBtn.addEventListener('click', onLoad);
        helpBtn.addEventListener('click', onHelp);

        codeArea.addEventListener('input', updateHighlighting);
        codeArea.addEventListener('scroll', syncScroll);

        DreamScriptInterpreter.init();
        console.log('[DreamOS Debug] DreamScriptApp: Initialized successfully.');
    };

    const open = (path = '', content = '') => {
        console.log(`[DreamOS Debug] DreamScriptApp: Opening with path: "${path}"`);
        if (!ideWindow) {
            console.error("DreamScript IDE not initialized.");
            return;
        }
        ideWindow.classList.remove('hidden');
        WindowManager.focusOrRestore('dreamscript-ide-window');
        filenameInput.value = path;
        codeArea.value = content;
        outputArea.innerText = 'Ready.';
        codeArea.focus();
        updateHighlighting();
        syncScroll();
    };

    const onHelp = () => {
        if (!helpWindow) return;
        helpContent.innerHTML = DREAMSCRIPT_HELP_HTML;
        helpWindow.classList.remove('hidden');
        WindowManager.focusOrRestore('dreamscript-help-window');
    };

    const onRun = () => {
        const code = codeArea.value;
        outputArea.innerText = 'Running...\n';
        // The IDE uses the synchronous runner with blocking prompts
        const result = DreamScriptInterpreter.runSync(code);
        outputArea.innerText = 'Done.\n------\n';
        outputArea.innerText += result;
    };

    const onSave = () => {
        const path = filenameInput.value;
        if (!path) {
            outputArea.innerText = "Error: Filename is required to save.";
            return;
        }
        const result = Kernel.writeFile(path, codeArea.value);
        outputArea.innerText = result.message;
    };

    const onLoad = () => {
        const path = filenameInput.value;
        if (!path) {
            outputArea.innerText = "Error: Filename is required to load.";
            return;
        }
        const result = Kernel.readFile(path);
        if (result.success) {
            codeArea.value = result.content;
            updateHighlighting();
            outputArea.innerText = `Successfully loaded ${result.path}`;
        } else {
            outputArea.innerText = result.message;
        }
    };

    return { open: open,
        init: init };
})();
/*
 * Copyright (c) 2026 Nicholas Paul Wilde. All rights reserved.
 * DREAMOS CHESS - A simple chess game app
 */
window.ChessApp = (() => {
    // --- DOM Elements ---
    let chessWindow, boardEl, statusEl, newGameBtn;

    // --- Game State ---
    let board = [];
    let turn = 'w';
    let selectedSquare = null;
    let gameOver = false;
    let playerColor = 'w';
    let moveHistory = [];

    // --- Constants ---
    const PIECES = {
        'wk': '♔', 'wq': '♕', 'wr': '♖', 'wb': '♗', 'wn': '♘', 'wp': '♙',
        'bk': '♚', 'bq': '♛', 'br': '♜', 'bb': '♝', 'bn': '♞', 'bp': '♟︎'
    };
    const MATERIAL = { 'p': 1, 'n': 3, 'b': 3, 'r': 5, 'q': 9, 'k': 100 };
    const AI_THINK_TIME = 250; // ms
    const SEARCH_DEPTH = 2; // How many moves ahead the AI looks. 2 is reasonable.

    // --- Private Engine Functions ---

    const _getPiece = (r, c) => (board[r] && board[r][c]) ? board[r][c] : null;

    const _isOpponent = (r, c, color) => {
        const piece = _getPiece(r, c);
        return piece && piece.color !== color;
    };

    const _isValid = (r, c) => r >= 0 && r < 8 && c >= 0 && c < 8;

    const _getPieceLegalMoves = (r, c) => {
        const piece = _getPiece(r, c);
        if (!piece) return [];

        const moves = [];
        const { type, color } = piece;

        const addMove = (tr, tc) => {
            if (_isValid(tr, tc) && (!_getPiece(tr, tc) || _isOpponent(tr, tc, color))) {
                moves.push({ from: [r, c], to: [tr, tc] });
            }
        };

        const addSlidingMoves = (dirs) => {
            for (const [dr, dc] of dirs) {
                for (let i = 1; i < 8; i++) {
                    const tr = r + i * dr, tc = c + i * dc;
                    if (!_isValid(tr, tc)) break;
                    const targetPiece = _getPiece(tr, tc);
                    if (targetPiece) {
                        if (targetPiece.color !== color) addMove(tr, tc);
                        break;
                    }
                    addMove(tr, tc);
                }
            }
        };

        switch (type) {
            case 'p': // Pawn
                const dir = color === 'w' ? -1 : 1;
                const startRow = color === 'w' ? 6 : 1;
                // Forward 1
                if (_isValid(r + dir, c) && !_getPiece(r + dir, c)) {
                    addMove(r + dir, c);
                    // Forward 2 from start
                    if (r === startRow && !_getPiece(r + 2 * dir, c)) {
                        addMove(r + 2 * dir, c);
                    }
                }
                // Captures
                [-1, 1].forEach(dc => {
                    if (_isValid(r + dir, c + dc) && _isOpponent(r + dir, c + dc, color)) {
                        addMove(r + dir, c + dc);
                    }
                });
                // En passant
                const lastMove = moveHistory[moveHistory.length - 1];
                if (lastMove && _getPiece(lastMove.to[0], lastMove.to[1])?.type === 'p' && Math.abs(lastMove.from[0] - lastMove.to[0]) === 2) {
                    if (r === lastMove.to[0] && Math.abs(c - lastMove.to[1]) === 1) {
                        moves.push({ from: [r, c], to: [r + dir, lastMove.to[1]], enPassant: true });
                    }
                }
                break;
            case 'r': addSlidingMoves([[0, 1], [0, -1], [1, 0], [-1, 0]]); break;
            case 'b': addSlidingMoves([[1, 1], [1, -1], [-1, 1], [-1, -1]]); break;
            case 'q': addSlidingMoves([[0, 1], [0, -1], [1, 0], [-1, 0], [1, 1], [1, -1], [-1, 1], [-1, -1]]); break;
            case 'n':
                [[1, 2], [1, -2], [-1, 2], [-1, -2], [2, 1], [2, -1], [-2, 1], [-2, -1]].forEach(([dr, dc]) => addMove(r + dr, c + dc));
                break;
            case 'k':
                [[0, 1], [0, -1], [1, 0], [-1, 0], [1, 1], [1, -1], [-1, 1], [-1, -1]].forEach(([dr, dc]) => addMove(r + dr, c + dc));
                // Castling
                if (!piece.hasMoved) {
                    // Kingside
                    const rRook = _getPiece(r, 7);
                    if (rRook?.type === 'r' && !rRook.hasMoved && !_getPiece(r, 5) && !_getPiece(r, 6)) {
                        if (!_isSquareAttackedBy(r, 4, color === 'w' ? 'b' : 'w') && !_isSquareAttackedBy(r, 5, color === 'w' ? 'b' : 'w')) {
                            moves.push({ from: [r, c], to: [r, 6], castling: 'kingside' });
                        }
                    }
                    // Queenside
                    const lRook = _getPiece(r, 0);
                    if (lRook?.type === 'r' && !lRook.hasMoved && !_getPiece(r, 1) && !_getPiece(r, 2) && !_getPiece(r, 3)) {
                        if (!_isSquareAttackedBy(r, 4, color === 'w' ? 'b' : 'w') && !_isSquareAttackedBy(r, 3, color === 'w' ? 'b' : 'w')) {
                            moves.push({ from: [r, c], to: [r, 2], castling: 'queenside' });
                        }
                    }
                }
                break;
        }
        return moves;
    };

    const _isSquareAttackedBy = (r, c, attackerColor) => {
        for (let i = 0; i < 8; i++) {
            for (let j = 0; j < 8; j++) {
                const piece = _getPiece(i, j);
                if (piece && piece.color === attackerColor) {
                    const moves = _getPieceLegalMoves(i, j); // Simplified check, doesn't check for pins
                    if (moves.some(m => m.to[0] === r && m.to[1] === c)) {
                        return true;
                    }
                }
            }
        }
        return false;
    };

    const _findKing = (color) => {
        for (let i = 0; i < 8; i++) {
            for (let j = 0; j < 8; j++) {
                const piece = _getPiece(i, j);
                if (piece && piece.type === 'k' && piece.color === color) {
                    return [i, j];
                }
            }
        }
        return null;
    };

    const _isKingInCheck = (color) => {
        const kingPos = _findKing(color);
        if (!kingPos) return false;
        return _isSquareAttackedBy(kingPos[0], kingPos[1], color === 'w' ? 'b' : 'w');
    };

    const _getAllLegalMoves = (color) => {
        let allMoves = [];
        for (let r = 0; r < 8; r++) {
            for (let c = 0; c < 8; c++) {
                const piece = _getPiece(r, c);
                if (piece && piece.color === color) {
                    _getPieceLegalMoves(r, c).forEach(move => {
                        // Test move to see if it leaves king in check
                        const captured = _makeMove(move);
                        if (!_isKingInCheck(color)) {
                            allMoves.push(move);
                        }
                        _undoMove(move, captured);
                    });
                }
            }
        }
        return allMoves;
    };

    const _makeMove = (move) => {
        const [fr, fc] = move.from;
        const [tr, tc] = move.to;
        const piece = { ..._getPiece(fr, fc), hasMoved: true };
        const captured = _getPiece(tr, tc);

        board[tr][tc] = piece;
        board[fr][fc] = null;

        // Pawn promotion
        if (piece.type === 'p' && (tr === 0 || tr === 7)) {
            board[tr][tc].type = 'q';
        }

        // En passant capture
        if (move.enPassant) {
            const capturedPawnPos = [fr, tc];
            const capturedPawn = _getPiece(capturedPawnPos[0], capturedPawnPos[1]);
            board[capturedPawnPos[0]][capturedPawnPos[1]] = null;
            return capturedPawn; // Special return for undo
        }

        // Castling
        if (move.castling) {
            if (move.castling === 'kingside') {
                board[fr][5] = board[fr][7];
                board[fr][7] = null;
            } else { // queenside
                board[fr][3] = board[fr][0];
                board[fr][0] = null;
            }
        }

        moveHistory.push(move);
        return captured;
    };

    const _undoMove = (move, captured) => {
        const [fr, fc] = move.from;
        const [tr, tc] = move.to;
        const piece = _getPiece(tr, tc);

        // If it was a promotion, revert it
        if (move.promotion) piece.type = 'p';

        board[fr][fc] = piece;
        board[tr][tc] = captured; // Can be null

        // Undo en passant
        if (move.enPassant) {
            board[tr][tc] = null;
            board[fr][tc] = captured;
        }

        // Undo castling
        if (move.castling) {
            if (move.castling === 'kingside') {
                board[fr][7] = board[fr][5];
                board[fr][5] = null;
            } else { // queenside
                board[fr][0] = board[fr][3];
                board[fr][3] = null;
            }
        }

        moveHistory.pop();
    };

    const _getGameState = () => {
        const legalMoves = _getAllLegalMoves(turn);
        if (legalMoves.length === 0) {
            return _isKingInCheck(turn) ? 'checkmate' : 'stalemate';
        }
        if (_isKingInCheck(turn)) return 'check';
        return 'playing';
    };

    // --- Private AI Functions ---

    const _evaluateBoard = () => {
        let score = 0;
        for (let r = 0; r < 8; r++) {
            for (let c = 0; c < 8; c++) {
                const piece = _getPiece(r, c);
                if (piece) {
                    score += MATERIAL[piece.type] * (piece.color === 'w' ? 1 : -1);
                }
            }
        }
        return score;
    };

    const _minimax = (depth, alpha, beta, isMaximizing) => {
        if (depth === 0) return _evaluateBoard();

        const color = isMaximizing ? 'w' : 'b';
        const legalMoves = _getAllLegalMoves(color);

        if (legalMoves.length === 0) {
            if (_isKingInCheck(color)) return isMaximizing ? -Infinity : Infinity; // Checkmate
            return 0; // Stalemate
        }

        if (isMaximizing) {
            let maxEval = -Infinity;
            for (const move of legalMoves) {
                const captured = _makeMove(move);
                const evaluation = _minimax(depth - 1, alpha, beta, false);
                _undoMove(move, captured);
                maxEval = Math.max(maxEval, evaluation);
                alpha = Math.max(alpha, evaluation);
                if (beta <= alpha) break;
            }
            return maxEval;
        } else {
            let minEval = Infinity;
            for (const move of legalMoves) {
                const captured = _makeMove(move);
                const evaluation = _minimax(depth - 1, alpha, beta, true);
                _undoMove(move, captured);
                minEval = Math.min(minEval, evaluation);
                beta = Math.min(beta, evaluation);
                if (beta <= alpha) break;
            }
            return minEval;
        }
    };

    const _findBestMove = () => {
        const legalMoves = _getAllLegalMoves(turn);
        if (legalMoves.length === 0) return null;

        let bestMove = null;
        let bestValue = turn === playerColor ? -Infinity : Infinity;

        for (const move of legalMoves) {
            const captured = _makeMove(move);
            const boardValue = _minimax(SEARCH_DEPTH - 1, -Infinity, Infinity, turn !== playerColor);
            _undoMove(move, captured);

            if (turn === playerColor) { // Player is maximizing
                if (boardValue > bestValue) {
                    bestValue = boardValue;
                    bestMove = move;
                }
            } else { // AI is minimizing
                if (boardValue < bestValue) {
                    bestValue = boardValue;
                    bestMove = move;
                }
            }
        }
        return bestMove || legalMoves[Math.floor(Math.random() * legalMoves.length)]; // Fallback
    };

    const _makeAIMove = () => {
        if (gameOver || turn === playerColor) return;
        _updateStatus("Computer is thinking...");

        setTimeout(() => {
            const bestMove = _findBestMove();
            if (bestMove) {
                _makeMove(bestMove);
                turn = playerColor;
                _drawBoard();
                _checkGameState();
            }
        }, AI_THINK_TIME);
    };

    // --- Private UI Functions ---

    const _createBoardUI = () => {
        boardEl.innerHTML = '';
        for (let r = 0; r < 8; r++) {
            for (let c = 0; c < 8; c++) {
                const square = document.createElement('div');
                square.className = `chess-square ${(r + c) % 2 === 0 ? 'light' : 'dark'}`;
                square.dataset.r = r;
                square.dataset.c = c;
                boardEl.appendChild(square);
            }
        }
        boardEl.addEventListener('click', _onSquareClick);
    };

    const _drawBoard = () => {
        document.querySelectorAll('.chess-square').forEach(sq => {
            sq.innerHTML = ''; // Clear piece and dots
            sq.classList.remove('selected');
        });

        for (let r = 0; r < 8; r++) {
            for (let c = 0; c < 8; c++) {
                const piece = _getPiece(r, c);
                if (piece) {
                    const squareEl = boardEl.querySelector(`[data-r='${r}'][data-c='${c}']`);
                    const pieceEl = document.createElement('span');
                    pieceEl.className = 'chess-piece';
                    pieceEl.innerText = PIECES[piece.color + piece.type];
                    squareEl.appendChild(pieceEl);
                }
            }
        }
    };

    const _updateStatus = (message) => {
        statusEl.innerText = message;
    };

    const _checkGameState = () => {
        const state = _getGameState();
        let message = turn === 'w' ? "White's turn" : "Black's turn";
        switch (state) {
            case 'check':
                message += ' - Check!';
                break;
            case 'checkmate':
                message = `Checkmate! ${turn === 'w' ? 'Black' : 'White'} wins.`;
                gameOver = true;
                break;
            case 'stalemate':
                message = "Stalemate! It's a draw.";
                gameOver = true;
                break;
        }
        _updateStatus(message);
        return state;
    };

    const _onSquareClick = (e) => {
        if (gameOver || turn !== playerColor) return;

        const square = e.target.closest('.chess-square');
        if (!square) return;

        const r = parseInt(square.dataset.r);
        const c = parseInt(square.dataset.c);

        if (selectedSquare) {
            const [sr, sc] = selectedSquare;
            const legalMoves = _getAllLegalMoves(playerColor).filter(m => m.from[0] === sr && m.from[1] === sc);
            const move = legalMoves.find(m => m.to[0] === r && m.to[1] === c);

            if (move) {
                _makeMove(move);
                turn = playerColor === 'w' ? 'b' : 'w';
                selectedSquare = null;
                _drawBoard();
                if (_checkGameState() !== 'checkmate') {
                    _makeAIMove();
                }
            } else {
                selectedSquare = null;
                _drawBoard(); // Clear highlights
            }
        } else {
            const piece = _getPiece(r, c);
            if (piece && piece.color === playerColor) {
                selectedSquare = [r, c];
                _drawBoard(); // Clear old highlights
                square.classList.add('selected');
                const legalMoves = _getAllLegalMoves(playerColor).filter(m => m.from[0] === r && m.from[1] === c);
                legalMoves.forEach(m => {
                    const targetSquare = boardEl.querySelector(`[data-r='${m.to[0]}'][data-c='${m.to[1]}']`);
                    const dot = document.createElement('div');
                    dot.className = 'legal-move-dot';
                    targetSquare.appendChild(dot);
                });
            }
        }
    };

    const _startNewGame = () => {
        const initialBoard = [
            ['br', 'bn', 'bb', 'bq', 'bk', 'bb', 'bn', 'br'],
            ['bp', 'bp', 'bp', 'bp', 'bp', 'bp', 'bp', 'bp'],
            [null, null, null, null, null, null, null, null],
            [null, null, null, null, null, null, null, null],
            [null, null, null, null, null, null, null, null],
            [null, null, null, null, null, null, null, null],
            ['wp', 'wp', 'wp', 'wp', 'wp', 'wp', 'wp', 'wp'],
            ['wr', 'wn', 'wb', 'wq', 'wk', 'wb', 'wn', 'wr'],
        ];

        board = initialBoard.map(row => row.map(p => p ? { color: p[0], type: p[1], hasMoved: false } : null));

        turn = 'w';
        playerColor = 'w';
        gameOver = false;
        selectedSquare = null;
        moveHistory = [];
        _drawBoard();
        _updateStatus("New game. White's turn.");
    };

    // --- Public API ---

    const init = () => {
        console.log('[DreamOS Debug] ChessApp: Initializing...');
        chessWindow = document.getElementById('chess-window');
        boardEl = document.getElementById('chessboard');
        statusEl = document.getElementById('chess-status-bar');
        newGameBtn = document.getElementById('chess-new-game-btn');

        _createBoardUI();
        newGameBtn.addEventListener('click', _startNewGame);
        console.log('[DreamOS Debug] ChessApp: Initialized successfully.');
    };

    const open = () => {
        console.log(`[DreamOS Debug] ChessApp: Opening...`);
        if (!chessWindow) {
            console.error("Chess app not initialized.");
            return;
        }
        chessWindow.classList.remove('hidden');
        _startNewGame();
    };

    return { init, open };
})();
/*
 * Copyright (c) 2026 Nicholas Paul Wilde. All rights reserved.
 * DREAMOS ADVENTURE - A data-driven text adventure game engine
 */
window.AdventureApp = (() => {
    // --- DOM Elements ---
    let adventureWindow, outputEl, inputEl;
    let scriptCode = '';

    // --- Private UI Functions ---

    const _appendToOutput = (text, className = '') => {
        // The interpreter might send numbers, so ensure text is a string.
        text = String(text);
        const line = document.createElement('div');
        if (className) line.className = className;
        line.innerHTML = text.replace(/\n/g, '<br>');
        outputEl.appendChild(line);
        outputEl.scrollTop = outputEl.scrollHeight;
    };

    const _handleScriptOutput = (text) => {
        _appendToOutput(text);
    };

    const _handleScriptPrompt = (promptMsg) => {
        _appendToOutput(promptMsg, 'command-echo');
        inputEl.disabled = false;
        inputEl.focus();
    };

    const _handleScriptEnd = () => {
        _appendToOutput("\n[The adventure has ended. Reload the window to play again.]", "command-echo");
        inputEl.disabled = true;
    };

    const _onInput = (e) => {
        if (e.key === 'Enter') {
            const command = inputEl.value;
            _appendToOutput(`> ${command}`, 'command-echo');
            inputEl.value = '';
            inputEl.disabled = true;
            // Resume the interpreter with the user's command
            DreamScriptInterpreter.resume(command);
        }
    };

    const _startNewGame = () => {
        outputEl.innerHTML = '';
        _appendToOutput("Loading DreamScript Adventure...");
        DreamScriptInterpreter.run(scriptCode, _handleScriptOutput, _handleScriptPrompt, _handleScriptEnd);
    };

    // --- Public API ---

    const init = () => {
        console.log('[DreamOS Debug] AdventureApp: Initializing...');
        adventureWindow = document.getElementById('adventure-window');
        outputEl = document.getElementById('adventure-output');
        inputEl = document.getElementById('adventure-input');

        if (!adventureWindow || !outputEl || !inputEl) {
            console.error("AdventureApp Error: A required DOM element is missing.");
            return;
        }

        inputEl.addEventListener('keydown', _onInput);

        // Load the adventure script from the VFS
        const scriptFile = Kernel.readFile("C:\\inetpub\\wwwroot\\adventure.ds");
        if (scriptFile.success) {
            scriptCode = scriptFile.content;
        } else {
            scriptCode = `PRINT "Error: Could not load adventure.ds from VFS."`;
        }
        console.log('[DreamOS Debug] AdventureApp: Initialized successfully.');
    };

    const open = () => {
        console.log(`[DreamOS Debug] AdventureApp: Opening...`);
        if (!adventureWindow) {
            console.error("Adventure app not initialized.");
            return;
        }
        adventureWindow.classList.remove('hidden');
        WindowManager.focusOrRestore('adventure-window');
        _startNewGame();
        inputEl.focus();
    };

    return { init, open };
})();
/*
 * Copyright (c) 2026 Nicholas Paul Wilde. All rights reserved.
 * DREAMOS SHELL - User Interface & Terminal Controller
 */
console.log('[DreamOS Debug] Shell: Starting initialization.');
const input = document.getElementById('command-input');
const output = document.getElementById('output');
const clock = document.getElementById('clock');
const startBtn = document.getElementById('start-btn');
const startMenu = document.getElementById('start-menu');
const vddOverlay = document.getElementById('vdd-overlay');
const vddStatus = document.getElementById('vdd-status');
const promptText = document.getElementById('prompt-text');
const terminalWindow = document.getElementById('terminal-window');
const taskbarAppsContainer = document.getElementById('taskbar-apps');

const mainFrame = document.getElementById('main-frame');

console.log('[DreamOS Debug] Shell: DOM elements cached.');

// Initialize App Modules
console.log('[DreamOS Debug] Shell: Initializing EditApp...');
EditApp.init();
console.log('[DreamOS Debug] Shell: EditApp initialized.');
console.log('[DreamOS Debug] Shell: Initializing DreamScriptApp...');
DreamScriptApp.init();
console.log('[DreamOS Debug] Shell: DreamScriptApp initialized.');
console.log('[DreamOS Debug] Shell: Initializing ChessApp...');
ChessApp.init();
console.log('[DreamOS Debug] Shell: ChessApp initialized.');
console.log('[DreamOS Debug] Shell: Initializing AdventureApp...');
AdventureApp.init();
console.log('[DreamOS Debug] Shell: AdventureApp initialized.');
console.log('[DreamOS Debug] Shell: Initializing HelpApp...');
HelpApp.init();
console.log('[DreamOS Debug] Shell: HelpApp initialized.');
console.log('[DreamOS Debug] Shell: Initializing WindowManager...');
WindowManager.init();
console.log('[DreamOS Debug] Shell: WindowManager initialized.');

// --- INITIALIZATION ---
const updateClock = () => {
    const now = new Date();
    clock.innerText = now.getHours().toString().padStart(2, '0') + ':' +
                        now.getMinutes().toString().padStart(2, '0');
};
updateClock();
setInterval(updateClock, 1000);
console.log('[DreamOS Debug] Shell: Clock setup complete.');

// --- Cluster Initialization with Password ---
console.log('[DreamOS Debug] Shell: Starting cluster initialization...');
// We ask for a password once. A loop is avoided to prevent the UI from freezing
// if the prompt is blocked by the browser or the user enters an empty string.
const passwordPromptMessage = 
    'Welcome to the DreamOS Cluster!\n\n' +
    'Please enter a shared password. This will be used to create a private network.\n' +
    'All nodes you want to connect MUST use the exact same password.';

let encryptionKey;
try {
    // This can be blocked by the browser when loaded over http, sometimes throwing an error.
    encryptionKey = prompt(passwordPromptMessage);
} catch (e) {
    console.error("The password prompt was blocked by the browser, causing an error:", e);
    encryptionKey = null; // Ensure key is null on error so the script can continue.
}

// An empty string or null (from cancel/block) are both invalid for the key.
// The `if (encryptionKey)` check correctly handles null, undefined, and "" as falsy.
if (encryptionKey) {
    console.log('[DreamOS Debug] Shell: Password provided. Initializing DreamCluster.');
    DreamCluster.init(encryptionKey, (status) => {
        if (!status.connected) {
            appendToOutput(`[Cluster] ${status.message}`);
        }
    });
} else {
    appendToOutput("[Cluster] Initialization skipped: No valid password provided.");
    console.log('[DreamOS Debug] Shell: No password. Skipping cluster initialization.');
}
console.log('[DreamOS Debug] Shell: Cluster initialization finished.');

const refreshVDD = () => {
    const status = HAL.getPowerStatus();
    vddOverlay.innerText = `VDD_STAT: ${status.gpu} | ${status.vram} | ${status.status}`;
    vddStatus.innerText = `WDDM:${status.status}`;
};
refreshVDD();
setInterval(refreshVDD, 5000);

console.log('[DreamOS Debug] Shell: Setting up background music...');
// --- Background Music (Shuffle Mode) ---
// As I cannot browse your website, I've created a placeholder playlist.
// Please replace these with the actual URLs of your MP3 files.
const musicPlaylist = [
    'https://nicholaswilde.net/rewind.mp3',
    'https://nicholaswilde.net/badbrain.mp3',
    'https://nicholaswilde.net/ballpark.mp3',
    'https://nicholaswilde.net/country.mp3',
    'https://nicholaswilde.net/dcs.mp3',
    'https://nicholaswilde.net/death.mp3',
    'https://nicholaswilde.net/hack.mp3',
    'https://nicholaswilde.net/haha.mp3',
    'https://nicholaswilde.net/paranoia.mp3',
    'https://nicholaswilde.net/sd.mp3',
    'https://nicholaswilde.net/stars.mp3',
    'https://nicholaswilde.net/stc.mp3',
    'https://nicholaswilde.net/worry.mp3'
];

const backgroundMusic = new Audio();
backgroundMusic.loop = false; // Explicitly disable looping for shuffle to work
// Set volume (optional, default is 1.0)
// backgroundMusic.volume = 0.5;

// Function to play the next random song
const playNextRandomSong = () => {
    // Remove any lingering interaction listeners before we start
    document.removeEventListener('click', playNextRandomSong);
    document.removeEventListener('keydown', playNextRandomSong);

    if (musicPlaylist.length === 0) {
        console.warn("Music playlist is empty.");
        return;
    }
    const randomIndex = Math.floor(Math.random() * musicPlaylist.length);
    backgroundMusic.src = musicPlaylist[randomIndex];
    
    const promise = backgroundMusic.play();
    if (promise !== undefined) {
        promise.catch(error => {
            // Autoplay was prevented. We'll wait for a user interaction.
            console.warn("Autoplay prevented by browser. Click or press a key to start music.");
            // Add listeners that will try to play again on the first interaction.
            document.addEventListener('click', playNextRandomSong, { once: true });
            document.addEventListener('keydown', playNextRandomSong, { once: true });
        });
    }
};

// When a song finishes, play the next random one.
backgroundMusic.addEventListener('ended', playNextRandomSong);

// Delay the initial playback attempt until 5 seconds after the OE fully loads
setTimeout(playNextRandomSong, 5000);

// Expose music controls to the Kernel via the window object
window.musicControls = {
    play: () => backgroundMusic.play(),
    pause: () => backgroundMusic.pause(),
    skip: playNextRandomSong
};
console.log('[DreamOS Debug] Shell: Background music setup complete.');

input.focus();
console.log('[DreamOS Debug] Shell: Focused command input.');

// --- Global Click Handler for Start Menu ---
console.log('[DreamOS Debug] Shell: Attaching global click listener for start menu.');
document.addEventListener('click', (e) => {
    // If the click is outside the start menu and not on the start button, hide the menu.
    if (!startMenu.contains(e.target) && e.target !== startBtn) {
        startMenu.classList.add('hidden');
    }
});

// --- Terminal Window Focus Logic ---
console.log('[DreamOS Debug] Shell: Attaching terminal focus listener.');
// When the terminal window itself is clicked, ensure the input field gets focus.
terminalWindow.addEventListener('click', (e) => {
    // If the click is inside the terminal window but not on the header, focus the input.
    if (!e.target.closest('.window-header')) {
        console.log('[DreamOS Debug] Shell: Terminal window clicked, focusing input.');
        input.focus();
    }
});

// --- INPUT HANDLING ---
input.addEventListener('keydown', (e) => {
    if (e.key === 'Enter') {
        console.log('[DreamOS Debug] Shell: Enter key pressed in command input.');
        const cmd = input.value.trim();
        if (cmd) {
            const currentPrompt = promptText.innerText;
            appendToOutput(`<span class="prompt">${currentPrompt}</span> ${cmd}`);

            const result = Kernel.execute(cmd);

            // Handle special signals from the kernel for UI actions
            if (typeof result === 'object' && result !== null && result.signal) {
                if (result.signal === 'KERNEL_SIGNAL_OPEN_DREAMSCRIPT_IDE') {
                    DreamScriptApp.open();
                } else if (result.signal === 'KERNEL_SIGNAL_OPEN_ADVENTURE') {
                    AdventureApp.open();
                } else if (result.signal === 'KERNEL_SIGNAL_OPEN_CHESS') {
                    ChessApp.open();
                } else if (result.signal === 'KERNEL_SIGNAL_OPEN_EDITOR') {
                    EditApp.open(result.path, result.content); // Call the new EditApp module
                } else if (result.signal === 'KERNEL_SIGNAL_OPEN_HELP') {
                    HelpApp.open();
                }
                // No text output for signal commands, so we don't fall through
            } else if (result === "KERNEL_SIGNAL_CLS") {
                output.innerHTML = '';
            } else if (result) {
                appendToOutput(result);
            }

            promptText.innerText = VFS.getPath() + ">";
        }
        input.value = '';
        const container = terminalWindow.querySelector('.window-content');
        container.scrollTop = container.scrollHeight;
    }
});

console.log('[DreamOS Debug] Shell: Attaching start button click listener.');
startBtn.addEventListener('click', (e) => {
    console.log('[DreamOS Debug] Shell: Start button clicked.');
    e.stopPropagation();
    startMenu.classList.toggle('hidden');
});

// --- Start Menu Item Click Handlers ---
console.log('[DreamOS Debug] Shell: Attaching start menu item listeners.');
// We set these up programmatically to ensure all scripts are loaded first.
document.getElementById('start-menu-nwhome').addEventListener('click', () => {
    mainFrame.src = 'http://nicholaswilde.net/index.php';
    startMenu.classList.add('hidden');
});
document.getElementById('start-menu-fleagrass').addEventListener('click', () => {
    mainFrame.src = 'http://fleagrass.com/';
    startMenu.classList.add('hidden');
});
document.getElementById('start-menu-dalnet').addEventListener('click', () => {
    mainFrame.src = 'https://www.dal.net/webchat/';
    startMenu.classList.add('hidden');
});
document.getElementById('start-menu-console').addEventListener('click', () => {
    WindowManager.focusOrRestore('terminal-window');
    startMenu.classList.add('hidden');
});
document.getElementById('start-menu-notepad').addEventListener('click', () => {
    EditApp.open();
    startMenu.classList.add('hidden');
});
document.getElementById('start-menu-dreamscript').addEventListener('click', () => {
    DreamScriptApp.open();
    startMenu.classList.add('hidden');
});
document.getElementById('start-menu-chess').addEventListener('click', () => {
    ChessApp.open();
    startMenu.classList.add('hidden');
});
document.getElementById('start-menu-adventure').addEventListener('click', () => {
    AdventureApp.open();
    startMenu.classList.add('hidden');
});
document.getElementById('start-menu-reboot').addEventListener('click', () => location.reload());
console.log('[DreamOS Debug] Shell: All start menu item listeners attached.');

function appendToOutput(text) {
    const line = document.createElement('div');
    line.innerHTML = String(text).replace(/\n/g, '<br>');
    output.appendChild(line);
}

console.log('[DreamOS Debug] Shell: Initialization complete. System is ready.');


    </script>
</body>
</html>

Comments

Popular posts from this blog