/**
 * @file VisualScripting2.ts
 * @description Visual Scripting 2.0 — Node-based Scripting System with Debugger
 * PRO-1.4: Professional Editor Features
 *
 * Features:
 * - Node-based visual programming (like Unreal Blueprints)
 * - Real-time debugger with breakpoints
 * - Step-by-step execution
 * - Watch expressions
 * - Variable inspection
 * - Call stack visualization
 * - Live preview in editor
 */
/** Type color mapping for visual identification */
const VS_TYPE_COLORS = {
    flow: '#ffffff',
    bool: '#dc2626', // Red
    int: '#22d3ee', // Cyan
    float: '#10b981', // Green
    string: '#f472b6', // Pink
    vec2: '#fbbf24', // Yellow
    vec3: '#fbbf24', // Yellow
    color: '#c084fc', // Purple
    entity: '#3b82f6', // Blue
    component: '#8b5cf6', // Violet
    asset: '#f97316', // Orange
    array: '#6b7280', // Gray
    map: '#6b7280', // Gray
    struct: '#14b8a6', // Teal
    object: '#6b7280', // Gray
    enum: '#84cc16', // Lime
    delegate: '#ef4444', // Red
    wildcard: '#a3a3a3', // Neutral
};
// ============================================================
// Visual Scripting Debugger
// ============================================================
class VSDebugger {
    constructor() {
        this.eventListeners = new Map();
        this.session = this.createSession();
    }
    createSession() {
        return {
            state: 'stopped',
            currentNode: null,
            currentGraph: null,
            callStack: [],
            breakpoints: new Map(),
            watches: [],
            history: [],
            historyIndex: -1,
            profiling: {
                enabled: false,
                nodeExecutionTimes: new Map(),
                totalFrameTime: 0,
                frameCount: 0,
            },
        };
    }
    // ─── Session Control ─────────────────────────────
    start() {
        this.session.state = 'running';
        this.emit('graph-started', {});
    }
    pause() {
        this.session.state = 'paused';
    }
    resume() {
        if (this.session.state === 'paused') {
            this.session.state = 'running';
        }
    }
    stop() {
        this.session = this.createSession();
        this.emit('graph-completed', {});
    }
    getState() {
        return this.session.state;
    }
    // ─── Stepping ────────────────────────────────────
    stepOver() {
        this.session.state = 'stepping';
        // Implementation would execute current node and stop at next
    }
    stepInto() {
        this.session.state = 'stepping';
        // Implementation would step into function/macro
    }
    stepOut() {
        this.session.state = 'stepping';
        // Implementation would step out of current function
    }
    stepBack() {
        if (this.session.historyIndex > 0) {
            this.session.historyIndex--;
            const snapshot = this.session.history[this.session.historyIndex];
            this.session.currentNode = snapshot.nodeId;
            // Restore state from snapshot
        }
    }
    // ─── Breakpoints ─────────────────────────────────
    addBreakpoint(nodeId, options) {
        const bp = {
            id: `bp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
            nodeId,
            enabled: true,
            ...options,
        };
        this.session.breakpoints.set(bp.id, bp);
        return bp;
    }
    removeBreakpoint(breakpointId) {
        this.session.breakpoints.delete(breakpointId);
    }
    toggleBreakpoint(nodeId) {
        // Find existing breakpoint on this node
        for (const bp of this.session.breakpoints.values()) {
            if (bp.nodeId === nodeId) {
                this.removeBreakpoint(bp.id);
                return null;
            }
        }
        return this.addBreakpoint(nodeId);
    }
    setBreakpointCondition(breakpointId, condition) {
        const bp = this.session.breakpoints.get(breakpointId);
        if (bp) {
            bp.condition = condition;
        }
    }
    enableBreakpoint(breakpointId, enabled) {
        const bp = this.session.breakpoints.get(breakpointId);
        if (bp) {
            bp.enabled = enabled;
        }
    }
    getBreakpoints() {
        return Array.from(this.session.breakpoints.values());
    }
    // ─── Watch Expressions ───────────────────────────
    addWatch(expression) {
        const watch = {
            id: `watch_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
            expression,
            value: undefined,
            type: 'wildcard',
        };
        this.session.watches.push(watch);
        return watch;
    }
    removeWatch(watchId) {
        const idx = this.session.watches.findIndex((w) => w.id === watchId);
        if (idx >= 0) {
            this.session.watches.splice(idx, 1);
        }
    }
    updateWatches(context) {
        for (const watch of this.session.watches) {
            try {
                watch.value = this.evaluateExpression(watch.expression, context);
                watch.error = undefined;
            }
            catch (err) {
                watch.error = String(err);
            }
        }
    }
    getWatches() {
        return [...this.session.watches];
    }
    // ─── Call Stack ──────────────────────────────────
    pushStack(frame) {
        this.session.callStack.push(frame);
    }
    popStack() {
        return this.session.callStack.pop();
    }
    getCallStack() {
        return [...this.session.callStack];
    }
    getCurrentFrame() {
        return this.session.callStack[this.session.callStack.length - 1] || null;
    }
    // ─── History/Snapshots ───────────────────────────
    recordSnapshot(snapshot) {
        // Limit history size
        const MAX_HISTORY = 1000;
        if (this.session.history.length >= MAX_HISTORY) {
            this.session.history.shift();
        }
        this.session.history.push(snapshot);
        this.session.historyIndex = this.session.history.length - 1;
    }
    getHistory() {
        return [...this.session.history];
    }
    // ─── Profiling ───────────────────────────────────
    enableProfiling(enabled) {
        this.session.profiling.enabled = enabled;
        if (!enabled) {
            this.session.profiling.nodeExecutionTimes.clear();
            this.session.profiling.totalFrameTime = 0;
            this.session.profiling.frameCount = 0;
        }
    }
    recordNodeTime(nodeId, timeMs) {
        if (!this.session.profiling.enabled)
            return;
        let times = this.session.profiling.nodeExecutionTimes.get(nodeId);
        if (!times) {
            times = [];
            this.session.profiling.nodeExecutionTimes.set(nodeId, times);
        }
        times.push(timeMs);
        // Keep last 100 samples
        if (times.length > 100) {
            times.shift();
        }
    }
    getNodeAverageTime(nodeId) {
        const times = this.session.profiling.nodeExecutionTimes.get(nodeId);
        if (!times || times.length === 0)
            return 0;
        return times.reduce((a, b) => a + b, 0) / times.length;
    }
    getProfilingData() {
        return { ...this.session.profiling };
    }
    // ─── Expression Evaluation ───────────────────────
    evaluateExpression(expr, context) {
        // Safe expression evaluator (no eval!)
        // Parse simple expressions like: entity.transform.position.x
        // Or: variables.health > 50
        const parts = expr.split('.');
        let value = undefined;
        if (parts[0] === 'entity' && context.entityId) {
            // Entity property access
            if (parts[1]) {
                const component = context.getComponent(context.entityId, parts[1]);
                if (component && parts[2]) {
                    value = this.getNestedValue(component, parts.slice(2));
                }
                else {
                    value = component;
                }
            }
        }
        else if (parts[0] === 'variables') {
            // Variable access
            if (parts[1]) {
                value = context.variables.get(parts[1]);
            }
        }
        else if (parts[0] === 'globals') {
            if (parts[1]) {
                value = context.globals.get(parts[1]);
            }
        }
        else if (parts[0] === 'dt') {
            value = context.dt;
        }
        else if (parts[0] === 'time') {
            value = context.time;
        }
        return value;
    }
    getNestedValue(obj, path) {
        let current = obj;
        for (const key of path) {
            if (current && typeof current === 'object' && key in current) {
                current = current[key];
            }
            else {
                return undefined;
            }
        }
        return current;
    }
    // ─── Event System ────────────────────────────────
    on(event, listener) {
        let listeners = this.eventListeners.get(event);
        if (!listeners) {
            listeners = [];
            this.eventListeners.set(event, listeners);
        }
        listeners.push(listener);
    }
    off(event, listener) {
        const listeners = this.eventListeners.get(event);
        if (listeners) {
            const idx = listeners.indexOf(listener);
            if (idx >= 0) {
                listeners.splice(idx, 1);
            }
        }
    }
    emit(type, data) {
        const event = {
            type,
            timestamp: Date.now(),
            data,
        };
        const listeners = this.eventListeners.get(type);
        if (listeners) {
            for (const listener of listeners) {
                listener(event);
            }
        }
    }
    // ─── Node Execution Hook ─────────────────────────
    onNodeStartExecution(nodeId, inputs) {
        // Check breakpoints
        for (const bp of this.session.breakpoints.values()) {
            if (bp.nodeId === nodeId && bp.enabled) {
                // Check condition if set
                if (bp.condition) ;
                // Check hit count
                if (bp.hitCount !== undefined) {
                    bp.hitCount--;
                    if (bp.hitCount > 0)
                        continue;
                }
                // Log message instead of breaking?
                if (bp.logMessage) {
                    console.log(`[VS Breakpoint] ${bp.logMessage}`);
                    continue;
                }
                // Hit breakpoint!
                this.session.state = 'paused';
                this.session.currentNode = nodeId;
                this.emit('breakpoint-hit', { nodeId, breakpoint: bp });
                // Remove temporary breakpoint
                if (bp.temporary) {
                    this.removeBreakpoint(bp.id);
                }
                return false; // Pause execution
            }
        }
        // Record for history
        this.recordSnapshot({
            timestamp: Date.now(),
            nodeId,
            inputs,
            outputs: {},
            variables: new Map(),
        });
        return true; // Continue execution
    }
    onNodeCompleteExecution(nodeId, outputs, timeMs) {
        // Update last snapshot with outputs
        if (this.session.history.length > 0) {
            const lastSnapshot = this.session.history[this.session.history.length - 1];
            if (lastSnapshot.nodeId === nodeId) {
                lastSnapshot.outputs = outputs;
            }
        }
        // Record profiling
        this.recordNodeTime(nodeId, timeMs);
        // Emit event
        this.emit('node-executed', { nodeId, outputs, timeMs });
        // Step mode handling
        if (this.session.state === 'stepping') {
            this.session.state = 'paused';
            this.emit('step-completed', { nodeId });
        }
    }
}
// ============================================================
// Enhanced Graph Executor with Debugging
// ============================================================
class VSGraphExecutor {
    constructor(debuggerInstance) {
        this.nodeLibrary = new Map();
        this.executionQueue = [];
        this.debugger = debuggerInstance || new VSDebugger();
    }
    // ─── Node Registration ───────────────────────────
    registerNode(definition) {
        this.nodeLibrary.set(definition.type, definition);
    }
    registerNodes(definitions) {
        for (const def of definitions) {
            this.registerNode(def);
        }
    }
    getNodeDefinition(type) {
        return this.nodeLibrary.get(type);
    }
    getAllNodeDefinitions() {
        return Array.from(this.nodeLibrary.values());
    }
    searchNodes(query) {
        const q = query.toLowerCase();
        return this.getAllNodeDefinitions().filter((def) => {
            var _a;
            return def.name.toLowerCase().includes(q) ||
                def.type.toLowerCase().includes(q) ||
                def.description.toLowerCase().includes(q) ||
                ((_a = def.keywords) === null || _a === void 0 ? void 0 : _a.some((k) => k.toLowerCase().includes(q)));
        });
    }
    // ─── Execution ───────────────────────────────────
    execute(graph, entryType, context) {
        this.debugger.start();
        // Find entry nodes
        const entryNodes = graph.nodes.filter((n) => n.type === entryType && !n.disabled);
        for (const entryNode of entryNodes) {
            this.executeNode(graph, entryNode, context);
        }
    }
    executeNode(graph, node, context) {
        if (node.disabled)
            return;
        const definition = this.nodeLibrary.get(node.type);
        if (!definition) {
            context.log('error', `Unknown node type: ${node.type}`);
            return;
        }
        // Gather inputs from connections
        const inputs = { ...node.inputs };
        for (const conn of graph.connections) {
            if (conn.toNode === node.id) {
                const sourceNode = graph.nodes.find((n) => n.id === conn.fromNode);
                if (sourceNode) {
                    inputs[conn.toPort] = sourceNode.outputs[conn.fromPort];
                }
            }
        }
        // Apply default values for unconnected inputs
        for (const port of definition.ports) {
            if (port.direction === 'input' && inputs[port.id] === undefined) {
                inputs[port.id] = port.defaultValue;
            }
        }
        // Debug hook - before execution
        if (!this.debugger.onNodeStartExecution(node.id, inputs)) {
            // Debugger paused execution
            this.executionQueue.push({ graph, nodeId: node.id, context });
            return;
        }
        // Track flow outputs
        const triggeredFlows = [];
        const originalTrigger = context.triggerFlow;
        context.triggerFlow = (portId) => {
            triggeredFlows.push(portId);
        };
        // Execute node
        const startTime = performance.now();
        let outputs = {};
        try {
            const result = definition.execute(inputs, context);
            if (result && !(result instanceof Promise)) {
                outputs = result;
            }
            else if (result instanceof Promise) {
                // Handle async nodes
                result
                    .then((asyncOutputs) => {
                    node.outputs = asyncOutputs;
                    this.followFlowConnections(graph, node, triggeredFlows, context);
                })
                    .catch((err) => {
                    context.log('error', `Node ${node.id} error: ${err}`);
                });
                return;
            }
        }
        catch (err) {
            context.log('error', `Node ${node.id} error: ${err}`);
        }
        const executionTime = performance.now() - startTime;
        // Store outputs
        node.outputs = outputs;
        // Restore trigger function
        context.triggerFlow = originalTrigger;
        // Debug hook - after execution
        this.debugger.onNodeCompleteExecution(node.id, outputs, executionTime);
        // Follow flow connections
        this.followFlowConnections(graph, node, triggeredFlows, context);
    }
    followFlowConnections(graph, node, triggeredFlows, context) {
        for (const flowPort of triggeredFlows) {
            const flowConnections = graph.connections.filter((c) => c.fromNode === node.id && c.fromPort === flowPort);
            for (const conn of flowConnections) {
                const nextNode = graph.nodes.find((n) => n.id === conn.toNode);
                if (nextNode) {
                    this.executeNode(graph, nextNode, context);
                }
            }
        }
    }
    // ─── Debugging ───────────────────────────────────
    getDebugger() {
        return this.debugger;
    }
    resumeExecution() {
        this.debugger.resume();
        // Process queued executions
        while (this.executionQueue.length > 0 && this.debugger.getState() === 'running') {
            const queued = this.executionQueue.shift();
            const node = queued.graph.nodes.find((n) => n.id === queued.nodeId);
            if (node) {
                this.executeNode(queued.graph, node, queued.context);
            }
        }
    }
}
// ============================================================
// Built-in Node Definitions
// ============================================================
function createBuiltInNodes() {
    return [
        // ─── Events ────────────────────────────────────
        {
            type: 'event_start',
            name: 'On Start',
            category: 'event',
            description: 'Fires once when the scene starts',
            icon: 'play',
            color: '#dc2626',
            ports: [{ id: 'exec', name: '', direction: 'output', type: 'flow' }],
            execute: (_inputs, ctx) => {
                ctx.triggerFlow('exec');
            },
        },
        {
            type: 'event_update',
            name: 'On Update',
            category: 'event',
            description: 'Fires every frame',
            icon: 'refresh',
            color: '#dc2626',
            ports: [
                { id: 'exec', name: '', direction: 'output', type: 'flow' },
                { id: 'delta', name: 'Delta Time', direction: 'output', type: 'float' },
            ],
            execute: (_inputs, ctx) => {
                ctx.triggerFlow('exec');
                return { delta: ctx.dt };
            },
        },
        {
            type: 'event_input',
            name: 'On Input',
            category: 'event',
            description: 'Fires when input action is triggered',
            icon: 'keyboard',
            color: '#dc2626',
            ports: [
                { id: 'action', name: 'Action', direction: 'input', type: 'string' },
                { id: 'pressed', name: 'Pressed', direction: 'output', type: 'flow' },
                { id: 'released', name: 'Released', direction: 'output', type: 'flow' },
                { id: 'held', name: 'Held', direction: 'output', type: 'flow' },
            ],
            execute: () => { },
        },
        // ─── Flow Control ──────────────────────────────
        {
            type: 'branch',
            name: 'Branch',
            category: 'flow',
            description: 'Branch execution based on condition',
            icon: 'git-branch',
            color: '#f97316',
            ports: [
                { id: 'exec', name: '', direction: 'input', type: 'flow' },
                {
                    id: 'condition',
                    name: 'Condition',
                    direction: 'input',
                    type: 'bool',
                    defaultValue: false,
                },
                { id: 'true', name: 'True', direction: 'output', type: 'flow' },
                { id: 'false', name: 'False', direction: 'output', type: 'flow' },
            ],
            execute: (inputs, ctx) => {
                ctx.triggerFlow(inputs.condition ? 'true' : 'false');
            },
        },
        {
            type: 'sequence',
            name: 'Sequence',
            category: 'flow',
            description: 'Execute outputs in sequence',
            icon: 'list',
            color: '#f97316',
            ports: [
                { id: 'exec', name: '', direction: 'input', type: 'flow' },
                { id: 'then_0', name: 'Then 0', direction: 'output', type: 'flow' },
                { id: 'then_1', name: 'Then 1', direction: 'output', type: 'flow' },
                { id: 'then_2', name: 'Then 2', direction: 'output', type: 'flow' },
            ],
            execute: (_inputs, ctx) => {
                ctx.triggerFlow('then_0');
                ctx.triggerFlow('then_1');
                ctx.triggerFlow('then_2');
            },
        },
        {
            type: 'for_loop',
            name: 'For Loop',
            category: 'flow',
            description: 'Loop from start to end',
            icon: 'repeat',
            color: '#f97316',
            latent: true,
            ports: [
                { id: 'exec', name: '', direction: 'input', type: 'flow' },
                { id: 'start', name: 'Start', direction: 'input', type: 'int', defaultValue: 0 },
                { id: 'end', name: 'End', direction: 'input', type: 'int', defaultValue: 10 },
                { id: 'body', name: 'Loop Body', direction: 'output', type: 'flow' },
                { id: 'index', name: 'Index', direction: 'output', type: 'int' },
                { id: 'completed', name: 'Completed', direction: 'output', type: 'flow' },
            ],
            execute: (inputs, ctx) => {
                const start = inputs.start;
                const end = inputs.end;
                for (let i = start; i < end; i++) {
                    ctx.triggerFlow('body');
                }
                ctx.triggerFlow('completed');
                return { index: end - 1 };
            },
        },
        {
            type: 'while_loop',
            name: 'While Loop',
            category: 'flow',
            description: 'Loop while condition is true',
            icon: 'repeat',
            color: '#f97316',
            latent: true,
            ports: [
                { id: 'exec', name: '', direction: 'input', type: 'flow' },
                { id: 'condition', name: 'Condition', direction: 'input', type: 'bool' },
                { id: 'body', name: 'Loop Body', direction: 'output', type: 'flow' },
                { id: 'completed', name: 'Completed', direction: 'output', type: 'flow' },
            ],
            execute: (inputs, ctx) => {
                let iterations = 0;
                const MAX_ITERATIONS = 10000;
                while (inputs.condition && iterations < MAX_ITERATIONS) {
                    ctx.triggerFlow('body');
                    iterations++;
                }
                ctx.triggerFlow('completed');
            },
        },
        // ─── Math Operations ───────────────────────────
        {
            type: 'math_add',
            name: 'Add',
            category: 'math',
            description: 'Add two numbers',
            icon: 'plus',
            color: '#22c55e',
            pure: true,
            compact: true,
            ports: [
                { id: 'a', name: 'A', direction: 'input', type: 'float', defaultValue: 0 },
                { id: 'b', name: 'B', direction: 'input', type: 'float', defaultValue: 0 },
                { id: 'result', name: 'Result', direction: 'output', type: 'float' },
            ],
            execute: (inputs) => ({ result: inputs.a + inputs.b }),
        },
        {
            type: 'math_subtract',
            name: 'Subtract',
            category: 'math',
            description: 'Subtract two numbers',
            icon: 'minus',
            color: '#22c55e',
            pure: true,
            compact: true,
            ports: [
                { id: 'a', name: 'A', direction: 'input', type: 'float', defaultValue: 0 },
                { id: 'b', name: 'B', direction: 'input', type: 'float', defaultValue: 0 },
                { id: 'result', name: 'Result', direction: 'output', type: 'float' },
            ],
            execute: (inputs) => ({ result: inputs.a - inputs.b }),
        },
        {
            type: 'math_multiply',
            name: 'Multiply',
            category: 'math',
            description: 'Multiply two numbers',
            icon: 'x',
            color: '#22c55e',
            pure: true,
            compact: true,
            ports: [
                { id: 'a', name: 'A', direction: 'input', type: 'float', defaultValue: 1 },
                { id: 'b', name: 'B', direction: 'input', type: 'float', defaultValue: 1 },
                { id: 'result', name: 'Result', direction: 'output', type: 'float' },
            ],
            execute: (inputs) => ({ result: inputs.a * inputs.b }),
        },
        {
            type: 'math_divide',
            name: 'Divide',
            category: 'math',
            description: 'Divide two numbers',
            icon: 'divide',
            color: '#22c55e',
            pure: true,
            compact: true,
            ports: [
                { id: 'a', name: 'A', direction: 'input', type: 'float', defaultValue: 1 },
                { id: 'b', name: 'B', direction: 'input', type: 'float', defaultValue: 1 },
                { id: 'result', name: 'Result', direction: 'output', type: 'float' },
            ],
            execute: (inputs) => ({
                result: inputs.b !== 0 ? inputs.a / inputs.b : 0,
            }),
        },
        {
            type: 'math_clamp',
            name: 'Clamp',
            category: 'math',
            description: 'Clamp value between min and max',
            icon: 'sliders',
            color: '#22c55e',
            pure: true,
            ports: [
                { id: 'value', name: 'Value', direction: 'input', type: 'float', defaultValue: 0 },
                { id: 'min', name: 'Min', direction: 'input', type: 'float', defaultValue: 0 },
                { id: 'max', name: 'Max', direction: 'input', type: 'float', defaultValue: 1 },
                { id: 'result', name: 'Result', direction: 'output', type: 'float' },
            ],
            execute: (inputs) => ({
                result: Math.min(Math.max(inputs.value, inputs.min), inputs.max),
            }),
        },
        {
            type: 'math_lerp',
            name: 'Lerp',
            category: 'math',
            description: 'Linear interpolation between two values',
            icon: 'trending-up',
            color: '#22c55e',
            pure: true,
            ports: [
                { id: 'a', name: 'A', direction: 'input', type: 'float', defaultValue: 0 },
                { id: 'b', name: 'B', direction: 'input', type: 'float', defaultValue: 1 },
                { id: 't', name: 'Alpha', direction: 'input', type: 'float', defaultValue: 0.5 },
                { id: 'result', name: 'Result', direction: 'output', type: 'float' },
            ],
            execute: (inputs) => ({
                result: inputs.a +
                    (inputs.b - inputs.a) * inputs.t,
            }),
        },
        {
            type: 'math_random',
            name: 'Random',
            category: 'math',
            description: 'Generate random number',
            icon: 'shuffle',
            color: '#22c55e',
            pure: true,
            ports: [
                { id: 'min', name: 'Min', direction: 'input', type: 'float', defaultValue: 0 },
                { id: 'max', name: 'Max', direction: 'input', type: 'float', defaultValue: 1 },
                { id: 'result', name: 'Result', direction: 'output', type: 'float' },
            ],
            execute: (inputs) => ({
                result: inputs.min +
                    Math.random() * (inputs.max - inputs.min),
            }),
        },
        // ─── Logic Operations ──────────────────────────
        {
            type: 'logic_and',
            name: 'AND',
            category: 'logic',
            description: 'Logical AND',
            icon: 'check-square',
            color: '#ef4444',
            pure: true,
            compact: true,
            ports: [
                { id: 'a', name: 'A', direction: 'input', type: 'bool', defaultValue: false },
                { id: 'b', name: 'B', direction: 'input', type: 'bool', defaultValue: false },
                { id: 'result', name: 'Result', direction: 'output', type: 'bool' },
            ],
            execute: (inputs) => ({ result: inputs.a && inputs.b }),
        },
        {
            type: 'logic_or',
            name: 'OR',
            category: 'logic',
            description: 'Logical OR',
            icon: 'box',
            color: '#ef4444',
            pure: true,
            compact: true,
            ports: [
                { id: 'a', name: 'A', direction: 'input', type: 'bool', defaultValue: false },
                { id: 'b', name: 'B', direction: 'input', type: 'bool', defaultValue: false },
                { id: 'result', name: 'Result', direction: 'output', type: 'bool' },
            ],
            execute: (inputs) => ({ result: inputs.a || inputs.b }),
        },
        {
            type: 'logic_not',
            name: 'NOT',
            category: 'logic',
            description: 'Logical NOT',
            icon: 'x-circle',
            color: '#ef4444',
            pure: true,
            compact: true,
            ports: [
                { id: 'value', name: 'Value', direction: 'input', type: 'bool', defaultValue: false },
                { id: 'result', name: 'Result', direction: 'output', type: 'bool' },
            ],
            execute: (inputs) => ({ result: !inputs.value }),
        },
        {
            type: 'compare_equal',
            name: 'Equal',
            category: 'logic',
            description: 'Check if two values are equal',
            icon: 'equal',
            color: '#ef4444',
            pure: true,
            compact: true,
            ports: [
                { id: 'a', name: 'A', direction: 'input', type: 'wildcard' },
                { id: 'b', name: 'B', direction: 'input', type: 'wildcard' },
                { id: 'result', name: 'Result', direction: 'output', type: 'bool' },
            ],
            execute: (inputs) => ({ result: inputs.a === inputs.b }),
        },
        {
            type: 'compare_greater',
            name: 'Greater Than',
            category: 'logic',
            description: 'Check if A > B',
            icon: 'chevron-right',
            color: '#ef4444',
            pure: true,
            compact: true,
            ports: [
                { id: 'a', name: 'A', direction: 'input', type: 'float', defaultValue: 0 },
                { id: 'b', name: 'B', direction: 'input', type: 'float', defaultValue: 0 },
                { id: 'result', name: 'Result', direction: 'output', type: 'bool' },
            ],
            execute: (inputs) => ({ result: inputs.a > inputs.b }),
        },
        {
            type: 'compare_less',
            name: 'Less Than',
            category: 'logic',
            description: 'Check if A < B',
            icon: 'chevron-left',
            color: '#ef4444',
            pure: true,
            compact: true,
            ports: [
                { id: 'a', name: 'A', direction: 'input', type: 'float', defaultValue: 0 },
                { id: 'b', name: 'B', direction: 'input', type: 'float', defaultValue: 0 },
                { id: 'result', name: 'Result', direction: 'output', type: 'bool' },
            ],
            execute: (inputs) => ({ result: inputs.a < inputs.b }),
        },
        // ─── Entity Operations ─────────────────────────
        {
            type: 'get_self',
            name: 'Get Self',
            category: 'entity',
            description: 'Get reference to the owning entity',
            icon: 'user',
            color: '#3b82f6',
            pure: true,
            ports: [{ id: 'entity', name: 'Entity', direction: 'output', type: 'entity' }],
            execute: (_inputs, ctx) => ({ entity: ctx.entityId }),
        },
        {
            type: 'spawn_entity',
            name: 'Spawn Entity',
            category: 'entity',
            description: 'Spawn a new entity from prefab',
            icon: 'plus-circle',
            color: '#3b82f6',
            ports: [
                { id: 'exec', name: '', direction: 'input', type: 'flow' },
                { id: 'prefab', name: 'Prefab', direction: 'input', type: 'asset' },
                {
                    id: 'position',
                    name: 'Position',
                    direction: 'input',
                    type: 'vec2',
                    defaultValue: { x: 0, y: 0 },
                },
                { id: 'then', name: '', direction: 'output', type: 'flow' },
                { id: 'spawned', name: 'Spawned', direction: 'output', type: 'entity' },
            ],
            execute: (inputs, ctx) => {
                const entity = ctx.spawnEntity(inputs.prefab, inputs.position);
                ctx.triggerFlow('then');
                return { spawned: entity };
            },
        },
        {
            type: 'destroy_entity',
            name: 'Destroy Entity',
            category: 'entity',
            description: 'Destroy an entity',
            icon: 'trash',
            color: '#3b82f6',
            ports: [
                { id: 'exec', name: '', direction: 'input', type: 'flow' },
                { id: 'entity', name: 'Entity', direction: 'input', type: 'entity' },
                { id: 'then', name: '', direction: 'output', type: 'flow' },
            ],
            execute: (inputs, ctx) => {
                ctx.destroyEntity(inputs.entity);
                ctx.triggerFlow('then');
            },
        },
        // ─── Transform Operations ──────────────────────
        {
            type: 'get_position',
            name: 'Get Position',
            category: 'transform',
            description: 'Get entity position',
            icon: 'map-pin',
            color: '#fbbf24',
            pure: true,
            ports: [
                { id: 'entity', name: 'Entity', direction: 'input', type: 'entity' },
                { id: 'position', name: 'Position', direction: 'output', type: 'vec2' },
            ],
            execute: (inputs, ctx) => {
                const transform = ctx.getComponent(inputs.entity, 'Transform');
                return { position: (transform === null || transform === void 0 ? void 0 : transform.position) || { x: 0, y: 0 } };
            },
        },
        {
            type: 'set_position',
            name: 'Set Position',
            category: 'transform',
            description: 'Set entity position',
            icon: 'move',
            color: '#fbbf24',
            ports: [
                { id: 'exec', name: '', direction: 'input', type: 'flow' },
                { id: 'entity', name: 'Entity', direction: 'input', type: 'entity' },
                {
                    id: 'position',
                    name: 'Position',
                    direction: 'input',
                    type: 'vec2',
                    defaultValue: { x: 0, y: 0 },
                },
                { id: 'then', name: '', direction: 'output', type: 'flow' },
            ],
            execute: (inputs, ctx) => {
                ctx.setComponent(inputs.entity, 'Transform', { position: inputs.position });
                ctx.triggerFlow('then');
            },
        },
        {
            type: 'translate',
            name: 'Translate',
            category: 'transform',
            description: 'Move entity by offset',
            icon: 'arrows-move',
            color: '#fbbf24',
            ports: [
                { id: 'exec', name: '', direction: 'input', type: 'flow' },
                { id: 'entity', name: 'Entity', direction: 'input', type: 'entity' },
                {
                    id: 'offset',
                    name: 'Offset',
                    direction: 'input',
                    type: 'vec2',
                    defaultValue: { x: 0, y: 0 },
                },
                { id: 'then', name: '', direction: 'output', type: 'flow' },
            ],
            execute: (inputs, ctx) => {
                const transform = ctx.getComponent(inputs.entity, 'Transform');
                if (transform) {
                    const offset = inputs.offset;
                    ctx.setComponent(inputs.entity, 'Transform', {
                        position: {
                            x: transform.position.x + offset.x,
                            y: transform.position.y + offset.y,
                        },
                    });
                }
                ctx.triggerFlow('then');
            },
        },
        // ─── Debug Operations ──────────────────────────
        {
            type: 'print',
            name: 'Print',
            category: 'debug',
            description: 'Print message to screen',
            icon: 'message-square',
            color: '#6b7280',
            ports: [
                { id: 'exec', name: '', direction: 'input', type: 'flow' },
                {
                    id: 'message',
                    name: 'Message',
                    direction: 'input',
                    type: 'string',
                    defaultValue: 'Hello!',
                },
                { id: 'duration', name: 'Duration', direction: 'input', type: 'float', defaultValue: 2 },
                { id: 'color', name: 'Color', direction: 'input', type: 'color', defaultValue: '#ffffff' },
                { id: 'then', name: '', direction: 'output', type: 'flow' },
            ],
            execute: (inputs, ctx) => {
                ctx.print(inputs.message, inputs.duration, inputs.color);
                ctx.triggerFlow('then');
            },
        },
        {
            type: 'log',
            name: 'Log',
            category: 'debug',
            description: 'Log message to console',
            icon: 'terminal',
            color: '#6b7280',
            ports: [
                { id: 'exec', name: '', direction: 'input', type: 'flow' },
                { id: 'message', name: 'Message', direction: 'input', type: 'string' },
                {
                    id: 'level',
                    name: 'Level',
                    direction: 'input',
                    type: 'enum',
                    enumDef: 'LogLevel',
                    defaultValue: 'info',
                },
                { id: 'then', name: '', direction: 'output', type: 'flow' },
            ],
            execute: (inputs, ctx) => {
                ctx.log(inputs.level, inputs.message);
                ctx.triggerFlow('then');
            },
        },
        // ─── Variable Operations ───────────────────────
        {
            type: 'get_variable',
            name: 'Get Variable',
            category: 'variable',
            description: 'Get variable value',
            icon: 'download',
            color: '#8b5cf6',
            pure: true,
            ports: [
                { id: 'name', name: 'Name', direction: 'input', type: 'string' },
                { id: 'value', name: 'Value', direction: 'output', type: 'wildcard' },
            ],
            execute: (inputs, ctx) => ({ value: ctx.variables.get(inputs.name) }),
        },
        {
            type: 'set_variable',
            name: 'Set Variable',
            category: 'variable',
            description: 'Set variable value',
            icon: 'upload',
            color: '#8b5cf6',
            ports: [
                { id: 'exec', name: '', direction: 'input', type: 'flow' },
                { id: 'name', name: 'Name', direction: 'input', type: 'string' },
                { id: 'value', name: 'Value', direction: 'input', type: 'wildcard' },
                { id: 'then', name: '', direction: 'output', type: 'flow' },
            ],
            execute: (inputs, ctx) => {
                ctx.variables.set(inputs.name, inputs.value);
                ctx.triggerFlow('then');
            },
        },
    ];
}
// ============================================================
// Factory Functions
// ============================================================
function createVSGraph(name) {
    return {
        id: `graph_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        name,
        nodes: [],
        connections: [],
        variables: [],
        functions: [],
        macros: [],
        parameters: [],
        graphType: 'blueprint',
    };
}
function createVSNode(type, position) {
    return {
        id: `node_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        type,
        position,
        inputs: {},
        outputs: {},
    };
}
function createVSConnection(fromNode, fromPort, toNode, toPort) {
    return {
        id: `conn_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        fromNode,
        fromPort,
        toNode,
        toPort,
    };
}
function createVSDebugger() {
    return new VSDebugger();
}
function createVSExecutor(debuggerInstance) {
    const executor = new VSGraphExecutor(debuggerInstance);
    executor.registerNodes(createBuiltInNodes());
    return executor;
}

export { VSDebugger, VSGraphExecutor, VS_TYPE_COLORS, createBuiltInNodes, createVSConnection, createVSDebugger, createVSExecutor, createVSGraph, createVSNode };
//# sourceMappingURL=VisualScripting2.js.map
