"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WorkflowBuilder = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const useWorkflowEngine_js_1 = require("./hooks/useWorkflowEngine.js");
const useCanvasDragDrop_js_1 = require("./hooks/useCanvasDragDrop.js");
const useNodePositioning_js_1 = require("./hooks/useNodePositioning.js");
const useWorkflowExecution_js_1 = require("./hooks/useWorkflowExecution.js");
const NodePalette_js_1 = require("./components/NodePalette.js");
const CanvasGrid_js_1 = require("./components/CanvasGrid.js");
const WorkflowNode_js_1 = require("./components/WorkflowNode.js");
const WorkflowEdge_js_1 = require("./components/WorkflowEdge.js");
const PropertyPanel_js_1 = require("./components/PropertyPanel.js");
const ExecutionPanel_js_1 = require("./components/ExecutionPanel.js");
const MiniMap_js_1 = require("./components/MiniMap.js");
const Toolbar_js_1 = require("./components/Toolbar.js");
const ContextMenu_js_1 = require("./components/ContextMenu.js");
/**
 * WorkflowBuilder - Advanced Visual Programming Interface
 *
 * A comprehensive drag-and-drop workflow builder with:
 * - Visual node-based programming
 * - Real-time execution and debugging
 * - AI-powered node suggestions
 * - Template library and sharing
 * - Version control and collaboration
 * - Performance monitoring
 * - Export to multiple formats
 */
