import { Component, ViewChild, Output, EventEmitter } from '@angular/core';
import { CommonModule } from '@angular/common';
import { StepComponent } from '../step/step.component';
import { SimpleConditionEditorComponent } from '../simple-condition-editor/simple-condition-editor.component';
import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component';
import { STEP_CONFIGS } from '../../models/step.model';
import * as i0 from "@angular/core";
import * as i1 from "../../services/flow-editor.service";
import * as i2 from "../../services/flow-executor.service";
import * as i3 from "@angular/common";
const _c0 = ["reteEditor"];
function FlowEditorComponent_div_7_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 29)(1, "div", 30);
    i0.ɵɵnamespaceSVG();
    i0.ɵɵelementStart(2, "svg", 31);
    i0.ɵɵelement(3, "line", 32);
    i0.ɵɵelementEnd();
    i0.ɵɵnamespaceHTML();
    i0.ɵɵelementStart(4, "span");
    i0.ɵɵtext(5, "First output from a step");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(6, "div", 30);
    i0.ɵɵnamespaceSVG();
    i0.ɵɵelementStart(7, "svg", 31);
    i0.ɵɵelement(8, "line", 33);
    i0.ɵɵelementEnd();
    i0.ɵɵnamespaceHTML();
    i0.ɵɵelementStart(9, "span");
    i0.ɵɵtext(10, "Second output from a step");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(11, "div", 30);
    i0.ɵɵnamespaceSVG();
    i0.ɵɵelementStart(12, "svg", 31);
    i0.ɵɵelement(13, "line", 34);
    i0.ɵɵelementEnd();
    i0.ɵɵnamespaceHTML();
    i0.ɵɵelementStart(14, "span");
    i0.ɵɵtext(15, "Third output from a step");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(16, "div", 30);
    i0.ɵɵnamespaceSVG();
    i0.ɵɵelementStart(17, "svg", 31);
    i0.ɵɵelement(18, "line", 35);
    i0.ɵɵelementEnd();
    i0.ɵɵnamespaceHTML();
    i0.ɵɵelementStart(19, "span");
    i0.ɵɵtext(20, "Backward connection (loop)");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(21, "div", 36);
    i0.ɵɵtext(22, " Colors help distinguish multiple paths from the same source step ");
    i0.ɵɵelementEnd()();
} }
function FlowEditorComponent__svg_g_36__svg_g_3_Template(rf, ctx) { if (rf & 1) {
    const _r5 = i0.ɵɵgetCurrentView();
    i0.ɵɵnamespaceSVG();
    i0.ɵɵelementStart(0, "g");
    i0.ɵɵelement(1, "rect", 40);
    i0.ɵɵelementStart(2, "rect", 41);
    i0.ɵɵlistener("click", function FlowEditorComponent__svg_g_36__svg_g_3_Template_rect_click_2_listener($event) { i0.ɵɵrestoreView(_r5); const connection_r3 = i0.ɵɵnextContext().$implicit; const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onConnectionClick($event, connection_r3)); });
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(3, "text", 42);
    i0.ɵɵtext(4);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const connection_r3 = i0.ɵɵnextContext().$implicit;
    const ctx_r3 = i0.ɵɵnextContext();
    i0.ɵɵadvance();
    i0.ɵɵattribute("x", ctx_r3.getConnectionMidpoint(connection_r3).x - ctx_r3.getConditionBoxWidth(connection_r3) / 2)("y", ctx_r3.getConnectionMidpoint(connection_r3).y - 15)("width", ctx_r3.getConditionBoxWidth(connection_r3))("transform", "translate(2, 2)");
    i0.ɵɵadvance();
    i0.ɵɵattribute("x", ctx_r3.getConnectionMidpoint(connection_r3).x - ctx_r3.getConditionBoxWidth(connection_r3) / 2)("y", ctx_r3.getConnectionMidpoint(connection_r3).y - 15)("width", ctx_r3.getConditionBoxWidth(connection_r3));
    i0.ɵɵadvance();
    i0.ɵɵattribute("x", ctx_r3.getConnectionMidpoint(connection_r3).x)("y", ctx_r3.getConnectionMidpoint(connection_r3).y + 4);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate1(" ", ctx_r3.getConditionLabel(connection_r3), " ");
} }
function FlowEditorComponent__svg_g_36_Template(rf, ctx) { if (rf & 1) {
    const _r2 = i0.ɵɵgetCurrentView();
    i0.ɵɵnamespaceSVG();
    i0.ɵɵelementStart(0, "g")(1, "path", 37);
    i0.ɵɵlistener("click", function FlowEditorComponent__svg_g_36_Template_path_click_1_listener($event) { const connection_r3 = i0.ɵɵrestoreView(_r2).$implicit; const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onConnectionClick($event, connection_r3)); });
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(2, "path", 38);
    i0.ɵɵlistener("click", function FlowEditorComponent__svg_g_36_Template_path_click_2_listener($event) { const connection_r3 = i0.ɵɵrestoreView(_r2).$implicit; const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onConnectionClick($event, connection_r3)); });
    i0.ɵɵelementEnd();
    i0.ɵɵtemplate(3, FlowEditorComponent__svg_g_36__svg_g_3_Template, 5, 10, "g", 39);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const connection_r3 = ctx.$implicit;
    const ctx_r3 = i0.ɵɵnextContext();
    i0.ɵɵadvance();
    i0.ɵɵattribute("d", ctx_r3.getConnectionPath(connection_r3))("stroke", ctx_r3.getConnectionColor(connection_r3))("stroke-dasharray", ctx_r3.getConnectionDashArray(connection_r3))("marker-end", ctx_r3.getConnectionMarker(connection_r3));
    i0.ɵɵadvance();
    i0.ɵɵattribute("d", ctx_r3.getConnectionPath(connection_r3));
    i0.ɵɵadvance();
    i0.ɵɵproperty("ngIf", connection_r3.condition);
} }
function FlowEditorComponent__svg_path_37_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵnamespaceSVG();
    i0.ɵɵelement(0, "path", 43);
} if (rf & 2) {
    const ctx_r3 = i0.ɵɵnextContext();
    i0.ɵɵattribute("d", ctx_r3.getTempConnectionPath());
} }
function FlowEditorComponent_app_step_39_Template(rf, ctx) { if (rf & 1) {
    const _r6 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "app-step", 44);
    i0.ɵɵlistener("stepSelected", function FlowEditorComponent_app_step_39_Template_app_step_stepSelected_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.selectStep($event)); })("stepDeleted", function FlowEditorComponent_app_step_39_Template_app_step_stepDeleted_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.deleteStep($event)); })("stepUpdated", function FlowEditorComponent_app_step_39_Template_app_step_stepUpdated_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.updateStep($event)); })("socketMouseDown", function FlowEditorComponent_app_step_39_Template_app_step_socketMouseDown_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onSocketMouseDown($event)); })("socketMouseEnter", function FlowEditorComponent_app_step_39_Template_app_step_socketMouseEnter_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onSocketMouseEnter($event)); })("socketMouseLeave", function FlowEditorComponent_app_step_39_Template_app_step_socketMouseLeave_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onSocketMouseLeave($event)); })("mousedown", function FlowEditorComponent_app_step_39_Template_app_step_mousedown_0_listener($event) { const step_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onStepDragStart($event, step_r7)); });
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const step_r7 = ctx.$implicit;
    const ctx_r3 = i0.ɵɵnextContext();
    i0.ɵɵstyleProp("left", step_r7.position[0], "px")("top", step_r7.position[1], "px")("position", "absolute");
    i0.ɵɵproperty("step", step_r7)("selected", ctx_r3.selectedStepId === step_r7.id)("executing", ctx_r3.executingStepId === step_r7.id);
    i0.ɵɵattribute("data-step-id", step_r7.id);
} }
function FlowEditorComponent_div_40_Template(rf, ctx) { if (rf & 1) {
    const _r8 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 45);
    i0.ɵɵlistener("click", function FlowEditorComponent_div_40_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.closeConditionEditor()); });
    i0.ɵɵelementStart(1, "div", 46);
    i0.ɵɵlistener("click", function FlowEditorComponent_div_40_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r8); return i0.ɵɵresetView($event.stopPropagation()); });
    i0.ɵɵelementStart(2, "app-simple-condition-editor", 47);
    i0.ɵɵlistener("save", function FlowEditorComponent_div_40_Template_app_simple_condition_editor_save_2_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.saveConnectionConditions($event)); })("cancel", function FlowEditorComponent_div_40_Template_app_simple_condition_editor_cancel_2_listener() { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.closeConditionEditor()); });
    i0.ɵɵelementEnd()()();
} if (rf & 2) {
    const ctx_r3 = i0.ɵɵnextContext();
    i0.ɵɵadvance(2);
    i0.ɵɵproperty("connection", ctx_r3.editingConnection);
} }
function FlowEditorComponent_app_confirmation_dialog_41_Template(rf, ctx) { if (rf & 1) {
    const _r9 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "app-confirmation-dialog", 48);
    i0.ɵɵlistener("confirm", function FlowEditorComponent_app_confirmation_dialog_41_Template_app_confirmation_dialog_confirm_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.confirmDeleteStep()); })("cancel", function FlowEditorComponent_app_confirmation_dialog_41_Template_app_confirmation_dialog_cancel_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.cancelDeleteStep()); });
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const ctx_r3 = i0.ɵɵnextContext();
    i0.ɵɵproperty("title", "Delete Step")("message", "Are you sure you want to delete this " + ctx_r3.stepToDelete.config.name + " step? This action cannot be undone.")("confirmText", "Delete");
} }
function FlowEditorComponent_app_confirmation_dialog_42_Template(rf, ctx) { if (rf & 1) {
    const _r10 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "app-confirmation-dialog", 48);
    i0.ɵɵlistener("confirm", function FlowEditorComponent_app_confirmation_dialog_42_Template_app_confirmation_dialog_confirm_0_listener() { i0.ɵɵrestoreView(_r10); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.confirmDeleteConnection()); })("cancel", function FlowEditorComponent_app_confirmation_dialog_42_Template_app_confirmation_dialog_cancel_0_listener() { i0.ɵɵrestoreView(_r10); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.cancelDeleteConnection()); });
    i0.ɵɵelementEnd();
} if (rf & 2) {
    i0.ɵɵproperty("title", "Delete Connection")("message", "Are you sure you want to delete this connection? This action cannot be undone.")("confirmText", "Delete");
} }
export class FlowEditorComponent {
    constructor(flowEditorService, flowExecutor, changeDetector) {
        this.flowEditorService = flowEditorService;
        this.flowExecutor = flowExecutor;
        this.changeDetector = changeDetector;
        this.toggleExecution = new EventEmitter();
        this.stepMoved = new EventEmitter();
        this.steps = [];
        this.connections = [];
        this.selectedStepId = null;
        this.executingStepId = null;
        this.showExecutionPanel = false;
        this.legendCollapsed = true;
        // Fixed dimensions for all steps
        this.STEP_WIDTH = 320;
        this.STEP_HEIGHT = 140;
        this.nextStepId = 1;
        this.isDragging = false;
        this.dragOffset = { x: 0, y: 0 };
        this.currentScale = 1;
        this.canvasOffset = { x: 50, y: 50 };
        // Connection creation state
        this.tempConnection = null;
        this.isCreatingConnection = false;
        // Condition editing
        this.editingConnection = null;
        // Deletion confirmation
        this.stepToDelete = null;
        this.connectionToDelete = null;
        this.currentDraggedStep = null;
        this.handleMouseMove = (event) => {
            if (this.isDragging && this.currentDraggedStep) {
                const rect = this.reteEditor.nativeElement.getBoundingClientRect();
                const mouseX = (event.clientX - rect.left - this.canvasOffset.x) / this.currentScale;
                const mouseY = (event.clientY - rect.top - this.canvasOffset.y) / this.currentScale;
                // Update position by subtracting the initial offset
                this.currentDraggedStep.position[0] = mouseX - this.dragOffset.x;
                this.currentDraggedStep.position[1] = mouseY - this.dragOffset.y;
            }
        };
        this.handleMouseUp = () => {
            if (this.isDragging && this.currentDraggedStep) {
                // Emit an event that the step position has changed
                this.stepMoved.emit(this.currentDraggedStep);
            }
            this.isDragging = false;
            this.currentDraggedStep = null;
            document.removeEventListener('mousemove', this.handleMouseMove);
            document.removeEventListener('mouseup', this.handleMouseUp);
        };
        this.handleConnectionMouseMove = (event) => {
            if (this.isCreatingConnection && this.tempConnection) {
                const rect = this.reteEditor.nativeElement.getBoundingClientRect();
                this.tempConnection.mouseX = (event.clientX - rect.left - this.canvasOffset.x) / this.currentScale;
                this.tempConnection.mouseY = (event.clientY - rect.top - this.canvasOffset.y) / this.currentScale;
            }
        };
        this.handleConnectionMouseUp = (event) => {
            if (this.isCreatingConnection && this.tempConnection) {
                // Check if we're over a socket
                const target = event.target;
                if (target.classList.contains('socket') && target._connectionTarget) {
                    const connectionTarget = target._connectionTarget;
                    const sourceStep = this.tempConnection.source;
                    const targetStep = connectionTarget.step;
                    // Create the connection
                    if (this.tempConnection.sourceType === 'output') {
                        this.createConnection(sourceStep.id, targetStep.id);
                    }
                    else {
                        this.createConnection(targetStep.id, sourceStep.id);
                    }
                    // Force change detection to show the new connection
                    this.changeDetector.detectChanges();
                }
                // Clean up
                this.isCreatingConnection = false;
                this.tempConnection = null;
                document.removeEventListener('mousemove', this.handleConnectionMouseMove);
                document.removeEventListener('mouseup', this.handleConnectionMouseUp);
            }
        };
    }
    ngOnInit() {
        // Subscribe to current executing step to highlight it
        this.flowExecutor.currentStepId.subscribe(stepId => {
            this.executingStepId = stepId;
            this.changeDetector.detectChanges();
        });
    }
    ngAfterViewInit() {
        this.initializeEditor();
        // Load the actual data from the service instead of creating example flow
        this.loadFlowData();
    }
    initializeEditor() {
        // Setup canvas events
        this.setupCanvasEvents();
    }
    loadFlowData() {
        // Load steps and connections from the service
        this.steps = this.flowEditorService.getAllSteps();
        this.connections = this.flowEditorService.connections || [];
        // Log the loaded data
        if (this.steps.length > 0 || this.connections.length > 0) {
            // Auto-arrange steps with proper spacing
            this.autoArrangeSteps();
            // The template will automatically render the steps and connections
            // through Angular's change detection
            this.changeDetector.detectChanges();
            // Fit entire flow in view after DOM is ready
            // Need longer delay to ensure canvas element has dimensions
            setTimeout(() => {
                this.fitToView();
            }, 500);
        }
    }
    centerOnStartingStep() {
        // Find a starting step or the first step
        const startingStep = this.steps.find(s => s.mjData?.startingStep) || this.steps[0];
        if (startingStep) {
            // Center the canvas on this step
            const container = this.reteEditor.nativeElement;
            const rect = container.getBoundingClientRect();
            // Calculate offset to center the step
            this.canvasOffset.x = (rect.width / 2) - (startingStep.position[0] * this.currentScale) - 120; // 120 is half step width
            this.canvasOffset.y = (rect.height / 2) - (startingStep.position[1] * this.currentScale) - 60; // 60 is half step height
            // Ensure we don't go too far up
            this.canvasOffset.y = Math.min(this.canvasOffset.y, 50);
            this.updateCanvasTransform();
        }
    }
    createExampleFlow() {
        // Create example steps with more spacing
        this.createStep('prompt', [100, 200]);
        this.createStep('agent', [500, 200]);
        this.createStep('action', [900, 200]);
        this.createStep('prompt', [1300, 100]);
        this.createStep('action', [1300, 300]);
        // Create connections
        this.createConnection(1, 2);
        this.createConnection(2, 3);
        this.createConnection(3, 4);
        this.createConnection(3, 5);
    }
    createStep(type, position) {
        const config = STEP_CONFIGS[type];
        const step = {
            id: this.nextStepId++,
            type: type,
            name: config.name,
            position: position,
            config: config
        };
        this.steps.push(step);
        // console.log('Step created:', step);
        // console.log('Total steps:', this.steps.length);
        // console.log('Current steps array:', this.steps);
        // Update the service with all steps
        this.flowEditorService.setAllSteps(this.steps);
        // Force Angular change detection
        this.changeDetector.detectChanges();
        // Log the DOM elements after change detection
        setTimeout(() => {
            // Step elements have been created
        }, 0);
        return step;
    }
    createConnection(sourceId, targetId) {
        const connection = {
            id: `${sourceId}-${targetId}`,
            source: sourceId,
            target: targetId,
            sourceOutput: 'out',
            targetInput: 'in',
            condition: {
                expression: 'success',
                label: 'Success'
            }
        };
        this.connections.push(connection);
        // console.log('Connection created:', connection);
        // console.log('Total connections:', this.connections.length);
        this.changeDetector.detectChanges();
    }
    setupCanvasEvents() {
        const container = this.reteEditor.nativeElement;
        // Click on empty canvas to deselect
        container.addEventListener('click', (e) => {
            // Only deselect if clicking on the canvas itself or the SVG
            const target = e.target;
            if (target === container || target.tagName === 'svg' || target.classList.contains('canvas-wrapper')) {
                this.selectedStepId = null;
                this.flowEditorService.selectNode(null);
            }
        });
        // Setup drop handling on the container itself
        container.addEventListener('dragover', (e) => {
            e.preventDefault();
            e.dataTransfer.dropEffect = 'copy';
            container.classList.add('drag-over');
        });
        container.addEventListener('dragleave', (e) => {
            const rect = container.getBoundingClientRect();
            if (e.clientX < rect.left || e.clientX > rect.right ||
                e.clientY < rect.top || e.clientY > rect.bottom) {
                container.classList.remove('drag-over');
            }
        });
        container.addEventListener('drop', (e) => {
            e.preventDefault();
            e.stopPropagation();
            container.classList.remove('drag-over');
            const plainData = e.dataTransfer?.getData('text/plain') || '';
            const stepType = e.dataTransfer?.getData('stepType');
            // Handle drag and drop of steps
            // Check if this is a step drop
            if (plainData.startsWith('step:')) {
                // Extract the step type from the plain data
                const extractedType = plainData.replace('step:', '');
                const rect = container.getBoundingClientRect();
                let x = (e.clientX - rect.left - this.canvasOffset.x) / this.currentScale;
                let y = (e.clientY - rect.top - this.canvasOffset.y) / this.currentScale;
                // Snap to grid for better alignment (optional)
                const gridSize = 50;
                x = Math.round(x / gridSize) * gridSize;
                y = Math.round(y / gridSize) * gridSize;
                // Create step at calculated position
                this.createStep(extractedType, [x, y]);
            }
        });
        // Pan canvas
        let isPanning = false;
        let startX = 0;
        let startY = 0;
        container.addEventListener('mousedown', (e) => {
            const target = e.target;
            // Only pan if clicking on empty canvas area
            if (target.classList.contains('canvas-wrapper') || target.classList.contains('steps-container') || target.classList.contains('rete-container')) {
                isPanning = true;
                startX = e.clientX - this.canvasOffset.x;
                startY = e.clientY - this.canvasOffset.y;
                container.style.cursor = 'grabbing';
            }
        });
        document.addEventListener('mousemove', (e) => {
            if (isPanning) {
                this.canvasOffset.x = e.clientX - startX;
                this.canvasOffset.y = e.clientY - startY;
                this.updateCanvasTransform();
            }
        });
        document.addEventListener('mouseup', () => {
            isPanning = false;
            container.style.cursor = 'grab';
        });
        // Zoom
        container.addEventListener('wheel', (e) => {
            e.preventDefault();
            const delta = e.deltaY > 0 ? 0.9 : 1.1;
            this.currentScale = Math.max(0.1, Math.min(2, this.currentScale * delta));
            this.updateCanvasTransform();
        });
    }
    updateCanvasTransform() {
        const canvasWrapper = this.reteEditor.nativeElement.querySelector('.canvas-wrapper');
        if (canvasWrapper) {
            canvasWrapper.style.transform = `translate(${this.canvasOffset.x}px, ${this.canvasOffset.y}px) scale(${this.currentScale})`;
        }
    }
    selectStep(step) {
        // Toggle selection if clicking the same step
        if (this.selectedStepId === step.id) {
            this.selectedStepId = null;
            this.flowEditorService.selectNode(null);
        }
        else {
            this.selectedStepId = step.id;
            this.flowEditorService.selectNode(step);
        }
    }
    deleteStep(step) {
        this.stepToDelete = step;
    }
    confirmDeleteStep() {
        if (!this.stepToDelete)
            return;
        const stepId = this.stepToDelete.id;
        this.steps = this.steps.filter(s => s.id !== stepId);
        this.connections = this.connections.filter(c => c.source !== stepId && c.target !== stepId);
        // Update the service with all steps
        this.flowEditorService.setAllSteps(this.steps);
        if (this.selectedStepId === stepId) {
            this.selectedStepId = null;
            this.flowEditorService.selectNode(null);
        }
        this.stepToDelete = null;
    }
    cancelDeleteStep() {
        this.stepToDelete = null;
    }
    deleteConnection(connection) {
        this.connectionToDelete = connection;
    }
    confirmDeleteConnection() {
        if (!this.connectionToDelete)
            return;
        this.connections = this.connections.filter(c => c.id !== this.connectionToDelete.id);
        this.connectionToDelete = null;
    }
    cancelDeleteConnection() {
        this.connectionToDelete = null;
    }
    onConnectionClick(event, connection) {
        event.stopPropagation();
        // Check if Shift key is held for delete
        if (event.shiftKey) {
            this.deleteConnection(connection);
        }
        else {
            // Open condition editor
            this.editingConnection = { ...connection };
        }
    }
    getConnectionMidpoint(connection) {
        const source = this.steps.find(s => s.id === connection.source);
        const target = this.steps.find(s => s.id === connection.target);
        if (!source || !target) {
            return { x: 0, y: 0 };
        }
        // Use fixed dimensions for all steps
        const sourceDimensions = { width: this.STEP_WIDTH, height: this.STEP_HEIGHT };
        const targetDimensions = { width: this.STEP_WIDTH, height: this.STEP_HEIGHT };
        const x1 = source.position[0] + sourceDimensions.width; // Output socket center at edge
        const y1 = source.position[1] + (sourceDimensions.height / 2);
        const x2 = target.position[0]; // Input socket center at edge
        const y2 = target.position[1] + (targetDimensions.height / 2);
        // For backward connections, adjust midpoint to be on the curve
        if (this.isBackwardConnection(connection)) {
            const midX = (x1 + x2) / 2;
            const midY = (y1 + y2) / 2 + 50; // Offset down to match the curve
            return { x: midX, y: midY };
        }
        // Return the midpoint of the connection
        const midpoint = {
            x: (x1 + x2) / 2,
            y: (y1 + y2) / 2
        };
        return midpoint;
    }
    saveConnectionConditions(updatedConnection) {
        const index = this.connections.findIndex(c => c.id === updatedConnection.id);
        if (index !== -1) {
            this.connections[index] = updatedConnection;
        }
        this.closeConditionEditor();
    }
    closeConditionEditor() {
        this.editingConnection = null;
    }
    getConditionPreview(connection) {
        if (!connection.condition) {
            return 'Always';
        }
        return connection.condition.expression;
    }
    getConditionLabel(connection) {
        if (!connection.condition) {
            return 'Always';
        }
        const label = connection.condition.label || connection.condition.expression;
        // Truncate if too long
        const maxLength = 12;
        if (label.length > maxLength) {
            return label.substring(0, maxLength - 2) + '...';
        }
        return label;
    }
    getConditionBoxWidth(connection) {
        const label = this.getConditionLabel(connection);
        // Estimate width based on character count (approx 7px per character + padding)
        const estimatedWidth = Math.max(80, Math.min(140, label.length * 7 + 30));
        return estimatedWidth;
    }
    getConnectionColor(connection) {
        // Check if this is a backward connection
        if (this.isBackwardConnection(connection)) {
            return '#EF4444'; // Red for backward connections
        }
        // Define a palette of distinct colors for forward connections
        const colorPalette = [
            '#3B82F6', // Blue
            '#10B981', // Green
            '#F59E0B', // Amber
            '#8B5CF6', // Purple
            '#EC4899', // Pink
            '#14B8A6', // Teal
            '#F97316', // Orange
            '#06B6D4', // Cyan
        ];
        // Get all forward connections from the same source
        const sourceConnections = this.connections
            .filter(c => c.source === connection.source && !this.isBackwardConnection(c))
            .sort((a, b) => (a.id || '').localeCompare(b.id || '')); // Sort by ID for consistency
        // Find the index of this connection among connections from the same source
        const connectionIndex = sourceConnections.findIndex(c => c.id === connection.id);
        // Use modulo to cycle through colors if there are more connections than colors
        return colorPalette[connectionIndex % colorPalette.length];
    }
    isBackwardConnection(connection) {
        // A connection is backward if the target step is positioned to the left of the source step
        const sourceStep = this.steps.find(s => s.id === connection.source);
        const targetStep = this.steps.find(s => s.id === connection.target);
        if (!sourceStep || !targetStep)
            return false;
        // Check if target is to the left of source (backward in the flow)
        return targetStep.position[0] < sourceStep.position[0];
    }
    getConnectionDashArray(connection) {
        // Return dash array for backward connections, solid for forward
        return this.isBackwardConnection(connection) ? '10,5' : '';
    }
    getConnectionMarker(connection) {
        // Add arrow marker for backward connections
        return this.isBackwardConnection(connection) ? 'url(#backward-arrow)' : '';
    }
    updateStep(step) {
        // Step updated, trigger any necessary updates
        this.flowEditorService.updateNode(step);
    }
    onStepDragStart(event, step) {
        event.preventDefault();
        this.isDragging = true;
        this.currentDraggedStep = step;
        // Calculate the offset between the mouse position and the step position
        // We need to account for the canvas transform (scale and offset)
        const rect = this.reteEditor.nativeElement.getBoundingClientRect();
        const mouseX = (event.clientX - rect.left - this.canvasOffset.x) / this.currentScale;
        const mouseY = (event.clientY - rect.top - this.canvasOffset.y) / this.currentScale;
        // Store the offset between mouse and step position
        this.dragOffset.x = mouseX - step.position[0];
        this.dragOffset.y = mouseY - step.position[1];
        // Add document level mouse move and up listeners
        document.addEventListener('mousemove', this.handleMouseMove);
        document.addEventListener('mouseup', this.handleMouseUp);
    }
    onStepDragEnd() {
        this.handleMouseUp();
    }
    getConnectionPath(connection) {
        const source = this.steps.find(s => s.id === connection.source);
        const target = this.steps.find(s => s.id === connection.target);
        if (!source || !target) {
            return '';
        }
        // Use fixed dimensions for all steps
        const sourceDimensions = { width: this.STEP_WIDTH, height: this.STEP_HEIGHT };
        const targetDimensions = { width: this.STEP_WIDTH, height: this.STEP_HEIGHT };
        // Socket positions - sockets are at 50% of total step height
        // The sockets are 16px diameter circles centered at edges
        // Output socket center is at right edge (the socket extends beyond with right: -8px)
        // Input socket center is at left edge (the socket extends beyond with left: -8px)
        // Socket positioning: sockets are 16px diameter circles
        // With right: -8px, the socket center is at the step edge (not beyond)
        // With left: -8px, the socket center is at the step edge (not beyond)
        const x1 = source.position[0] + sourceDimensions.width; // Output socket center at right edge
        const y1 = source.position[1] + (sourceDimensions.height / 2); // 50% of step height
        const x2 = target.position[0]; // Input socket center at left edge
        const y2 = target.position[1] + (targetDimensions.height / 2); // 50% of step height
        // Check if this is a backward connection
        if (this.isBackwardConnection(connection)) {
            // For backward connections, create a more pronounced curve that goes below
            const dx = x2 - x1;
            // Make the curve go below the steps for better visibility
            const curveOffset = 100; // How far below to curve
            const midX = (x1 + x2) / 2;
            const midY = Math.max(y1, y2) + curveOffset;
            // Create a path that curves below with a smoother quadratic curve
            const cp1x = x1 + 50;
            const cp1y = y1 + curveOffset / 2;
            const cp2x = x2 - 50;
            const cp2y = y2 + curveOffset / 2;
            return `M ${x1} ${y1} C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${x2} ${y2}`;
        }
        // For forward connections, use the standard bezier curve
        const dx = x2 - x1;
        const controlPointOffset = Math.max(50, Math.min(150, Math.abs(dx) * 0.4));
        const path = `M ${x1} ${y1} C ${x1 + controlPointOffset} ${y1}, ${x2 - controlPointOffset} ${y2}, ${x2} ${y2}`;
        return path;
    }
    onZoomIn() {
        this.currentScale = Math.min(2, this.currentScale * 1.2);
        this.updateCanvasTransform();
    }
    onZoomOut() {
        this.currentScale = Math.max(0.1, this.currentScale * 0.8);
        this.updateCanvasTransform();
    }
    onResetView() {
        // Fit entire flow in view
        this.fitToView();
    }
    onAutoArrange() {
        // Recalculate optimal positions for all steps
        this.autoArrangeSteps();
        // Fit all steps in view
        this.fitToView();
    }
    autoArrangeSteps() {
        if (this.steps.length === 0)
            return;
        // Spacing adjusted for larger step dimensions and condition text
        // Step width is 320px, so we need spacing > 320px to avoid overlap
        const horizontalSpacing = 500; // Balanced spacing - enough room for connections without being too spread out
        const verticalSpacing = 200; // Good vertical separation
        // Build adjacency map for BFS traversal
        const adjacencyMap = new Map();
        const incomingEdges = new Map();
        this.steps.forEach(step => {
            adjacencyMap.set(step.id, []);
            incomingEdges.set(step.id, 0);
        });
        this.connections.forEach(conn => {
            const sourceSteps = adjacencyMap.get(conn.source) || [];
            sourceSteps.push(conn.target);
            adjacencyMap.set(conn.source, sourceSteps);
            const targetCount = incomingEdges.get(conn.target) || 0;
            incomingEdges.set(conn.target, targetCount + 1);
        });
        // Find starting nodes (no incoming edges or marked as starting)
        const startingSteps = this.steps.filter(step => incomingEdges.get(step.id) === 0 || step.mjData?.startingStep);
        // Use BFS to assign levels
        const levels = new Map();
        const queue = [...startingSteps];
        startingSteps.forEach(step => levels.set(step.id, 0));
        while (queue.length > 0) {
            const current = queue.shift();
            const currentLevel = levels.get(current.id) || 0;
            const neighbors = adjacencyMap.get(current.id) || [];
            neighbors.forEach(neighborId => {
                if (!levels.has(neighborId)) {
                    levels.set(neighborId, currentLevel + 1);
                    const neighborStep = this.steps.find(s => s.id === neighborId);
                    if (neighborStep)
                        queue.push(neighborStep);
                }
            });
        }
        // Group steps by level
        const stepsByLevel = new Map();
        this.steps.forEach(step => {
            const level = levels.get(step.id) || 0;
            if (!stepsByLevel.has(level)) {
                stepsByLevel.set(level, []);
            }
            stepsByLevel.get(level).push(step);
        });
        // Calculate positions
        const startX = 100;
        const startY = 50;
        stepsByLevel.forEach((stepsInLevel, level) => {
            const x = startX + (level * horizontalSpacing);
            const totalHeight = (stepsInLevel.length - 1) * verticalSpacing;
            const startYForLevel = startY + Math.max(0, (400 - totalHeight) / 2);
            stepsInLevel.forEach((step, index) => {
                const y = startYForLevel + (index * verticalSpacing);
                step.position = [x, y];
            });
        });
    }
    fitToView() {
        if (this.steps.length === 0) {
            // If no steps, just reset to default view
            this.currentScale = 1;
            this.canvasOffset = { x: 0, y: 0 };
            this.updateCanvasTransform();
            return;
        }
        // Get viewport dimensions
        const viewportWidth = this.reteEditor.nativeElement.clientWidth;
        const viewportHeight = this.reteEditor.nativeElement.clientHeight;
        // Check if DOM is ready - if not, retry
        if (viewportWidth === 0 || viewportHeight === 0) {
            setTimeout(() => this.fitToView(), 200);
            return;
        }
        // Find bounds of all steps
        let minX = Infinity, minY = Infinity;
        let maxX = -Infinity, maxY = -Infinity;
        this.steps.forEach(step => {
            minX = Math.min(minX, step.position[0]);
            minY = Math.min(minY, step.position[1]);
            maxX = Math.max(maxX, step.position[0] + this.STEP_WIDTH);
            maxY = Math.max(maxY, step.position[1] + this.STEP_HEIGHT);
        });
        // Calculate content dimensions
        const contentWidth = maxX - minX;
        const contentHeight = maxY - minY;
        // Calculate scale to fit content with padding
        const padding = 100;
        const scaleX = (viewportWidth - padding * 2) / contentWidth;
        const scaleY = (viewportHeight - padding * 2) / contentHeight;
        // Use the smaller scale to ensure everything fits
        // But don't zoom out too much or zoom in too much
        const idealScale = Math.min(scaleX, scaleY);
        this.currentScale = Math.max(0.3, Math.min(idealScale, 1.0));
        // Calculate the center point of the content
        const contentCenterX = minX + contentWidth / 2;
        const contentCenterY = minY + contentHeight / 2;
        // Calculate the center point of the viewport
        const viewportCenterX = viewportWidth / 2;
        const viewportCenterY = viewportHeight / 2;
        // Calculate offset to center the content
        this.canvasOffset.x = viewportCenterX - (contentCenterX * this.currentScale);
        this.canvasOffset.y = viewportCenterY - (contentCenterY * this.currentScale);
        this.updateCanvasTransform();
    }
    toggleExecutionPanel() {
        this.showExecutionPanel = !this.showExecutionPanel;
        this.toggleExecution.emit();
    }
    runFlow() {
        // Run the flow with current steps and connections
        if (this.steps.length === 0) {
            alert('Please add some steps to the flow first!');
            return;
        }
        this.flowExecutor.executeFlow(this.steps, this.connections);
    }
    ngOnDestroy() {
        // Cleanup
        document.removeEventListener('mousemove', this.handleConnectionMouseMove);
        document.removeEventListener('mouseup', this.handleConnectionMouseUp);
    }
    // Socket event handlers
    onSocketMouseDown(event) {
        event.event.stopPropagation();
        event.event.preventDefault();
        this.isCreatingConnection = true;
        const rect = this.reteEditor.nativeElement.getBoundingClientRect();
        this.tempConnection = {
            source: event.step,
            sourceType: event.type,
            mouseX: (event.event.clientX - rect.left - this.canvasOffset.x) / this.currentScale,
            mouseY: (event.event.clientY - rect.top - this.canvasOffset.y) / this.currentScale
        };
        // Add document-level listeners for connection creation
        document.addEventListener('mousemove', this.handleConnectionMouseMove);
        document.addEventListener('mouseup', this.handleConnectionMouseUp);
    }
    onSocketMouseEnter(event) {
        if (this.isCreatingConnection && this.tempConnection) {
            const targetStep = event.step;
            const sourceStep = this.tempConnection.source;
            // Check if we can create a connection
            if (this.canCreateConnection(sourceStep, targetStep, this.tempConnection.sourceType, event.type)) {
                // Highlight the socket
                const socket = event.event.target;
                socket.classList.add('can-connect');
                // Store the potential target for the mouseup event
                socket._connectionTarget = {
                    step: targetStep,
                    type: event.type
                };
            }
        }
    }
    onSocketMouseLeave(event) {
        const socket = event.target;
        socket.classList.remove('can-connect');
        delete socket._connectionTarget;
    }
    canCreateConnection(source, target, sourceType, targetType) {
        // Don't connect to self
        if (source.id === target.id)
            return false;
        // Only connect output to input
        if (sourceType === 'output' && targetType === 'input') {
            // Check if connection already exists
            return !this.connections.some(c => c.source === source.id && c.target === target.id);
        }
        return false;
    }
    getTempConnectionPath() {
        if (!this.tempConnection)
            return '';
        const source = this.tempConnection.source;
        const sourceType = this.tempConnection.sourceType;
        let x1, y1;
        const socketY = source.position[1] + (this.STEP_HEIGHT / 2);
        if (sourceType === 'output') {
            x1 = source.position[0] + this.STEP_WIDTH; // Output socket center at edge
            y1 = socketY;
        }
        else {
            x1 = source.position[0]; // Input socket center at edge
            y1 = socketY;
        }
        const x2 = this.tempConnection.mouseX;
        const y2 = this.tempConnection.mouseY;
        // Create a smooth bezier curve
        const dx = x2 - x1;
        const controlPointOffset = Math.max(50, Math.min(150, Math.abs(dx) * 0.4));
        if (sourceType === 'output') {
            return `M ${x1} ${y1} C ${x1 + controlPointOffset} ${y1}, ${x2 - controlPointOffset} ${y2}, ${x2} ${y2}`;
        }
        else {
            return `M ${x1} ${y1} C ${x1 - controlPointOffset} ${y1}, ${x2 + controlPointOffset} ${y2}, ${x2} ${y2}`;
        }
    }
    static { this.ɵfac = function FlowEditorComponent_Factory(t) { return new (t || FlowEditorComponent)(i0.ɵɵdirectiveInject(i1.FlowEditorService), i0.ɵɵdirectiveInject(i2.FlowExecutorService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); }; }
    static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FlowEditorComponent, selectors: [["app-flow-editor"]], viewQuery: function FlowEditorComponent_Query(rf, ctx) { if (rf & 1) {
            i0.ɵɵviewQuery(_c0, 7);
        } if (rf & 2) {
            let _t;
            i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.reteEditor = _t.first);
        } }, outputs: { toggleExecution: "toggleExecution", stepMoved: "stepMoved" }, standalone: true, features: [i0.ɵɵStandaloneFeature], decls: 43, vars: 14, consts: [["reteEditor", ""], [1, "flow-editor"], [1, "canvas-header"], [1, "legend-panel"], [1, "legend-header", 3, "click"], [1, "fas"], ["class", "legend-content", 4, "ngIf"], [1, "canvas-controls"], ["title", "Zoom In", 1, "control-button", 3, "click"], [1, "fas", "fa-search-plus"], ["title", "Zoom Out", 1, "control-button", 3, "click"], [1, "fas", "fa-search-minus"], ["title", "Reset View", 1, "control-button", 3, "click"], [1, "fas", "fa-sync-alt"], ["title", "Auto Arrange Steps", 1, "control-button", 3, "click"], [1, "fas", "fa-project-diagram"], ["title", "Toggle Execution Panel", 1, "control-button", 3, "click"], [1, "fas", "fa-play-circle"], [1, "rete-container"], [1, "canvas-wrapper"], [1, "connections-layer"], ["id", "backward-arrow", "markerWidth", "10", "markerHeight", "10", "refX", "9", "refY", "3", "orient", "auto", "markerUnits", "strokeWidth"], ["d", "M0,0 L0,6 L9,3 z", "fill", "#EF4444"], [4, "ngFor", "ngForOf"], ["class", "temp-connection-path", "fill", "none", "stroke", "#28a745", "stroke-width", "3", "stroke-dasharray", "5,5", 4, "ngIf"], [1, "steps-container"], [3, "step", "selected", "executing", "left", "top", "position", "stepSelected", "stepDeleted", "stepUpdated", "socketMouseDown", "socketMouseEnter", "socketMouseLeave", "mousedown", 4, "ngFor", "ngForOf"], ["class", "modal-backdrop", 3, "click", 4, "ngIf"], [3, "title", "message", "confirmText", "confirm", "cancel", 4, "ngIf"], [1, "legend-content"], [1, "legend-item"], ["width", "30", "height", "2"], ["x1", "0", "y1", "1", "x2", "30", "y2", "1", "stroke", "#3B82F6", "stroke-width", "2"], ["x1", "0", "y1", "1", "x2", "30", "y2", "1", "stroke", "#10B981", "stroke-width", "2"], ["x1", "0", "y1", "1", "x2", "30", "y2", "1", "stroke", "#F59E0B", "stroke-width", "2"], ["x1", "0", "y1", "1", "x2", "30", "y2", "1", "stroke", "#EF4444", "stroke-width", "2"], [1, "legend-note"], ["fill", "none", "stroke-width", "3", 1, "connection-path", 2, "cursor", "pointer", "pointer-events", "stroke", 3, "click"], ["fill", "none", "stroke", "transparent", "stroke-width", "20", 1, "connection-hover", 2, "cursor", "pointer", "pointer-events", "stroke", 3, "click"], [4, "ngIf"], ["height", "30", "rx", "15", "fill", "rgba(0,0,0,0.1)", 2, "pointer-events", "none"], ["height", "30", "rx", "15", "fill", "#FFFFFF", "stroke", "#0076B6", "stroke-width", "2", 2, "cursor", "pointer", 3, "click"], ["text-anchor", "middle", "font-size", "12", "font-weight", "600", "fill", "#0076B6", 2, "cursor", "pointer", "pointer-events", "none"], ["fill", "none", "stroke", "#28a745", "stroke-width", "3", "stroke-dasharray", "5,5", 1, "temp-connection-path"], [3, "stepSelected", "stepDeleted", "stepUpdated", "socketMouseDown", "socketMouseEnter", "socketMouseLeave", "mousedown", "step", "selected", "executing"], [1, "modal-backdrop", 3, "click"], [1, "modal-container", 3, "click"], [3, "save", "cancel", "connection"], [3, "confirm", "cancel", "title", "message", "confirmText"]], template: function FlowEditorComponent_Template(rf, ctx) { if (rf & 1) {
            const _r1 = i0.ɵɵgetCurrentView();
            i0.ɵɵelementStart(0, "div", 1)(1, "div", 2)(2, "div", 3)(3, "div", 4);
            i0.ɵɵlistener("click", function FlowEditorComponent_Template_div_click_3_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.legendCollapsed = !ctx.legendCollapsed); });
            i0.ɵɵelement(4, "i", 5);
            i0.ɵɵelementStart(5, "span");
            i0.ɵɵtext(6, "Connection Legend");
            i0.ɵɵelementEnd()();
            i0.ɵɵtemplate(7, FlowEditorComponent_div_7_Template, 23, 0, "div", 6);
            i0.ɵɵelementEnd();
            i0.ɵɵelementStart(8, "div", 7)(9, "button", 8);
            i0.ɵɵlistener("click", function FlowEditorComponent_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onZoomIn()); });
            i0.ɵɵelement(10, "i", 9);
            i0.ɵɵelementStart(11, "span");
            i0.ɵɵtext(12, "Zoom In");
            i0.ɵɵelementEnd()();
            i0.ɵɵelementStart(13, "button", 10);
            i0.ɵɵlistener("click", function FlowEditorComponent_Template_button_click_13_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onZoomOut()); });
            i0.ɵɵelement(14, "i", 11);
            i0.ɵɵelementStart(15, "span");
            i0.ɵɵtext(16, "Zoom Out");
            i0.ɵɵelementEnd()();
            i0.ɵɵelementStart(17, "button", 12);
            i0.ɵɵlistener("click", function FlowEditorComponent_Template_button_click_17_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onResetView()); });
            i0.ɵɵelement(18, "i", 13);
            i0.ɵɵelementStart(19, "span");
            i0.ɵɵtext(20, "Reset View");
            i0.ɵɵelementEnd()();
            i0.ɵɵelementStart(21, "button", 14);
            i0.ɵɵlistener("click", function FlowEditorComponent_Template_button_click_21_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAutoArrange()); });
            i0.ɵɵelement(22, "i", 15);
            i0.ɵɵelementStart(23, "span");
            i0.ɵɵtext(24, "Auto Arrange");
            i0.ɵɵelementEnd()();
            i0.ɵɵelementStart(25, "button", 16);
            i0.ɵɵlistener("click", function FlowEditorComponent_Template_button_click_25_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.toggleExecutionPanel()); });
            i0.ɵɵelement(26, "i", 17);
            i0.ɵɵelementStart(27, "span");
            i0.ɵɵtext(28);
            i0.ɵɵelementEnd()()()();
            i0.ɵɵelementStart(29, "div", 18, 0)(31, "div", 19);
            i0.ɵɵnamespaceSVG();
            i0.ɵɵelementStart(32, "svg", 20)(33, "defs")(34, "marker", 21);
            i0.ɵɵelement(35, "path", 22);
            i0.ɵɵelementEnd()();
            i0.ɵɵtemplate(36, FlowEditorComponent__svg_g_36_Template, 4, 6, "g", 23)(37, FlowEditorComponent__svg_path_37_Template, 1, 1, "path", 24);
            i0.ɵɵelementEnd();
            i0.ɵɵnamespaceHTML();
            i0.ɵɵelementStart(38, "div", 25);
            i0.ɵɵtemplate(39, FlowEditorComponent_app_step_39_Template, 1, 10, "app-step", 26);
            i0.ɵɵelementEnd()()();
            i0.ɵɵtemplate(40, FlowEditorComponent_div_40_Template, 3, 1, "div", 27)(41, FlowEditorComponent_app_confirmation_dialog_41_Template, 1, 3, "app-confirmation-dialog", 28)(42, FlowEditorComponent_app_confirmation_dialog_42_Template, 1, 3, "app-confirmation-dialog", 28);
            i0.ɵɵelementEnd();
        } if (rf & 2) {
            i0.ɵɵadvance(2);
            i0.ɵɵclassProp("collapsed", ctx.legendCollapsed);
            i0.ɵɵadvance(2);
            i0.ɵɵclassProp("fa-chevron-down", !ctx.legendCollapsed)("fa-chevron-right", ctx.legendCollapsed);
            i0.ɵɵadvance(3);
            i0.ɵɵproperty("ngIf", !ctx.legendCollapsed);
            i0.ɵɵadvance(21);
            i0.ɵɵtextInterpolate1("", ctx.showExecutionPanel ? "Hide" : "Show", " Execution");
            i0.ɵɵadvance(8);
            i0.ɵɵproperty("ngForOf", ctx.connections);
            i0.ɵɵadvance();
            i0.ɵɵproperty("ngIf", ctx.tempConnection);
            i0.ɵɵadvance(2);
            i0.ɵɵproperty("ngForOf", ctx.steps);
            i0.ɵɵadvance();
            i0.ɵɵproperty("ngIf", ctx.editingConnection);
            i0.ɵɵadvance();
            i0.ɵɵproperty("ngIf", ctx.stepToDelete);
            i0.ɵɵadvance();
            i0.ɵɵproperty("ngIf", ctx.connectionToDelete);
        } }, dependencies: [CommonModule, i3.NgForOf, i3.NgIf, StepComponent, SimpleConditionEditorComponent, ConfirmationDialogComponent], styles: [".flow-editor[_ngcontent-%COMP%] {\n  display: flex;\n  flex-direction: column;\n  height: 100%;\n  overflow: hidden;\n}\n\n.canvas-header[_ngcontent-%COMP%] {\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  padding: 0.75rem 1rem;\n  background-color: var(--white-color);\n  border-bottom: 1px solid var(--gray-700);\n  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n}\n\n.canvas-controls[_ngcontent-%COMP%] {\n  display: flex;\n  gap: 0.5rem;\n}\n\n.rete-container[_ngcontent-%COMP%] {\n  flex: 1;\n  position: relative;\n  overflow: hidden;\n  cursor: grab;\n  background-color: var(--gray-600);\n  \n  &.grabbing {\n    cursor: grabbing;\n  }\n  \n  &.drag-over {\n    background-color: rgba(0, 118, 182, 0.05);\n    outline: 2px dashed var(--mj-blue);\n    outline-offset: -2px;\n  }\n}\n\n.canvas-wrapper[_ngcontent-%COMP%] {\n  position: relative;\n  width: 5000px;  // Large area for workflow\n  height: 3000px; // Large height for vertical workflows\n  min-height: 600px;\n  transform-origin: 0 0;\n}\n\n.connections-layer[_ngcontent-%COMP%] {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 5000px;  // Match canvas-wrapper width\n  height: 3000px; // Match canvas-wrapper height\n  pointer-events: none;\n  z-index: 1;\n  overflow: visible;\n  \n  path {\n    pointer-events: auto;\n  }\n  \n  text, rect, circle {\n    pointer-events: auto;\n  }\n  \n  .temp-connection-path {\n    animation: dash 1s linear infinite;\n  }\n  \n  .connection-path {\n    transition: stroke 0.2s ease;\n  }\n  \n  .connection-hover:hover + .connection-path,\n  .connection-path:hover {\n    stroke: #dc3545 !important;\n  }\n  \n  @keyframes dash {\n    to {\n      stroke-dashoffset: -10;\n    }\n  }\n}\n\n.steps-container[_ngcontent-%COMP%] {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  z-index: 2;\n  pointer-events: none;\n  \n  app-step {\n    pointer-events: auto;\n  }\n}\n\n.control-button[_ngcontent-%COMP%] {\n  display: inline-flex;\n  align-items: center;\n  gap: 0.5rem;\n  padding: 0.5rem 1rem;\n  border: 1px solid var(--light-blue);\n  background: var(--white-color);\n  border-radius: 0.5rem;\n  cursor: pointer;\n  transition: all var(--transition-time);\n  font-size: 0.875rem;\n  color: var(--mj-blue);\n  \n  &:hover {\n    background: var(--light-blue);\n    color: var(--navy);\n    transform: translateY(-2px);\n    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n  }\n  \n  i {\n    font-size: 1rem;\n  }\n}\n\n.modal-backdrop[_ngcontent-%COMP%] {\n  position: fixed;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  background: rgba(0, 0, 0, 0.5);\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  z-index: 1000;\n}\n\n.modal-container[_ngcontent-%COMP%] {\n  position: relative;\n  animation: _ngcontent-%COMP%_modalSlideIn 0.3s ease;\n}\n\n@keyframes _ngcontent-%COMP%_modalSlideIn {\n  from {\n    opacity: 0;\n    transform: translateY(-20px);\n  }\n  to {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n\n.legend-panel[_ngcontent-%COMP%] {\n  position: relative;\n  background: var(--white-color);\n  border: 1px solid var(--gray-700);\n  border-radius: var(--border-radius);\n  box-shadow: var(--shadow);\n  min-width: 150px;\n  transition: all 0.3s ease;\n  margin-right: auto;\n  margin-left: 1rem;\n  \n  &.collapsed {\n    min-width: auto;\n    .legend-header {\n      border-bottom: none;\n      border-radius: var(--border-radius);\n    }\n  }\n  \n  .legend-header {\n    padding: 0.75rem;\n    background: var(--gray-600);\n    border-bottom: 1px solid var(--gray-700);\n    display: flex;\n    align-items: center;\n    gap: 0.5rem;\n    cursor: pointer;\n    user-select: none;\n    border-radius: calc(var(--border-radius) - 1px) calc(var(--border-radius) - 1px) 0 0;\n    \n    &:hover {\n      background: var(--gray-650);\n    }\n    \n    i {\n      font-size: 0.75rem;\n      transition: transform 0.2s;\n    }\n    \n    span {\n      font-weight: 600;\n      font-size: 0.875rem;\n    }\n  }\n  \n  .legend-content {\n    position: absolute;\n    top: 100%;\n    left: 0;\n    margin-top: 0.25rem;\n    background: var(--white-color);\n    border: 1px solid var(--gray-700);\n    border-radius: var(--border-radius);\n    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n    padding: 1rem;\n    min-width: 280px;\n    z-index: 1000;\n    \n    .legend-item {\n      display: flex;\n      align-items: center;\n      gap: 0.75rem;\n      margin-bottom: 0.75rem;\n      \n      svg {\n        flex-shrink: 0;\n      }\n      \n      span {\n        font-size: 0.813rem;\n        color: var(--gray-800);\n      }\n    }\n    \n    .legend-note {\n      margin-top: 1rem;\n      padding-top: 0.75rem;\n      border-top: 1px solid var(--gray-700);\n      font-size: 0.75rem;\n      color: var(--gray-750);\n      font-style: italic;\n    }\n  }\n}"] }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FlowEditorComponent, [{
        type: Component,
        args: [{ selector: 'app-flow-editor', standalone: true, imports: [CommonModule, StepComponent, SimpleConditionEditorComponent, ConfirmationDialogComponent], template: "<div class=\"flow-editor\">\n  <div class=\"canvas-header\">\n    <!-- Connection Legend -->\n    <div class=\"legend-panel\" [class.collapsed]=\"legendCollapsed\">\n      <div class=\"legend-header\" (click)=\"legendCollapsed = !legendCollapsed\">\n        <i class=\"fas\" [class.fa-chevron-down]=\"!legendCollapsed\" [class.fa-chevron-right]=\"legendCollapsed\"></i>\n        <span>Connection Legend</span>\n      </div>\n      <div class=\"legend-content\" *ngIf=\"!legendCollapsed\">\n        <div class=\"legend-item\">\n          <svg width=\"30\" height=\"2\">\n            <line x1=\"0\" y1=\"1\" x2=\"30\" y2=\"1\" stroke=\"#3B82F6\" stroke-width=\"2\"/>\n          </svg>\n          <span>First output from a step</span>\n        </div>\n        <div class=\"legend-item\">\n          <svg width=\"30\" height=\"2\">\n            <line x1=\"0\" y1=\"1\" x2=\"30\" y2=\"1\" stroke=\"#10B981\" stroke-width=\"2\"/>\n          </svg>\n          <span>Second output from a step</span>\n        </div>\n        <div class=\"legend-item\">\n          <svg width=\"30\" height=\"2\">\n            <line x1=\"0\" y1=\"1\" x2=\"30\" y2=\"1\" stroke=\"#F59E0B\" stroke-width=\"2\"/>\n          </svg>\n          <span>Third output from a step</span>\n        </div>\n        <div class=\"legend-item\">\n          <svg width=\"30\" height=\"2\">\n            <line x1=\"0\" y1=\"1\" x2=\"30\" y2=\"1\" stroke=\"#EF4444\" stroke-width=\"2\"/>\n          </svg>\n          <span>Backward connection (loop)</span>\n        </div>\n        <div class=\"legend-note\">\n          Colors help distinguish multiple paths from the same source step\n        </div>\n      </div>\n    </div>\n    \n    <div class=\"canvas-controls\">\n      <button \n        class=\"control-button\" \n        (click)=\"onZoomIn()\"\n        title=\"Zoom In\">\n        <i class=\"fas fa-search-plus\"></i>\n        <span>Zoom In</span>\n      </button>\n      <button \n        class=\"control-button\" \n        (click)=\"onZoomOut()\"\n        title=\"Zoom Out\">\n        <i class=\"fas fa-search-minus\"></i>\n        <span>Zoom Out</span>\n      </button>\n      <button \n        class=\"control-button\" \n        (click)=\"onResetView()\"\n        title=\"Reset View\">\n        <i class=\"fas fa-sync-alt\"></i>\n        <span>Reset View</span>\n      </button>\n      <button \n        class=\"control-button\" \n        (click)=\"onAutoArrange()\"\n        title=\"Auto Arrange Steps\">\n        <i class=\"fas fa-project-diagram\"></i>\n        <span>Auto Arrange</span>\n      </button>\n      <button \n        class=\"control-button\" \n        (click)=\"toggleExecutionPanel()\"\n        title=\"Toggle Execution Panel\">\n        <i class=\"fas fa-play-circle\"></i>\n        <span>{{ showExecutionPanel ? 'Hide' : 'Show' }} Execution</span>\n      </button>\n    </div>\n  </div>\n  \n  <div #reteEditor class=\"rete-container\">\n    <div class=\"canvas-wrapper\">\n      <svg class=\"connections-layer\">\n        <!-- Define arrow markers for backward connections -->\n        <defs>\n          <marker id=\"backward-arrow\" markerWidth=\"10\" markerHeight=\"10\" \n                  refX=\"9\" refY=\"3\" orient=\"auto\" markerUnits=\"strokeWidth\">\n            <path d=\"M0,0 L0,6 L9,3 z\" fill=\"#EF4444\" />\n          </marker>\n        </defs>\n        <g *ngFor=\"let connection of connections\">\n          <path [attr.d]=\"getConnectionPath(connection)\" \n                class=\"connection-path\"\n                fill=\"none\"\n                [attr.stroke]=\"getConnectionColor(connection)\"\n                [attr.stroke-dasharray]=\"getConnectionDashArray(connection)\"\n                [attr.marker-end]=\"getConnectionMarker(connection)\"\n                stroke-width=\"3\"\n                style=\"cursor: pointer; pointer-events: stroke\"\n                (click)=\"onConnectionClick($event, connection)\"/>\n          <path [attr.d]=\"getConnectionPath(connection)\" \n                class=\"connection-hover\"\n                fill=\"none\"\n                stroke=\"transparent\"\n                stroke-width=\"20\"\n                style=\"cursor: pointer; pointer-events: stroke\"\n                (click)=\"onConnectionClick($event, connection)\"/>\n          \n          <!-- Condition indicator -->\n          <g *ngIf=\"connection.condition\">\n            <!-- Shadow for condition box -->\n            <rect\n              [attr.x]=\"getConnectionMidpoint(connection).x - getConditionBoxWidth(connection)/2\"\n              [attr.y]=\"getConnectionMidpoint(connection).y - 15\"\n              [attr.width]=\"getConditionBoxWidth(connection)\"\n              height=\"30\"\n              rx=\"15\"\n              fill=\"rgba(0,0,0,0.1)\"\n              [attr.transform]=\"'translate(2, 2)'\"\n              style=\"pointer-events: none\"/>\n            <rect\n              [attr.x]=\"getConnectionMidpoint(connection).x - getConditionBoxWidth(connection)/2\"\n              [attr.y]=\"getConnectionMidpoint(connection).y - 15\"\n              [attr.width]=\"getConditionBoxWidth(connection)\"\n              height=\"30\"\n              rx=\"15\"\n              fill=\"#FFFFFF\"\n              stroke=\"#0076B6\"\n              stroke-width=\"2\"\n              style=\"cursor: pointer\"\n              (click)=\"onConnectionClick($event, connection)\"/>\n            <text \n              [attr.x]=\"getConnectionMidpoint(connection).x\"\n              [attr.y]=\"getConnectionMidpoint(connection).y + 4\"\n              text-anchor=\"middle\"\n              font-size=\"12\"\n              font-weight=\"600\"\n              fill=\"#0076B6\"\n              style=\"cursor: pointer; pointer-events: none;\">\n              {{ getConditionLabel(connection) }}\n            </text>\n          </g>\n          \n        </g>\n        <path *ngIf=\"tempConnection\" \n              [attr.d]=\"getTempConnectionPath()\" \n              class=\"temp-connection-path\"\n              fill=\"none\"\n              stroke=\"#28a745\"\n              stroke-width=\"3\"\n              stroke-dasharray=\"5,5\"/>\n      </svg>\n      \n      <div class=\"steps-container\">\n        <app-step \n          *ngFor=\"let step of steps\"\n          [step]=\"step\"\n          [selected]=\"selectedStepId === step.id\"\n          [executing]=\"executingStepId === step.id\"\n          [style.left.px]=\"step.position[0]\"\n          [style.top.px]=\"step.position[1]\"\n          [style.position]=\"'absolute'\"\n          [attr.data-step-id]=\"step.id\"\n          (stepSelected)=\"selectStep($event)\"\n          (stepDeleted)=\"deleteStep($event)\"\n          (stepUpdated)=\"updateStep($event)\"\n          (socketMouseDown)=\"onSocketMouseDown($event)\"\n          (socketMouseEnter)=\"onSocketMouseEnter($event)\"\n          (socketMouseLeave)=\"onSocketMouseLeave($event)\"\n          (mousedown)=\"onStepDragStart($event, step)\">\n        </app-step>\n      </div>\n    </div>\n  </div>\n  \n  <!-- Condition Editor Modal -->\n  <div class=\"modal-backdrop\" *ngIf=\"editingConnection\" (click)=\"closeConditionEditor()\">\n    <div class=\"modal-container\" (click)=\"$event.stopPropagation()\">\n      <app-simple-condition-editor\n        [connection]=\"editingConnection\"\n        (save)=\"saveConnectionConditions($event)\"\n        (cancel)=\"closeConditionEditor()\">\n      </app-simple-condition-editor>\n    </div>\n  </div>\n  \n  <!-- Delete Step Confirmation Dialog -->\n  <app-confirmation-dialog\n    *ngIf=\"stepToDelete\"\n    [title]=\"'Delete Step'\"\n    [message]=\"'Are you sure you want to delete this ' + stepToDelete.config.name + ' step? This action cannot be undone.'\"\n    [confirmText]=\"'Delete'\"\n    (confirm)=\"confirmDeleteStep()\"\n    (cancel)=\"cancelDeleteStep()\">\n  </app-confirmation-dialog>\n  \n  <!-- Delete Connection Confirmation Dialog -->\n  <app-confirmation-dialog\n    *ngIf=\"connectionToDelete\"\n    [title]=\"'Delete Connection'\"\n    [message]=\"'Are you sure you want to delete this connection? This action cannot be undone.'\"\n    [confirmText]=\"'Delete'\"\n    (confirm)=\"confirmDeleteConnection()\"\n    (cancel)=\"cancelDeleteConnection()\">\n  </app-confirmation-dialog>\n</div>", styles: [".flow-editor {\n  display: flex;\n  flex-direction: column;\n  height: 100%;\n  overflow: hidden;\n}\n\n.canvas-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  padding: 0.75rem 1rem;\n  background-color: var(--white-color);\n  border-bottom: 1px solid var(--gray-700);\n  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n}\n\n.canvas-controls {\n  display: flex;\n  gap: 0.5rem;\n}\n\n.rete-container {\n  flex: 1;\n  position: relative;\n  overflow: hidden;\n  cursor: grab;\n  background-color: var(--gray-600);\n  \n  &.grabbing {\n    cursor: grabbing;\n  }\n  \n  &.drag-over {\n    background-color: rgba(0, 118, 182, 0.05);\n    outline: 2px dashed var(--mj-blue);\n    outline-offset: -2px;\n  }\n}\n\n.canvas-wrapper {\n  position: relative;\n  width: 5000px;  // Large area for workflow\n  height: 3000px; // Large height for vertical workflows\n  min-height: 600px;\n  transform-origin: 0 0;\n}\n\n.connections-layer {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 5000px;  // Match canvas-wrapper width\n  height: 3000px; // Match canvas-wrapper height\n  pointer-events: none;\n  z-index: 1;\n  overflow: visible;\n  \n  path {\n    pointer-events: auto;\n  }\n  \n  text, rect, circle {\n    pointer-events: auto;\n  }\n  \n  .temp-connection-path {\n    animation: dash 1s linear infinite;\n  }\n  \n  .connection-path {\n    transition: stroke 0.2s ease;\n  }\n  \n  .connection-hover:hover + .connection-path,\n  .connection-path:hover {\n    stroke: #dc3545 !important;\n  }\n  \n  @keyframes dash {\n    to {\n      stroke-dashoffset: -10;\n    }\n  }\n}\n\n.steps-container {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  z-index: 2;\n  pointer-events: none;\n  \n  app-step {\n    pointer-events: auto;\n  }\n}\n\n.control-button {\n  display: inline-flex;\n  align-items: center;\n  gap: 0.5rem;\n  padding: 0.5rem 1rem;\n  border: 1px solid var(--light-blue);\n  background: var(--white-color);\n  border-radius: 0.5rem;\n  cursor: pointer;\n  transition: all var(--transition-time);\n  font-size: 0.875rem;\n  color: var(--mj-blue);\n  \n  &:hover {\n    background: var(--light-blue);\n    color: var(--navy);\n    transform: translateY(-2px);\n    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n  }\n  \n  i {\n    font-size: 1rem;\n  }\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  background: rgba(0, 0, 0, 0.5);\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  z-index: 1000;\n}\n\n.modal-container {\n  position: relative;\n  animation: modalSlideIn 0.3s ease;\n}\n\n@keyframes modalSlideIn {\n  from {\n    opacity: 0;\n    transform: translateY(-20px);\n  }\n  to {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n\n.legend-panel {\n  position: relative;\n  background: var(--white-color);\n  border: 1px solid var(--gray-700);\n  border-radius: var(--border-radius);\n  box-shadow: var(--shadow);\n  min-width: 150px;\n  transition: all 0.3s ease;\n  margin-right: auto;\n  margin-left: 1rem;\n  \n  &.collapsed {\n    min-width: auto;\n    .legend-header {\n      border-bottom: none;\n      border-radius: var(--border-radius);\n    }\n  }\n  \n  .legend-header {\n    padding: 0.75rem;\n    background: var(--gray-600);\n    border-bottom: 1px solid var(--gray-700);\n    display: flex;\n    align-items: center;\n    gap: 0.5rem;\n    cursor: pointer;\n    user-select: none;\n    border-radius: calc(var(--border-radius) - 1px) calc(var(--border-radius) - 1px) 0 0;\n    \n    &:hover {\n      background: var(--gray-650);\n    }\n    \n    i {\n      font-size: 0.75rem;\n      transition: transform 0.2s;\n    }\n    \n    span {\n      font-weight: 600;\n      font-size: 0.875rem;\n    }\n  }\n  \n  .legend-content {\n    position: absolute;\n    top: 100%;\n    left: 0;\n    margin-top: 0.25rem;\n    background: var(--white-color);\n    border: 1px solid var(--gray-700);\n    border-radius: var(--border-radius);\n    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n    padding: 1rem;\n    min-width: 280px;\n    z-index: 1000;\n    \n    .legend-item {\n      display: flex;\n      align-items: center;\n      gap: 0.75rem;\n      margin-bottom: 0.75rem;\n      \n      svg {\n        flex-shrink: 0;\n      }\n      \n      span {\n        font-size: 0.813rem;\n        color: var(--gray-800);\n      }\n    }\n    \n    .legend-note {\n      margin-top: 1rem;\n      padding-top: 0.75rem;\n      border-top: 1px solid var(--gray-700);\n      font-size: 0.75rem;\n      color: var(--gray-750);\n      font-style: italic;\n    }\n  }\n}\n\n\n"] }]
    }], () => [{ type: i1.FlowEditorService }, { type: i2.FlowExecutorService }, { type: i0.ChangeDetectorRef }], { reteEditor: [{
            type: ViewChild,
            args: ['reteEditor', { static: true }]
        }], toggleExecution: [{
            type: Output
        }], stepMoved: [{
            type: Output
        }] }); })();
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FlowEditorComponent, { className: "FlowEditorComponent", filePath: "src/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/flow-editor/flow-editor.component.ts", lineNumber: 18 }); })();
//# sourceMappingURL=flow-editor.component.js.map