"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FlowEditContext = void 0;
const tslib_1 = require("tslib");
const jsx_runtime_1 = require("react/jsx-runtime");
const AutoBind_1 = require("@appglue/common/dist/Common/AutoBind");
const FlowStepSequence_1 = require("@appglue/common/dist/Flow/Structure/FlowStepSequence");
const FlowStepData_1 = require("@appglue/common/dist/Flow/Steps/FlowStepData");
const StateManager_1 = require("@appglue/common/dist/Common/StateManager");
const DataUtilities_1 = require("@appglue/common/dist/Common/DataUtilities");
const FlowConfiguration_1 = require("@appglue/common/dist/Flow/FlowConfiguration");
const FlowConstants_1 = require("@appglue/common/dist/Flow/Utilities/FlowConstants");
const CandidateSequence_1 = require("@appglue/common/dist/Flow/Structure/CandidateSequence");
const FlowStepOutputInstructions_1 = require("@appglue/common/dist/Flow/Structure/FlowStepOutputInstructions");
const HTMLUtilities_1 = require("../CommonUI/HTMLUtilities");
const ReactRenderHook_1 = require("../CommonUI/ReactRenderHook");
const DataDefinition_1 = require("@appglue/common/dist/Common/Data/DataDefinition");
const FlowEditContext_PositionData_1 = require("./Builder/FlowEditContext.PositionData");
const FlowBuilderPage_1 = require("./Builder/FlowBuilderPage");
const FlowExtraConnection_1 = require("@appglue/common/dist/Flow/Structure/FlowExtraConnection");
const RegisterFlowStepData_1 = require("@appglue/common/dist/Flow/Utilities/RegisterFlowStepData");
const RegisterFlowEditor_1 = require("./Utilities/RegisterFlowEditor");
const AppGlueError_1 = require("@appglue/common/dist/AppGlueError");
const FlowUtilities_1 = require("@appglue/common/dist/Flow/Utilities/FlowUtilities");
const core_1 = require("@material-ui/core");
const BranchIcon_1 = require("../CommonUI/Icon/BranchIcon");
const react_1 = require("react");
const FlowSequenceEditRenderer_1 = require("./Builder/FlowSequenceEditRenderer");
const FlowSequenceCompleteStrategy_1 = require("@appglue/common/dist/Flow/Structure/FlowSequenceCompleteStrategy");
const UIToggleButton_1 = require("../CommonUI/BuildlingBlocks/UIToggleButton");
const UILabel_1 = require("../CommonUI/BuildlingBlocks/UILabel");
const ObserveState_1 = require("../CommonUI/StateManagement/ObserveState");
const UIButton_1 = require("../CommonUI/BuildlingBlocks/UIButton");
const FlowMappingLayer_1 = require("./Builder/Components/FlowMappingLayer");
class FlowEditContext {
    static CONNECTIONS_CHANGED = "connections";
    static IS_SHOW_EDITOR = "isShowEditor";
    static DESIGNER_SCROLL_TOP = "designerScrollTop";
    static CONTEXT_CONTROl = "contextControl";
    static SHOW_ERROR_BRANCH = "isShowErrorBranch";
    static SELECTION_ELEMENT = "selectionElement";
    static SELECTED_SEQUENCE_FOR_ERROR = "selectedSequenceForError";
    static IS_SHOW_ERROR_BRANCH = "isShowErrorBranch";
    static SHOW_ERROR_OR_END_CONNECTIONS = "showErrorOrEndConnections";
    static NOTIFICATION = "notification";
    static SHOW_STEP_STRATEGY = "selectedStepStrategy";
    static SELECTED_FOR_COLOR = "selectedForColor";
    static FLOW_NAME = "flowName";
    static IS_SHOW_DESCRIPTION = "isShowDescription";
    static IS_COLLAPSED = "isCollapsed";
    static MODE = "mode";
    static DRAGGING_CONTROL = "draggingControl";
    static DRAG_OVER_SEQUENCE = "dragOverSequence";
    static CLIPBOARD_ELEMENT = "clipboardElement";
    static SHOW_SEQUENCE_STRATEGY = "showSequenceStrategy";
    static FLOW_CONTEXT_LISTENER_NAME = "FlowContextListenerName__";
    onFlowSave;
    onFlowCancel;
    flowEditor;
    flow;
    flowName;
    viewAPIUrl;
    flowStartDataDefinition = new DataDefinition_1.DataDefinition();
    mode = FlowBuilderPage_1.FlowBuilderPage.Flow;
    isShowEditor = false;
    candidateWidth = FlowConstants_1.FlowConstants.PATH_CANDIDATE_WIDTH;
    candidateHeight = FlowConstants_1.FlowConstants.PATH_CANDIDATE_HEIGHT;
    candidateDraggingWidth = FlowConstants_1.FlowConstants.PATH_DRAGGING_CANDIDATE_WIDTH;
    candidateDraggingHeight = FlowConstants_1.FlowConstants.PATH_DRAGGING_CANDIDATE_HEIGHT;
    candidatePadding = "0 40px";
    candidateFontSize = 12;
    sequenceCandidateShift = FlowConstants_1.FlowConstants.SEQUENCE_CANDIDATE_SHIFT;
    pathCandidateShift = FlowConstants_1.FlowConstants.PATH_CANDIDATE_SHIFT;
    collapsedWidth = FlowConstants_1.FlowConstants.DEFAULT_COLLAPSED_STACK_WIDTH;
    collapsedHeight = FlowConstants_1.FlowConstants.DEFAULT_COLLAPSED_STACK_HEIGHT;
    errorCollapsedWidth = FlowConstants_1.FlowConstants.COLLAPSED_ERROR_STACK_WIDTH;
    stackWidth = FlowConstants_1.FlowConstants.DEFAULT_STACK_WIDTH;
    stackHeight = FlowConstants_1.FlowConstants.DEFAULT_STACK_HEIGHT;
    stepEditors = {};
    constructor(flow, flowEditor) {
        this.flow = flow;
        this.flowEditor = flowEditor;
        // check initial positioning
        this.delayPosition();
        // listen to flow
        StateManager_1.StateManager.addObserver(flow, (_o, val) => {
            this.flowChanged(val);
        });
        // setup listeners to all sequences
        this.listenToSequences();
    }
    _selectedForColor = undefined;
    get selectedForColor() {
        return this._selectedForColor;
    }
    set selectedForColor(sel) {
        this._selectedForColor = sel;
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.SELECTED_FOR_COLOR);
    }
    _selectedSequenceForError = null;
    get selectedSequenceForError() {
        return this._selectedSequenceForError;
    }
    set selectedSequenceForError(s) {
        this._selectedSequenceForError = s;
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.SELECTED_SEQUENCE_FOR_ERROR);
    }
    _isShowErrorBranch = false;
    get isShowErrorBranch() {
        return this._isShowErrorBranch;
    }
    set isShowErrorBranch(show) {
        this._isShowErrorBranch = show;
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.IS_SHOW_ERROR_BRANCH);
    }
    _isShowDescription = false;
    get isShowDescription() {
        return this._isShowDescription;
    }
    set isShowDescription(show) {
        this._isShowDescription = show;
        this.flow.toggleShowDescription(show);
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.IS_SHOW_DESCRIPTION);
    }
    _selectedSequenceStrategy = null;
    get selectedSequenceStrategy() {
        return this._selectedSequenceStrategy;
    }
    set selectedSequenceStrategy(s) {
        this._selectedSequenceStrategy = s;
        if (s?.sequence)
            StateManager_1.StateManager.changed(s.sequence);
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.SHOW_SEQUENCE_STRATEGY);
    }
    _selectedStepStrategy = null;
    get selectedStepStrategy() {
        return this._selectedStepStrategy;
    }
    set selectedStepStrategy(s) {
        this._selectedStepStrategy = s;
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.SHOW_STEP_STRATEGY);
    }
    _clipboardElement;
    get clipboardElement() {
        return this._clipboardElement;
    }
    set clipboardElement(elem) {
        this._clipboardElement = elem;
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.CLIPBOARD_ELEMENT);
    }
    _contextControl = null;
    // ------------------------
    // handling flow structure changes
    // ------------------------
    get contextControl() {
        return this._contextControl;
    }
    set contextControl(control) {
        this._contextControl = control;
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.CONTEXT_CONTROl);
    }
    // ------------------------
    // end - handling flow structure changes
    // ------------------------
    // ------------------------
    // force refresh
    // ------------------------
    _notification;
    get notification() {
        return this._notification;
    }
    set notification(n) {
        this._notification = n;
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.NOTIFICATION);
    }
    _draggingElemType;
    // ------------------------
    // end - force refresh
    // ------------------------
    get draggingElemType() {
        return this._draggingElemType;
    }
    set draggingElemType(type) {
        this._draggingElemType = type;
    }
    _selectionElement;
    get selectionElement() {
        return this._selectionElement;
    }
    _lastSelectionElement;
    get lastSelectionElement() {
        return this._lastSelectionElement;
    }
    _dragOverSequenceId = undefined;
    get dragOverSequenceId() {
        return this._dragOverSequenceId;
    }
    _draggingControl = null;
    get draggingControl() {
        return this._draggingControl;
    }
    set draggingControl(con) {
        this._draggingControl = con;
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.DRAGGING_CONTROL);
    }
    _showErrorOrEndConnections = null;
    // showing connections for error or end
    get showErrorOrEndConnections() {
        return this._showErrorOrEndConnections;
    }
    set showErrorOrEndConnections(isShow) {
        this._showErrorOrEndConnections = isShow;
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.SHOW_ERROR_OR_END_CONNECTIONS);
    }
    _isCollapsed = false;
    get isCollapsed() {
        return this._isCollapsed;
    }
    set isCollapsed(show) {
        this._isCollapsed = show;
        this.flow.toggleCollapsed(show);
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.IS_COLLAPSED);
    }
    _designerScrollTop = 0;
    get designerScrollTop() {
        return this._designerScrollTop;
    }
    set designerScrollTop(top) {
        this._designerScrollTop = top;
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.DESIGNER_SCROLL_TOP);
    }
    set dragOverSequence(sequence) {
        let oldSequence = null;
        // same sequence no need to update.
        if (sequence && sequence._id === this._dragOverSequenceId)
            return;
        if (this._dragOverSequenceId) {
            oldSequence = this.flow.find(this._dragOverSequenceId);
        }
        if (sequence) {
            this._dragOverSequenceId = sequence._id;
            StateManager_1.StateManager.propertyChanged(sequence, FlowEditContext.DRAG_OVER_SEQUENCE);
        }
        else {
            this._dragOverSequenceId = undefined;
        }
        if (oldSequence) {
            StateManager_1.StateManager.propertyChanged(oldSequence, FlowEditContext.DRAG_OVER_SEQUENCE);
        }
    }
    get selection() {
        return this._selectionElement?._id;
    }
    getLine(value) {
        let targetSequence = this.flow.getCandidateOrRealSequence(value.toId);
        let isHiddenStep = FlowUtilities_1.FlowUtilities.IsEndStep(value.fromStep);
        let startId = null;
        let startAnchor = "right";
        let endAnchor = [
            "left",
            "top",
            {
                position: "bottom",
                offset: {
                    x: 20,
                    y: -10,
                },
            },
        ];
        let endId = value.toId;
        if (value.isReturn) {
            startId = value.fromId;
            endId = value.toId;
            if (isHiddenStep) {
                endAnchor = {
                    position: "bottom",
                    offset: {
                        x: 20,
                        y: 20,
                    },
                };
            }
            if (!isHiddenStep) {
                if (value.fromSequence.isCollapsed) {
                    endId = value.fromSequence._id;
                    startId = value.fromId;
                }
                endAnchor = {
                    position: "right",
                    offset: {
                        x: -5,
                        y: 10,
                    },
                };
            }
            //            const startSeq = this.editContext.flow.getCandidateOrRealSequence(startId) as FlowStepSequence;
            startAnchor = {
                position: "left",
                offset: {
                    x: 0,
                    y: 10,
                },
            };
            return {
                targetSequence,
                arrow: {
                    start: startId,
                    startAnchor: startAnchor,
                    end: endId,
                    endAnchor: endAnchor,
                    strokeWidth: 2,
                    dashness: true,
                    headSize: 3,
                    color: FlowConstants_1.FlowConstants.DEFAULT_RELATION_LINE_COLOR,
                    //                    avoidRects: this.flow.sequences.map((s) => s._id),
                },
                labels: [],
                value,
            };
        }
        else {
            if (value.fromSequence.isCollapsed) {
                // no need to split the lines by instruction. just do with squence.
                startId = value.fromSequence._id;
                startAnchor = [
                    {
                        position: "bottom",
                        offset: {
                            x: 20,
                            y: -10,
                        },
                    },
                    {
                        position: "right",
                        offset: {
                            y: Math.ceil(value.fromSequence.instructions.filter((ins) => ins.strategy !== FlowStepOutputInstructions_1.FlowStepOutputInstructionType.BRANCH).length / 2) * 16,
                            x: -12,
                        },
                    },
                    "top",
                    "left",
                ];
            }
            else {
                startId = value.fromId;
            }
            if (isHiddenStep) {
                startAnchor = "bottom";
            }
            if (targetSequence instanceof CandidateSequence_1.CandidateSequence && !isHiddenStep) {
                endAnchor = "left";
            }
            const tooltip = value.fromInstruction.pathName;
            const label = tooltip.length > FlowConstants_1.FlowConstants.MAX_CHARS_STEP_PATH_LABEL
                ? `${tooltip.slice(0, FlowConstants_1.FlowConstants.MAX_CHARS_STEP_PATH_LABEL)}...`
                : tooltip;
            return {
                targetSequence,
                arrow: {
                    start: startId,
                    startAnchor: startAnchor,
                    end: endId,
                    endAnchor: endAnchor,
                    strokeWidth: 2,
                    headSize: 3,
                    color: FlowConstants_1.FlowConstants.DEFAULT_RELATION_LINE_COLOR,
                    //avoidRects: this.flow.sequences.map((s) => s._id),
                },
                labels: [
                    {
                        label: ((0, jsx_runtime_1.jsx)(core_1.Tooltip, { title: tooltip, children: (0, jsx_runtime_1.jsxs)("span", { style: { display: "flex", alignItems: "center" }, children: [isHiddenStep && (0, jsx_runtime_1.jsx)(BranchIcon_1.BranchIcon, {}), " ", label] }) })),
                        value,
                        isFlowConnection: isHiddenStep,
                    },
                ],
                value,
            };
        }
    }
    getLines() {
        let connections = this.flow.getConnections();
        connections = connections.filter((c) => {
            // hide the line while dragging
            if (c.fromStep._id === this.draggingControl?.source.current) {
                return false;
            }
            return true;
        });
        return connections.reduce((lines, value) => {
            let line = this.getLine(value);
            let isSet = false;
            if (!value.isReturn) {
                for (let l of lines) {
                    // combining the lines by start sequence and end sequence.
                    if (l.arrow.end === line.arrow.end && l.value.fromSequence._id === line.value.fromSequence._id) {
                        l.labels = [...l.labels, ...line.labels];
                        l.arrow.start = l.value.fromSequence._id;
                        isSet = true;
                        break;
                    }
                }
            }
            if (!isSet) {
                lines.push(line);
            }
            return lines;
        }, []);
    }
    listenToSequences() {
        for (let s of this.flow.sequences) {
            StateManager_1.StateManager.removeObserverByName(s, FlowEditContext.FLOW_CONTEXT_LISTENER_NAME);
            StateManager_1.StateManager.addObserver(s, (o, val) => {
                this.flowSequenceChanged(o, val);
            }, undefined, FlowEditContext.FLOW_CONTEXT_LISTENER_NAME);
        }
    }
    flowChanged(properties) {
        if (properties && properties.length !== 0 && properties?.indexOf(FlowConfiguration_1.FlowConfiguration.CANDIDATE_SEQUENCES) !== -1)
            StateManager_1.StateManager.propertyChanged(this, FlowConfiguration_1.FlowConfiguration.CANDIDATE_SEQUENCES);
        if (properties && properties.length !== 0 && properties?.indexOf(FlowConfiguration_1.FlowConfiguration.SEQUENCES) !== -1)
            StateManager_1.StateManager.propertyChanged(this, FlowConfiguration_1.FlowConfiguration.SEQUENCES);
        if (properties && properties.indexOf(FlowConfiguration_1.FlowConfiguration.ADD_SEQUENCE) !== -1) {
            this.listenToSequences();
        }
        if (properties && properties.indexOf(FlowConfiguration_1.FlowConfiguration.REMOVE_SEQUENCE) !== -1) {
            this.listenToSequences();
        }
        if (properties && properties.indexOf(FlowConfiguration_1.FlowConfiguration.OUTPUT_STRATEGY) !== -1) {
            StateManager_1.StateManager.propertyChanged(this, FlowConfiguration_1.FlowConfiguration.OUTPUT_STRATEGY);
        }
        if (properties === undefined ||
            properties.length === 0 ||
            properties?.indexOf(FlowConfiguration_1.FlowConfiguration.SEQUENCES) !== -1 ||
            properties?.indexOf(FlowConfiguration_1.FlowConfiguration.CANDIDATE_SEQUENCES) !== -1 ||
            properties?.indexOf(FlowConfiguration_1.FlowConfiguration.REMOVE_SEQUENCE) !== -1 ||
            properties?.indexOf(FlowConfiguration_1.FlowConfiguration.ADD_SEQUENCE) !== -1)
            this.delayPosition();
    }
    flowSequenceChanged(_sequence, properties) {
        if (properties === undefined ||
            properties?.indexOf(FlowStepSequence_1.FlowStepSequence.STEPS_CHANGED) !== -1 ||
            properties?.indexOf(FlowStepSequence_1.FlowStepSequence.MOVED) !== -1 ||
            properties?.indexOf(FlowStepSequence_1.FlowStepSequence.COLLAPSING) !== -1 ||
            properties?.indexOf(FlowStepSequence_1.FlowStepSequence.EXPANDING) !== -1 ||
            properties?.indexOf(FlowStepSequence_1.FlowStepSequence.IS_COLLAPSED) !== -1 ||
            properties?.indexOf(FlowStepSequence_1.FlowStepSequence.DRAG_END) !== -1 ||
            properties?.indexOf(FlowStepSequence_1.FlowStepSequence.BRANCHES_CHANGED) !== -1) {
            this.delayPosition();
        }
        if (properties !== undefined && properties?.indexOf(FlowStepSequence_1.FlowStepSequence.STEPS_CHANGED) !== -1) {
            this.flow.invalidateNodes();
        }
        if (properties === undefined || properties?.indexOf(FlowStepSequence_1.FlowStepSequence.STRATEGY) !== -1) {
            console.log("doing refresh");
            this.syncCandidates();
            this.delayPosition(true);
        }
        if (properties?.indexOf(FlowStepSequence_1.FlowStepSequence.DRAG_OVER) !== -1)
            StateManager_1.StateManager.propertyChanged(this, FlowStepSequence_1.FlowStepSequence.DRAG_OVER);
        if (properties?.indexOf(FlowStepSequence_1.FlowStepSequence.STRATEGY) !== -1)
            StateManager_1.StateManager.propertyChanged(this, FlowStepSequence_1.FlowStepSequence.STRATEGY);
        if (properties?.indexOf(FlowStepSequence_1.FlowStepSequence.DRAG_END) !== -1)
            this.refreshLines();
    }
    getOrCreateStepEditor(type, data) {
        if (data) {
            let editor = this.stepEditors[data?._id];
            if (editor)
                return editor;
        }
        let reg = RegisterFlowEditor_1.FlowStepEditorRegistration.getByTypeName(type);
        if (!reg)
            throw new AppGlueError_1.AppGlueError("could not find registratio for type " + type);
        return reg.create(this, data);
    }
    getStepEditor(id) {
        let step = this.flow.find(id);
        if (!step)
            throw new AppGlueError_1.AppGlueError("flow step not found " + id);
        return this.getOrCreateStepEditor(step.__type, step);
    }
    registerStepEditor(_id, control) {
        this.stepEditors[_id] = control;
    }
    // eslint-disable-next-line
    onStepMoved(fromSequence, toSequence, step) {
        // if to sequence is collapsed, set it expanded and select added step.
        if (toSequence instanceof FlowStepSequence_1.FlowStepSequence && toSequence.isCollapsed) {
            toSequence.isCollapsed = false;
            this.setSelection(step);
        }
        this.delayPosition();
    }
    renderEditUI(editContext, elem) {
        if (!elem)
            return null;
        if (elem instanceof FlowConfiguration_1.FlowConfiguration) {
            return (0, jsx_runtime_1.jsx)(RenderFlowSettingsEditor, { flowConfig: elem });
        }
        else if (elem instanceof FlowStepSequence_1.FlowStepSequence) {
            return new FlowSequenceEditRenderer_1.FlowSequenceEditRenderer(elem).renderEditUI();
        }
        else {
            let stepui = this.getOrCreateStepEditor(elem.__type, elem);
            return stepui.renderEditUI();
        }
    }
    getSequenceWidth(sequence) {
        return this.getSequenceMainSize(sequence).width || 0;
    }
    getSequenceY(sequence) {
        // we need to get the updated position of end / error using geometry as we are not setting the position data for them in positioned logic.
        if (sequence.isEnd || sequence.isError) {
            return ((this.geometryForElementById(sequence._id)?.top || 0) +
                (this.designerScrollTop || 0) -
                (this.designerGeometry()?.top || 0));
        }
        return sequence.y;
    }
    geometryForElementById(id) {
        return HTMLUtilities_1.HTMLUtilities.getGeometry(id, FlowConstants_1.FlowConstants.DESIGN_SURFACE_ID);
    }
    designerGeometry() {
        return HTMLUtilities_1.HTMLUtilities.getGeometry(FlowConstants_1.FlowConstants.DESIGN_SURFACE_ID);
    }
    refreshSequences() {
        StateManager_1.StateManager.propertyChanged(this, FlowConfiguration_1.FlowConfiguration.CANDIDATE_SEQUENCES);
        StateManager_1.StateManager.propertyChanged(this.flow, FlowConfiguration_1.FlowConfiguration.SEQUENCES);
        // it calls refresh lines
        this.refreshLines();
    }
    refreshLines() {
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.CONNECTIONS_CHANGED);
    }
    getCandidateSequences() {
        return this.flow.candidateSequences;
    }
    getSequenceByXY(x, y) {
        for (let s of [...this.flow.sequences, this.flow.endSequence, this.flow.errorSequence]) {
            // if (x > s.x && x < s.x + s.width && y > s.y && y < s.y + s.height)
            //     return s;
            let sequenceShape = HTMLUtilities_1.HTMLUtilities.getGeometry(s._id);
            if (sequenceShape) {
                if (x > s.x && x < s.x + sequenceShape.width && y > s.y && y < s.y + sequenceShape.height)
                    return s;
            }
        }
        return null;
    }
    purgeCandidateSequences() {
        this.syncCandidates();
        this.positionCandidateSequences(false);
    }
    getErrorSeqeuenceMainSize(sequence) {
        if (sequence.isCollapsed) {
            return {
                width: this.errorCollapsedWidth,
                height: this.collapsedHeight,
                fontSize: 16,
                title: {
                    color: FlowConstants_1.FlowConstants.ERROR_COLLAPSED_TITLE_COLOR,
                },
            };
        }
        return {
            width: FlowConstants_1.FlowConstants.DEFAULT_STACK_WIDTH,
            height: sequence.steps.length === 0 ? 100 : undefined,
            fontSize: 16,
            title: {
                color: FlowConstants_1.FlowConstants.ERROR_TITLE_COLOR,
            },
        };
    }
    getEndSequenceMainSize(sequence) {
        if (sequence.isCollapsed) {
            return {
                width: this.errorCollapsedWidth,
                height: this.collapsedHeight,
            };
        }
        return {
            width: FlowConstants_1.FlowConstants.DEFAULT_STACK_WIDTH,
            height: sequence.steps.length === 0 ? 100 : undefined,
        };
    }
    getPrimaryMainSize(sequence) {
        if (sequence.isCollapsed) {
            return {
                width: this.collapsedWidth,
                height: this.collapsedHeight,
            };
        }
        return {
            width: this.stackWidth,
            height: sequence.steps.length === 0 ? this.stackHeight : undefined,
        };
    }
    getSequenceMainSize(sequence) {
        // error stack common styles
        if (sequence.isError)
            return this.getErrorSeqeuenceMainSize(sequence);
        // end stack common styles
        if (sequence.isEnd)
            return this.getEndSequenceMainSize(sequence);
        //primary stack common styles
        if (sequence.isPrimary)
            return this.getPrimaryMainSize(sequence);
        if (sequence.isCollapsed) {
            return {
                width: this.collapsedWidth,
                height: this.collapsedHeight,
            };
        }
        return {
            width: this.stackWidth,
            height: sequence.steps.length === 0 ? this.stackHeight : undefined,
        };
    }
    // eslint-disable-next-line
    //    @LogTime()
    positionCandidateSequences(requirePurge = true) {
        let wasRepositioned = false;
        if (requirePurge) {
            wasRepositioned = this.syncCandidates();
        }
        // lookup position and set for instructions by sequence.
        for (let sequence of this.flow.sequences) {
            this.setCandidateDesiredPositionForSeqeuence(sequence);
        }
        // lookup position and set for all instructions
        // for (let inst of this.flow.getAlternateOutputPaths()) {
        // set candidate desired position by view mode.
        // this.displayBehavior.setCandidateDesiredPositionForStepStrategy(inst, this.flow);
        // let pos = HTMLUtilities.getGeometry(inst.getElementId(), FlowConstants.DESIGN_SURFACE_ID);
        // if (pos) {
        //     let insty = pos.top + 18 - (candidateStyles.height / 2);
        //     let instx= pos.left + FlowConstants.PATH_CANDIDATE_SHIFT;
        //     // when it's step for sequence strategy
        //     if (inst.stepId.endsWith('_end')) {
        //         insty = insty - 20;
        //         // let seq = this.flow.findSequenceByStepId(inst.stepId)
        //         // if not collapsed, set candidate for sequence strategy to bottom of sequence
        //         // otherwise, it's set side of sequence like as other candidate for normal step pathes.
        //         // if (!this.displayBehavior.isCollapsed(seq!)) {
        //         //     // for hidden step instruction only applied when expanded;
        //         //     insty = insty + FlowConstants.SEQUENCE_STRATEGY_Y_OFFSET;
        //         //     instx = instx - FlowConstants.SEQUENCE_STRATEGY_X_OFFSET;
        //         // }
        //     }
        //   //  inst.postionHistory.push({x: instx, y: insty, from: 'poll'});
        //     inst.candidateStackY = insty;
        //     inst.candidateStackX = instx;
        // }
        // }
        let workingSet = [];
        for (let realS of this.flow.candidateSequences) {
            let geo = HTMLUtilities_1.HTMLUtilities.getGeometry(realS.getElementId());
            if (!geo) {
                // todo: need to get width and height from display behavior
                geo = new HTMLUtilities_1.HTMLShapeGeometry(realS.desiredY, realS.desiredX, FlowConstants_1.FlowConstants.PATH_CANDIDATE_HEIGHT, FlowConstants_1.FlowConstants.PATH_CANDIDATE_WIDTH);
            }
            else {
                geo.left = realS.desiredX;
                geo.top = realS.desiredY;
            }
            geo.bottomPadding = 5;
            workingSet.push(new FlowEditContext_PositionData_1.PositionData(geo, false, true, realS, realS.x, realS.y));
        }
        // add real sequences to this
        for (let realS of this.flow.sequences) {
            let geo = HTMLUtilities_1.HTMLUtilities.getGeometry(realS.getElementId());
            if (!geo) {
                // todo: need to get width and height from display behavior
                geo = new HTMLUtilities_1.HTMLShapeGeometry(realS.x, this.getSequenceY(realS), this.getSequenceMainSize(realS).width, this.getSequenceMainSize(realS).height || FlowConstants_1.FlowConstants.DEFAULT_STACK_HEIGHT);
            }
            geo.topPadding = FlowConstants_1.FlowConstants.TITLE_AREA_HEIGHT;
            geo.bottomPadding = this.getSequenceExtraSize(realS).height || 0;
            geo.rightPadding = this.getSequenceExtraSize(realS).width;
            geo.top = realS.desiredY;
            geo.left = realS.desiredX;
            workingSet.push(new FlowEditContext_PositionData_1.PositionData(geo, false, false, realS, realS.x, this.getSequenceY(realS)));
            if (geo) {
                realS.height = geo.height;
            }
        }
        for (let candS of workingSet) {
            candS.sequence.reset();
        }
        // sort working set
        workingSet = workingSet.sort((a, b) => {
            // sort real above candidates
            if (a.isCandidate !== b.isCandidate) {
                if (a.isCandidate)
                    return 1;
                else
                    return -1;
            }
            if (a.shape.top + a.shape.left > b.shape.top + b.shape.left) {
                return 1;
            }
            else {
                return -1;
            }
        });
        for (let positionThis of workingSet) {
            // find any that are in vertical range
            let consider = [];
            // console.log('positioning', positionThis)
            for (let otherPostion of workingSet) {
                if (!otherPostion.positioned)
                    continue;
                if (positionThis.inRange(otherPostion))
                    consider.push(otherPostion);
            }
            // position so its missed
            FlowEditContext_PositionData_1.PositionData.positionOneSequence(positionThis, consider);
        }
        if (wasRepositioned)
            return true;
        for (let o of workingSet) {
            if (o.initialX !== o.sequence.x || o.initialY !== o.sequence.y) {
                return true;
            }
        }
        return false;
    }
    isDragOver(id) {
        return this.dragOverSequenceId === id;
    }
    canCombine(combine, withSequence) {
        // todo: fix this
        // if (combine instanceof CandidateSequence) {
        //
        //     // ui should not allow this
        //     if (step.sequence?._id === withSequence._id)
        //         return false;
        // }
        if (combine instanceof CandidateSequence_1.CandidateSequence) {
            let sequence = this.flow.findSequenceByStepId(combine.instruction.stepId);
            if (sequence) {
                // ui should not allow this
                if (sequence?._id === withSequence._id)
                    return false;
                return this.flow.canLink(sequence, withSequence);
            }
        }
        else if (combine instanceof FlowStepSequence_1.FlowStepSequence) {
            return this.flow.canLink(combine, withSequence);
        }
        return true;
    }
    combineSequences(combine, withSequence) {
        // ui should not allow this
        if (!this.canCombine(combine, withSequence)) {
            this.notification = {
                message: "You can not link to this sequence.",
                onSuccess: () => {
                },
            };
            return;
        }
        if (withSequence instanceof CandidateSequence_1.CandidateSequence) {
            throw new Error("Can not combine / link the candidate sequences");
        }
        else if (combine instanceof CandidateSequence_1.CandidateSequence && combine.instruction) {
            // linking
            let step = this.flow.find(combine.instruction.stepId);
            let inst = step.findOutputInstruction(combine.instruction.pathName);
            if (!inst)
                throw new Error("instruction not found");
            inst.connectedSequenceId = withSequence._id;
            StateManager_1.StateManager.changed(inst);
            // remove candidate sequence
            this.flow.candidateSequences = this.flow.candidateSequences.filter((c) => c._id !== combine._id);
            this.refreshSequences();
        }
        else if (combine instanceof FlowStepSequence_1.FlowStepSequence) {
            // combining
            for (let s of combine.steps) {
                this.flow.moveToSequence(s, combine, withSequence);
            }
            for (let seq of this.flow.sequences) {
                if (seq._id === combine._id)
                    continue;
                for (let s of seq.steps) {
                    for (let ins of s.getOutcomeInstructions()) {
                        if (ins.connectedSequenceId === combine._id &&
                            ins.strategy === FlowStepOutputInstructions_1.FlowStepOutputInstructionType.BRANCH) {
                            ins.connectedSequenceId = withSequence._id;
                        }
                    }
                }
            }
            // delete combine
            let idx = this.flow.sequences.indexOf(combine);
            this.deleteSequence(idx);
            this.refreshSequences();
        }
    }
    onCopy(selectedId) {
        let elem = this._lastSelectionElement;
        if (selectedId) {
            elem = this.flow.find(selectedId);
            this.contextControl = null;
        }
        if (!elem)
            return;
        if (elem instanceof FlowConfiguration_1.FlowConfiguration) {
            // do nothing
        }
        else if (elem instanceof FlowStepSequence_1.FlowStepSequence && !elem.canCopy) {
            this.notification = {
                message: "You can not copy this sequence",
                onSuccess: () => {
                },
            };
        }
        else {
            this.clipboardElement = this.cloneFlowElement(elem);
        }
    }
    onCut(selectedId) {
        let elem = this._lastSelectionElement;
        if (selectedId) {
            elem = this.flow.find(selectedId);
            this.contextControl = null;
        }
        if (!elem)
            return;
        if (elem instanceof FlowStepSequence_1.FlowStepSequence) {
            if (!elem.canCopy) {
                this.notification = {
                    message: "You can not copy this sequence",
                    onSuccess: () => {
                    },
                };
                return;
            }
            let idx = this.flow.sequences.indexOf(elem);
            if (idx > 0) {
                if (elem.steps.length > 0) {
                    this.notification = {
                        message: "This sequence has the steps. Do you want to cut it really?",
                        onSuccess: () => {
                            this.clipboardElement = this.cloneFlowElement(elem);
                            this.deleteSequence(idx);
                        },
                        onCancel: () => {
                        },
                    };
                }
                else {
                    this.deleteSequence(idx);
                }
            }
            else {
                this.notification = {
                    message: "Primary Stack can not be cut. But it's copied to clipboarded",
                    onSuccess: () => {
                    },
                };
            }
        }
        else {
            this.clipboardElement = this.cloneFlowElement(elem);
            this.flow.remove(elem);
        }
    }
    deleteSequence(idx) {
        this.flow.deleteSequenceByIndex(idx);
        StateManager_1.StateManager.propertyChanged(this.flow, FlowConfiguration_1.FlowConfiguration.SEQUENCES);
        this.purgeCandidateSequences();
    }
    onDelete(selectedId) {
        let elem = this._lastSelectionElement;
        if (selectedId) {
            elem = this.flow.find(selectedId);
            this.contextControl = null;
        }
        if (!elem)
            return;
        if (elem instanceof FlowStepSequence_1.FlowStepSequence) {
            if (!elem.canDelete) {
                this.notification = {
                    message: "You can not delete this sequence",
                    onSuccess: () => {
                    },
                };
                return;
            }
            let idx = this.flow.sequences.indexOf(elem);
            if (idx > 0) {
                if (elem.steps.length > 0) {
                    this.notification = {
                        message: "This sequence has the steps. If you delete this, you will lost all data. it's okay?",
                        onSuccess: () => {
                            this.deleteSequence(idx);
                        },
                        onCancel: () => {
                        },
                    };
                }
                else {
                    this.deleteSequence(idx);
                }
            }
            else {
                this.notification = {
                    message: "Primary Stack can not be deleted.",
                    onSuccess: () => {
                    },
                };
            }
        }
        else {
            this.flow.remove(elem);
            this.purgeCandidateSequences();
        }
    }
    onPaste() {
        if (!this.clipboardElement || (!this.selectionElement && !(this.clipboardElement instanceof FlowStepSequence_1.FlowStepSequence)))
            return;
        if (this.clipboardElement instanceof FlowStepSequence_1.FlowStepSequence) {
            let newSeq = this.cloneFlowElement(this.clipboardElement);
            newSeq._id = DataUtilities_1.DataUtilities.generateUniqueId();
            newSeq.desiredY += 20;
            newSeq.desiredX += 20;
            newSeq.x += 20;
            newSeq.y += 20;
            this.flow.addSequence(newSeq);
        }
        else if (!(this.clipboardElement instanceof FlowStepSequence_1.FlowStepSequence) &&
            !(this.selectionElement instanceof FlowStepSequence_1.FlowStepSequence) &&
            this.selectionElement) {
            for (let s of this.flow.sequences) {
                let idx = s.steps.indexOf(this.selectionElement);
                if (idx >= 0) {
                    let elem = this.cloneFlowElement(this.clipboardElement);
                    elem._id = DataUtilities_1.DataUtilities.generateUniqueId();
                    this.flow.add(elem, s, idx);
                    break;
                }
            }
        }
    }
    setSelection(selection) {
        this._selectionElement = selection;
        StateManager_1.StateManager.changed(selection);
        if (this._lastSelectionElement) {
            StateManager_1.StateManager.changed(this._lastSelectionElement);
        }
        this._lastSelectionElement = selection;
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.SELECTION_ELEMENT);
        this.showEditLayer();
    }
    clearSelection() {
        this._selectionElement = undefined;
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.SELECTION_ELEMENT);
        this.hideEditLayer();
    }
    addStepToCandidate(step, candidate) {
        let s = candidate.createSequence();
        let instruction = Reflect.get(candidate, "instruction");
        if (instruction) {
            // hook the paths together
            if (instruction.pathName && instruction.stepId) {
                instruction.connectedSequenceId = s._id;
            }
        }
        this.flow.addSequence(s);
        s.strategy = FlowSequenceCompleteStrategy_1.FlowSequenceCompleteStrategy.END_FLOW;
        s.addStep(step);
    }
    moveStepToCandidate(step, sequence, candidate) {
        if (!this.flow.canMoveToSequence(step, candidate)) {
            throw new Error("You can not move this step");
        }
        sequence.removeStep(step);
        this.addStepToCandidate(step, candidate);
    }
    toggleEditLayer() {
        this.isShowEditor = !this.isShowEditor;
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.IS_SHOW_EDITOR);
    }
    hideEditLayer() {
        this.isShowEditor = false;
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.IS_SHOW_EDITOR);
    }
    showEditLayer() {
        this.isShowEditor = true;
        StateManager_1.StateManager.propertyChanged(this, FlowEditContext.IS_SHOW_EDITOR);
    }
    refresh() {
        if (this.flowEditor) {
            StateManager_1.StateManager.changed(this);
            StateManager_1.StateManager.changed(this.flow);
        }
    }
    setSelectedStepStrategy(elem, step) {
        let elemGeo = HTMLUtilities_1.HTMLUtilities.getGeometryFromElement(elem, FlowConstants_1.FlowConstants.DESIGN_SURFACE_ID);
        this.selectedStepStrategy = {
            position: {
                x: elemGeo?.left || 0,
                y: elemGeo?.top || 0,
            },
            step,
        };
    }
    setSelectedSequenceStrategy(elem, sequence) {
        let elemGeo = HTMLUtilities_1.HTMLUtilities.getGeometryFromElement(elem, FlowConstants_1.FlowConstants.DESIGN_SURFACE_ID);
        this.selectedSequenceStrategy = {
            position: {
                x: elemGeo?.left || 0,
                y: elemGeo?.top || 0,
            },
            sequence,
        };
    }
    getEndFlowConnections() {
        let conn = [];
        // showErrorOrEndConnections is set END FLOW or end stack is expanded.
        if (this.showErrorOrEndConnections === FlowStepOutputInstructions_1.FlowStepOutputInstructionType.END_FLOW ||
            !this.flow.endSequence.isCollapsed ||
            this.isShowErrorBranch) {
            for (let s of this.flow.sequences) {
                for (let step of [...s.steps, s.endStep]) {
                    step.getOutcomeInstructions().forEach((ins) => {
                        if (ins.strategy === FlowStepOutputInstructions_1.FlowStepOutputInstructionType.END_FLOW) {
                            let fromStep = this.flow.find(ins.stepId);
                            if (fromStep) {
                                conn.push(new FlowExtraConnection_1.FlowExtraConnection(ins.getElementId(), this.flow.endSequence._id, fromStep, ins));
                            }
                        }
                    });
                }
            }
        }
        return conn;
    }
    getErrorFlowConnections() {
        let conn = [];
        // showErrorOrEndConnections is set THROW or error stack is expanded.
        if (this.showErrorOrEndConnections === FlowStepOutputInstructions_1.FlowStepOutputInstructionType.THROW_EXCEPTION ||
            !this.flow.errorSequence.isCollapsed ||
            this.isShowErrorBranch) {
            for (let s of this.flow.sequences) {
                for (let step of [...s.steps, s.endStep]) {
                    step.getOutcomeInstructions().forEach((ins) => {
                        if (ins.strategy === FlowStepOutputInstructions_1.FlowStepOutputInstructionType.THROW_EXCEPTION) {
                            let fromStep = this.flow.find(ins.stepId);
                            if (fromStep) {
                                conn.push(new FlowExtraConnection_1.FlowExtraConnection(ins.getElementId(), this.flow.errorSequence._id, fromStep, ins));
                            }
                        }
                    });
                }
            }
        }
        return conn;
    }
    setSelectedSequenceForError(elem, sequence) {
        let elemGeo = HTMLUtilities_1.HTMLUtilities.getGeometryFromElement(elem, FlowConstants_1.FlowConstants.DESIGN_SURFACE_ID);
        this.selectedSequenceForError = {
            position: {
                x: sequence.x,
                y: (elemGeo?.top || 0) + 15,
            },
            sequence,
        };
    }
    setSelectedForColor(sequence, element) {
        let pos = HTMLUtilities_1.HTMLUtilities.getGeometryFromElement(element, FlowConstants_1.FlowConstants.DESIGN_SURFACE_ID);
        this.selectedForColor = {
            instance: sequence,
            position: {
                x: (pos?.left || 0) + 24,
                y: pos?.top || 0,
            },
        };
    }
    isDraggingOverSequence(sequence) {
        let ret = !!(this.draggingControl &&
            this.draggingControl.destination &&
            this.draggingControl.destination === sequence._id);
        return ret;
    }
    setCandidateDesiredPositionForSeqeuence(sequence) {
        // when sequence is expanded, we need to set the disired position of candidates by instruction.
        if (!sequence.isCollapsed) {
            for (let inst of sequence.instructions) {
                this.setCandidateDesiredPositionForStepStrategy(inst);
            }
        }
        // when sequenece is collapsed, we need to set the disired position of candidates by sequence and index
        else {
            let pos = HTMLUtilities_1.HTMLUtilities.getGeometry(sequence._id, FlowConstants_1.FlowConstants.DESIGN_SURFACE_ID);
            if (pos) {
                let idx = 0;
                for (let inst of sequence.instructions) {
                    // for hidden step
                    if (inst.stepId.endsWith("_end")) {
                        this.setCandidateDesiredPositionForSequenceStrategy(inst);
                        continue;
                    }
                    let c = this.flow.getCandidateOrRealSequence(inst.connectedSequenceId);
                    if (c instanceof CandidateSequence_1.CandidateSequence) {
                        let insty = pos.top + idx * this.getCandidateCommonStyles().height + 10;
                        let instx = pos.left + pos.width + this.pathCandidateShift;
                        inst.candidateStackY = insty;
                        inst.candidateStackX = instx;
                        idx += 1;
                    }
                }
            }
        }
    }
    getCandidateCommonStyles() {
        return {
            width: this.candidateWidth,
            height: this.candidateHeight,
            padding: this.candidatePadding,
            fontSize: this.candidateFontSize,
            dragging: {
                width: this.candidateDraggingWidth,
                height: this.candidateDraggingHeight,
            },
        };
    }
    setCandidateDesiredPositionForSequenceStrategy(inst) {
        let seq = this.flow.findSequenceByStepId(inst.stepId);
        if (!seq)
            return;
        let pos = HTMLUtilities_1.HTMLUtilities.getGeometry(seq._id, FlowConstants_1.FlowConstants.DESIGN_SURFACE_ID);
        if (pos) {
            // set center below sequence.
            let instx = pos.left + pos.width / 2 - this.getCandidateCommonStyles().width / 2;
            let insty = pos.top + pos.height + this.sequenceCandidateShift;
            inst.candidateStackY = insty;
            inst.candidateStackX = instx < 0 ? 0 : instx;
        }
    }
    setCandidateDesiredPositionForStepStrategy(inst) {
        // if it's for sequence strategy
        let step = this.flow.find(inst.stepId);
        if (step instanceof FlowStepData_1.FlowStepData && FlowUtilities_1.FlowUtilities.IsEndStep(step)) {
            this.setCandidateDesiredPositionForSequenceStrategy(inst);
        }
        else {
            let pos = HTMLUtilities_1.HTMLUtilities.getGeometry(inst.getElementId(), FlowConstants_1.FlowConstants.DESIGN_SURFACE_ID);
            if (pos) {
                let insty = pos.top + 18 - this.getCandidateCommonStyles().height / 2;
                let instx = pos.left + this.pathCandidateShift;
                inst.candidateStackY = insty;
                inst.candidateStackX = instx;
            }
        }
    }
    getSequenceExtraSize(sequence) {
        return {
            width: 0,
            height: sequence.strategy === FlowSequenceCompleteStrategy_1.FlowSequenceCompleteStrategy.LINK ? 0 : FlowConstants_1.FlowConstants.FLOW_CONNECT_AREA_HEIGHT,
        };
    }
    delayPosition(alwaysRefresh = false) {
        ReactRenderHook_1.ReactRenderHook.registerCallback("position", () => {
            if (this.positionCandidateSequences(true)) {
                this.refreshSequences();
            }
            if (alwaysRefresh)
                this.refreshSequences();
        });
    }
    //@LogTime()s
    syncCandidates() {
        let sequenceIds = this.flow.sequences.map((s) => s._id);
        let wasChanged = false;
        // remove the candidate that has same id with sequence.
        this.flow.candidateSequences = this.flow.candidateSequences.filter((c) => {
            if (sequenceIds.indexOf(c._id) < 0) {
                let instruction = Reflect.get(c, "instruction");
                //                console.log('inst ' + instruction);
                if (instruction) {
                    if (instruction.connectedSequenceId !== c._id) {
                        wasChanged = true;
                        return false;
                    }
                    if (!instruction.stepId) {
                        wasChanged = true;
                        // path declares no step
                        return false;
                    }
                    let step = this.flow.find(instruction.stepId);
                    // step still exists
                    if (!step) {
                        wasChanged = true;
                        return false;
                    }
                    // candidate declares no path name
                    if (!instruction.pathName || instruction.pathName === "") {
                        wasChanged = true;
                        return false;
                    }
                    // is outcome the same
                    if (!step.isCurrentOutcome(instruction.pathName)) {
                        wasChanged = true;
                        return false;
                    }
                    // its not set to branch
                    if (instruction.strategy !== FlowStepOutputInstructions_1.FlowStepOutputInstructionType.BRANCH) {
                        wasChanged = true;
                        return false;
                    }
                    return true;
                }
                else {
                    // this is a valid one
                    return true;
                }
            }
            else {
                wasChanged = true;
                return false;
            }
        });
        // add missing sequences
        for (let seq of this.flow.sequences) {
            for (let step of [...seq.steps, seq.endStep]) {
                let paths = [...step.getOutcomeInstructions(), ...seq.instructions];
                if (paths && paths.length > 0) {
                    for (let inst of paths) {
                        if (inst.strategy === FlowStepOutputInstructions_1.FlowStepOutputInstructionType.BRANCH && inst.connectedSequenceId) {
                            if (!this.flow.getCandidateOrRealSequence(inst.connectedSequenceId)) {
                                // its missing, we need to add
                                let cs = new CandidateSequence_1.CandidateSequence(inst);
                                cs._id = inst.connectedSequenceId;
                                this.flow.candidateSequences.push(cs);
                                this.flow.invalidateNodes();
                                // mark as changed
                                wasChanged = true;
                            }
                        }
                    }
                }
            }
        }
        return wasChanged;
    }
    cloneFlowElement(s) {
        let val;
        if (s instanceof FlowStepSequence_1.FlowStepSequence) {
            val = new FlowStepSequence_1.FlowStepSequence();
            DataUtilities_1.DataUtilities.spreadDataWithoutFunction(val, DataUtilities_1.DataUtilities.clone(s), [
                "_id",
                "_steps",
                "_hiddenStep",
                "_strategy",
            ]);
            for (let step of s.steps) {
                val.addStep(this.cloneFlowElement(step));
            }
            val.strategy = FlowSequenceCompleteStrategy_1.FlowSequenceCompleteStrategy.END_FLOW;
            // copying the sequence strategy.
            // val.strategy = s.strategy;
            // let fromInst = s.hiddenStep.getOutcomeInstructions()[0];
            // let toInst = val.hiddenStep.getOutcomeInstructions()[0]
            // toInst.errorMessage = fromInst.errorMessage;
            // if (s.strategy === FlowStepSequenceStrategy.LINK) {
            //     if (fromInst.connectedSequenceId) {
            //         let s = this.getCandidateOrRealSequence(fromInst.connectedSequenceId);
            //         if (s instanceof FlowStepSequence) {
            //             toInst.connectedSequenceId = s._id;
            //         } else {
            //             toInst.connectedSequenceId = DataUtilities.generateUniqueId();
            //         }
            //     }
            // }
            return val;
        }
        else if (s instanceof FlowStepData_1.FlowStepData) {
            let registeredData = RegisterFlowStepData_1.FlowStepDataRegistration.getByTypeName(s.__type);
            let data = registeredData.create();
            DataUtilities_1.DataUtilities.spreadDataWithoutFunction(data, DataUtilities_1.DataUtilities.clone(s), [
                "_id",
                "_nonDefaultOutputInstructions",
            ]);
            let paths = s.getOutcomes();
            if (paths) {
                for (let i of paths) {
                    data.findOutputInstruction(i.name);
                }
            }
            return data;
        }
        else {
            throw new Error("Unknown element type");
        }
    }
}
tslib_1.__decorate([
    AutoBind_1.AutoBind
], FlowEditContext.prototype, "flowChanged", null);
tslib_1.__decorate([
    AutoBind_1.AutoBind
], FlowEditContext.prototype, "flowSequenceChanged", null);
tslib_1.__decorate([
    AutoBind_1.AutoBind
], FlowEditContext.prototype, "onCopy", null);
tslib_1.__decorate([
    AutoBind_1.AutoBind
], FlowEditContext.prototype, "onCut", null);
tslib_1.__decorate([
    AutoBind_1.AutoBind
], FlowEditContext.prototype, "deleteSequence", null);
tslib_1.__decorate([
    AutoBind_1.AutoBind
], FlowEditContext.prototype, "onDelete", null);
tslib_1.__decorate([
    AutoBind_1.AutoBind
], FlowEditContext.prototype, "onPaste", null);
tslib_1.__decorate([
    AutoBind_1.AutoBind
], FlowEditContext.prototype, "toggleEditLayer", null);
tslib_1.__decorate([
    AutoBind_1.AutoBind
], FlowEditContext.prototype, "hideEditLayer", null);
tslib_1.__decorate([
    AutoBind_1.AutoBind
], FlowEditContext.prototype, "showEditLayer", null);
tslib_1.__decorate([
    AutoBind_1.AutoBind
], FlowEditContext.prototype, "setSelectedStepStrategy", null);
tslib_1.__decorate([
    AutoBind_1.AutoBind
], FlowEditContext.prototype, "setSelectedSequenceStrategy", null);
tslib_1.__decorate([
    AutoBind_1.AutoBind
], FlowEditContext.prototype, "setSelectedSequenceForError", null);
tslib_1.__decorate([
    AutoBind_1.AutoBind
], FlowEditContext.prototype, "cloneFlowElement", null);
exports.FlowEditContext = FlowEditContext;
function RenderFlowSettingsEditor(props) {
    const [showMapping, setShowMapping] = (0, react_1.useState)(false);
    let options = [
        { value: FlowConfiguration_1.FlowOutputType.NODATA, text: "No Output" },
        { value: FlowConfiguration_1.FlowOutputType.ADDEDDATA, text: "Added Data" },
        { value: FlowConfiguration_1.FlowOutputType.ALLDATA, text: "All Data" },
        { value: FlowConfiguration_1.FlowOutputType.DEFINED, text: "Define Outputs" },
    ];
    return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(ObserveState_1.ObserveState, { listenTo: props.flowConfig, properties: [FlowConfiguration_1.FlowConfiguration.OUTPUT_STRATEGY], control: () => {
                return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(UILabel_1.UILabel, { children: "Flow Outputs" }), (0, jsx_runtime_1.jsx)(UIToggleButton_1.UIToggleButton, { value: props.flowConfig.defineOutputs, options: options, onChange: (newValue) => {
                                // @ts-ignore
                                props.flowConfig.defineOutputs = newValue;
                            } }), props.flowConfig.getExecutionResult().fields.length !== 0 && ((0, jsx_runtime_1.jsx)(UIButton_1.UIButton, { onClick: () => setShowMapping(true), children: "Edit Result Mapping" })), (0, jsx_runtime_1.jsx)(FlowMappingLayer_1.FlowMappingLayer, { flow: props.flowConfig, open: showMapping, onComplete: () => setShowMapping(false) })] }));
            } }) }));
}
//# sourceMappingURL=FlowEditContext.js.map