const WorkflowBuilder = ({ initialWorkflow, onWorkflowChange, onExecute, onSave, mode = 'design', enableAISuggestions = true, enableCollaboration = false, enableVersionControl = false, enableTesting = true, enableExport = true, className = '', height = 600, readonly = false }) => {
    // State management
    const [workflow, setWorkflow] = (0, react_1.useState)(initialWorkflow || { nodes: [], edges: [] });
    const [selectedNodes, setSelectedNodes] = (0, react_1.useState)([]);
    const [selectedEdges, setSelectedEdges] = (0, react_1.useState)([]);
    const [dragState, setDragState] = (0, react_1.useState)(null);
    const [canvasOffset, setCanvasOffset] = (0, react_1.useState)({ x: 0, y: 0 });
    const [zoomLevel, setZoomLevel] = (0, react_1.useState)(1);
    const [showPropertyPanel, setShowPropertyPanel] = (0, react_1.useState)(true);
    const [showMiniMap, setShowMiniMap] = (0, react_1.useState)(true);
    const [contextMenu, setContextMenu] = (0, react_1.useState)(null);
    // Refs
    const canvasRef = (0, react_1.useRef)(null);
    const svgRef = (0, react_1.useRef)(null);
    // Custom hooks
    const { addNode, updateNode, deleteNode, addEdge, deleteEdge, validateWorkflow, optimizeWorkflow, suggestNextNodes } = (0, useWorkflowEngine_js_1.useWorkflowEngine)(workflow, setWorkflow);
    const { isDragging, draggedNode, handleMouseDown, handleMouseMove, handleMouseUp, getDropPosition } = (0, useCanvasDragDrop_js_1.useCanvasDragDrop)(canvasRef, canvasOffset, zoomLevel);
    const { autoLayout, snapToGrid, alignNodes, distributeNodes } = (0, useNodePositioning_js_1.useNodePositioning)();
    const { isExecuting, executionResults, currentStep, executeWorkflow, stepThrough, pauseExecution, stopExecution } = (0, useWorkflowExecution_js_1.useWorkflowExecution)();
    // Event handlers
    const handleCanvasClick = (0, react_1.useCallback)((event) => {
        if (readonly)
            return;
        const rect = canvasRef.current?.getBoundingClientRect();
        if (!rect)
            return;
        const x = (event.clientX - rect.left - canvasOffset.x) / zoomLevel;
        const y = (event.clientY - rect.top - canvasOffset.y) / zoomLevel;
        // Clear selections if clicking on empty canvas
        if (event.target === canvasRef.current) {
            setSelectedNodes([]);
            setSelectedEdges([]);
            setContextMenu(null);
        }
    }, [readonly, canvasOffset, zoomLevel]);
    const handleCanvasRightClick = (0, react_1.useCallback)((event) => {
        if (readonly)
            return;
        event.preventDefault();
        const rect = canvasRef.current?.getBoundingClientRect();
        if (!rect)
            return;
        setContextMenu({
            x: event.clientX,
            y: event.clientY
        });
    }, [readonly]);
    const handleNodeDrop = (0, react_1.useCallback)((nodeType, position) => {
        if (readonly)
            return;
        const newNode = {
            id: `node_${Date.now()}`,
            type: nodeType,
            position,
            data: getDefaultNodeData(nodeType),
            selected: false
        };
        addNode(newNode);
        // AI-powered suggestions for next nodes
        if (enableAISuggestions) {
            const suggestions = suggestNextNodes(newNode);
            // Show suggestions in UI
        }
    }, [readonly, addNode, enableAISuggestions, suggestNextNodes]);
    const handleNodeSelect = (0, react_1.useCallback)((nodeId, multiSelect = false) => {
        if (readonly)
            return;
        setSelectedNodes(prev => {
            if (multiSelect) {
                return prev.includes(nodeId)
                    ? prev.filter(id => id !== nodeId)
                    : [...prev, nodeId];
            }
            else {
                return [nodeId];
            }
        });
        // Update node selection state
        setWorkflow(prev => ({
            ...prev,
            nodes: prev.nodes.map(node => ({
                ...node,
                selected: multiSelect
                    ? selectedNodes.includes(node.id) ? !node.selected : node.id === nodeId
                    : node.id === nodeId
            }))
        }));
    }, [readonly, selectedNodes]);
    const handleNodeDelete = (0, react_1.useCallback)((nodeId) => {
        if (readonly)
            return;
        deleteNode(nodeId);
        setSelectedNodes(prev => prev.filter(id => id !== nodeId));
    }, [readonly, deleteNode]);
    const handleEdgeCreate = (0, react_1.useCallback)((sourceId, targetId) => {
        if (readonly)
            return;
        const newEdge = {
            id: `edge_${Date.now()}`,
            source: sourceId,
            target: targetId,
            type: 'default'
        };
        addEdge(newEdge);
    }, [readonly, addEdge]);
    const handleZoom = (0, react_1.useCallback)((delta, point) => {
        setZoomLevel(prev => {
            const newZoom = Math.max(0.1, Math.min(2, prev + delta));
            if (point) {
                // Zoom towards the point
                const factor = newZoom / prev;
                setCanvasOffset(prevOffset => ({
                    x: point.x - (point.x - prevOffset.x) * factor,
                    y: point.y - (point.y - prevOffset.y) * factor
                }));
            }
            return newZoom;
        });
    }, []);
    const handlePan = (0, react_1.useCallback)((deltaX, deltaY) => {
        setCanvasOffset(prev => ({
            x: prev.x + deltaX,
            y: prev.y + deltaY
        }));
    }, []);
    // Keyboard shortcuts
    (0, react_1.useEffect)(() => {
        const handleKeyDown = (event) => {
            if (readonly)
                return;
            switch (event.key) {
                case 'Delete':
                case 'Backspace':
                    selectedNodes.forEach(nodeId => handleNodeDelete(nodeId));
                    break;
                case 'a':
                    if (event.ctrlKey || event.metaKey) {
                        event.preventDefault();
                        setSelectedNodes(workflow.nodes.map(node => node.id));
                    }
                    break;
                case 'z':
                    if (event.ctrlKey || event.metaKey) {
                        event.preventDefault();
                        // Implement undo functionality
                    }
                    break;
                case 'c':
                    if (event.ctrlKey || event.metaKey) {
                        event.preventDefault();
                        // Implement copy functionality
                    }
                    break;
                case 'v':
                    if (event.ctrlKey || event.metaKey) {
                        event.preventDefault();
                        // Implement paste functionality
                    }
                    break;
                case 'Escape':
                    setSelectedNodes([]);
                    setSelectedEdges([]);
                    setContextMenu(null);
                    break;
            }
        };
        window.addEventListener('keydown', handleKeyDown);
        return () => window.removeEventListener('keydown', handleKeyDown);
    }, [readonly, selectedNodes, workflow.nodes, handleNodeDelete]);
    // Auto-save functionality
    (0, react_1.useEffect)(() => {
        const autoSaveTimer = setTimeout(() => {
            onWorkflowChange?.(workflow);
        }, 1000);
        return () => clearTimeout(autoSaveTimer);
    }, [workflow, onWorkflowChange]);
    // Computed values
    const selectedNode = (0, react_1.useMemo)(() => {
        if (selectedNodes.length === 1) {
            return workflow.nodes.find(node => node.id === selectedNodes[0]);
        }
        return null;
    }, [selectedNodes, workflow.nodes]);
    const validationErrors = (0, react_1.useMemo)(() => {
        return validateWorkflow(workflow);
    }, [workflow, validateWorkflow]);
    // Render functions
    const renderNodes = () => {
        return workflow.nodes.map(node => ((0, jsx_runtime_1.jsx)(WorkflowNode_js_1.WorkflowNode, { node: node, selected: selectedNodes.includes(node.id), onSelect: handleNodeSelect, onDelete: handleNodeDelete, onUpdate: (updates) => updateNode(node.id, updates), onConnectStart: (outputId) => {
                // Start edge creation
            }, onConnectEnd: (inputId) => {
                // Complete edge creation
            }, readonly: readonly, zoomLevel: zoomLevel, isExecuting: isExecuting && currentStep?.nodeId === node.id, executionResult: executionResults[node.id] }, node.id)));
    };
    const renderEdges = () => {
        return workflow.edges.map(edge => {
            const sourceNode = workflow.nodes.find(n => n.id === edge.source);
            const targetNode = workflow.nodes.find(n => n.id === edge.target);
            if (!sourceNode || !targetNode)
                return null;
            return ((0, jsx_runtime_1.jsx)(WorkflowEdge_js_1.WorkflowEdge, { edge: edge, sourcePosition: sourceNode.position, targetPosition: targetNode.position, selected: selectedEdges.includes(edge.id), onSelect: () => setSelectedEdges([edge.id]), onDelete: () => deleteEdge(edge.id), readonly: readonly, isActive: isExecuting && currentStep?.edgeId === edge.id }, edge.id));
        });
    };
    return ((0, jsx_runtime_1.jsxs)("div", { className: `workflow-builder ${className}`, style: { height }, children: [(0, jsx_runtime_1.jsx)(Toolbar_js_1.Toolbar, { onSave: () => onSave?.(workflow), onExecute: () => executeWorkflow(workflow), onStop: stopExecution, onPause: pauseExecution, onZoomIn: () => handleZoom(0.1), onZoomOut: () => handleZoom(-0.1), onZoomFit: () => {
                    // Implement zoom to fit
                }, onAutoLayout: () => autoLayout(workflow.nodes), onExport: () => {
                    // Implement export functionality
                }, isExecuting: isExecuting, canExecute: validationErrors.length === 0, readonly: readonly, enableTesting: enableTesting, enableExport: enableExport }), (0, jsx_runtime_1.jsxs)("div", { className: "workflow-builder-content flex", children: [(0, jsx_runtime_1.jsx)(NodePalette_js_1.NodePalette, { onNodeDrag: handleNodeDrop, enableAISuggestions: enableAISuggestions, suggestedNodes: selectedNode ? suggestNextNodes(selectedNode) : [], readonly: readonly }), (0, jsx_runtime_1.jsxs)("div", { className: "workflow-canvas-container flex-1 relative", children: [(0, jsx_runtime_1.jsxs)("div", { ref: canvasRef, className: "workflow-canvas", onClick: handleCanvasClick, onContextMenu: handleCanvasRightClick, onMouseDown: handleMouseDown, onMouseMove: handleMouseMove, onMouseUp: handleMouseUp, onWheel: (e) => {
                                    e.preventDefault();
                                    const delta = e.deltaY > 0 ? -0.1 : 0.1;
                                    handleZoom(delta, { x: e.clientX, y: e.clientY });
                                }, style: {
                                    transform: `translate(${canvasOffset.x}px, ${canvasOffset.y}px) scale(${zoomLevel})`,
                                    transformOrigin: '0 0',
                                    cursor: isDragging ? 'grabbing' : 'grab'
                                }, children: [(0, jsx_runtime_1.jsx)(CanvasGrid_js_1.CanvasGrid, { offset: canvasOffset, zoom: zoomLevel, gridSize: 20 }), (0, jsx_runtime_1.jsx)("svg", { ref: svgRef, className: "workflow-edges", style: {
                                            position: 'absolute',
                                            top: 0,
                                            left: 0,
                                            width: '100%',
                                            height: '100%',
                                            pointerEvents: 'none'
                                        }, children: renderEdges() }), (0, jsx_runtime_1.jsx)("div", { className: "workflow-nodes", children: renderNodes() }), draggedNode && ((0, jsx_runtime_1.jsx)("div", { className: "drag-preview", style: {
                                            position: 'absolute',
                                            left: draggedNode.position.x,
                                            top: draggedNode.position.y,
                                            pointerEvents: 'none',
                                            opacity: 0.7
                                        }, children: (0, jsx_runtime_1.jsx)(WorkflowNode_js_1.WorkflowNode, { node: draggedNode, selected: false, readonly: true, zoomLevel: zoomLevel }) }))] }), showMiniMap && ((0, jsx_runtime_1.jsx)(MiniMap_js_1.MiniMap, { nodes: workflow.nodes, edges: workflow.edges, canvasOffset: canvasOffset, zoomLevel: zoomLevel, onNavigate: (offset) => setCanvasOffset(offset), className: "absolute bottom-4 right-4" })), mode === 'execute' && ((0, jsx_runtime_1.jsx)(ExecutionPanel_js_1.ExecutionPanel, { isExecuting: isExecuting, currentStep: currentStep, executionResults: executionResults, onStepThrough: stepThrough, onPause: pauseExecution, onStop: stopExecution, className: "absolute top-4 right-4" }))] }), showPropertyPanel && ((0, jsx_runtime_1.jsx)(PropertyPanel_js_1.PropertyPanel, { selectedNode: selectedNode, onNodeUpdate: (updates) => {
                            if (selectedNode) {
                                updateNode(selectedNode.id, updates);
                            }
                        }, validationErrors: validationErrors.filter(error => selectedNode && error.nodeId === selectedNode.id), readonly: readonly }))] }), contextMenu && ((0, jsx_runtime_1.jsx)(ContextMenu_js_1.ContextMenu, { x: contextMenu.x, y: contextMenu.y, onClose: () => setContextMenu(null), onAddNode: (nodeType) => {
                    const rect = canvasRef.current?.getBoundingClientRect();
                    if (rect) {
                        const position = {
                            x: (contextMenu.x - rect.left - canvasOffset.x) / zoomLevel,
                            y: (contextMenu.y - rect.top - canvasOffset.y) / zoomLevel
                        };
                        handleNodeDrop(nodeType, position);
                    }
                    setContextMenu(null);
                }, onPaste: () => {
                    // Implement paste functionality
                    setContextMenu(null);
                }, readonly: readonly })), validationErrors.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "validation-errors absolute bottom-4 left-4 bg-red-100 border border-red-400 rounded p-3", children: [(0, jsx_runtime_1.jsx)("h4", { className: "font-medium text-red-800 mb-2", children: "Workflow Validation Errors:" }), (0, jsx_runtime_1.jsx)("ul", { className: "text-sm text-red-700", children: validationErrors.map((error, index) => ((0, jsx_runtime_1.jsxs)("li", { children: ["\u2022 ", error.message] }, index))) })] }))] }));
};
exports.WorkflowBuilder = WorkflowBuilder;
// Helper function to get default node data
function getDefaultNodeData(nodeType) {
    switch (nodeType) {
        case 'trigger':
            return {
                triggerType: 'manual',
                schedule: null
            };
        case 'action':
            return {
                actionType: 'http_request',
                method: 'GET',
                url: '',
                headers: {},
                body: ''
            };
        case 'condition':
            return {
                operator: 'equals',
                leftValue: '',
                rightValue: '',
                trueOutput: null,
                falseOutput: null
            };
        case 'ai_processor':
            return {
                model: 'gpt-4',
                prompt: '',
                temperature: 0.7,
                maxTokens: 1000
            };
        case 'data_transformer':
            return {
                transformType: 'map',
                mapping: {},
                script: ''
            };
        case 'output':
            return {
                outputType: 'response',
                format: 'json',
                template: ''
            };
        default:
            return {};
    }
}
//# sourceMappingURL=WorkflowBuilder.js.map