"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FlowSequenceStack = void 0;
const tslib_1 = require("tslib");
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = tslib_1.__importDefault(require("react"));
const react_beautiful_dnd_1 = require("react-beautiful-dnd");
const react_draggable_1 = tslib_1.__importDefault(require("react-draggable"));
const styled_components_1 = tslib_1.__importDefault(require("styled-components"));
const FlowStepSequence_1 = require("@appglue/common/dist/Flow/Structure/FlowStepSequence");
const StateManager_1 = require("@appglue/common/dist/Common/StateManager");
const FlowEditContext_1 = require("../FlowEditContext");
const movement_white_svg_1 = tslib_1.__importDefault(require("../../assets/images/icons/movement_white.svg"));
const FlowStepOutputInstructions_1 = require("@appglue/common/dist/Flow/Structure/FlowStepOutputInstructions");
const ObserveState_1 = require("../../CommonUI/StateManagement/ObserveState");
const FlowConstants_1 = require("@appglue/common/dist/Flow/Utilities/FlowConstants");
const RenderSequenceStrategy_1 = require("./CommonRender/RenderSequenceStrategy");
const RenderSequenceContent_1 = require("./CommonRender/RenderSequenceContent");
const RenderSequenceActions_1 = require("./CommonRender/RenderSequenceActions");
const RenderSequenceTitle_1 = require("./CommonRender/RenderSequenceTitle");
const material_1 = require("@mui/material");
const FlowStepSequenceType_1 = require("@appglue/common/dist/Flow/Structure/FlowStepSequenceType");
const UIStyleConstants_1 = require("@appglue/common/dist/Common/UIStyleConstants");
const RenderCollapsedStack_1 = require("./CommonRender/RenderCollapsedStack");
const ExpressionIcon_1 = require("../../CommonUI/Icon/ExpressionIcon");
const ExpressionEditLayer_1 = require("../../Expressions/ExpressionEditLayer");
const FlowSequenceDiv = (0, styled_components_1.default)("div") `
    ${(props) => !props.isDisabledDragging &&
    `
            top: ${props.isDragging ? 0 : props.position.y}px;
            left: ${props.isDragging ? 0 : props.position.x}px;
            position: absolute;
	    `}

    margin-bottom: 10px;
    padding: ${(props) => props.padding};
    background: transparent;

    box-sizing: border-box;
    border-radius: 7px;
    min-width: ${(props) => props.size.width}px;

    ${(props) => `border: 2px solid ${props.borderColor};`}
    ${(props) => (!props.isDragging ? `transform: none !important;` : `z-index: 1;`)}
  > div.stack {
        border-radius: 4px;
        position: relative;
        padding: 8px 12px 6px;
        background: ${(props) => props.background};

        ${(props) => !props.isDisabledDragging &&
    props.isDragging &&
    `
			&.stack-move {
				cursor: url(${movement_white_svg_1.default}), auto;
			}
		`}
    }

    .stack-actions {
        position: absolute;
        right: 5px;
        top: -40px;
        padding-bottom: 20px;

        .button-group {
            opacity: ${(props) => (props.selected ? 1 : 0)};
            transition: opacity 0.1s;

            border: 1px solid #f1f1f6;
            box-sizing: border-box;
            border-radius: 4px;
            display: flex;
        }
    }

    &:hover .stack-actions .button-group {
        opacity: 1;
    }
`;
class FlowSequenceStack extends react_1.default.Component {
    containerRef = react_1.default.createRef();
    constructor(props) {
        super(props);
        this.state = {
            isDragging: false,
            openExpression: false,
        };
    }
    static getEndSequenceTitleStyle(sequence) {
        if (sequence.isCollapsed) {
            return {
                color: FlowConstants_1.FlowConstants.END_COLLAPSED_TITLE_COLOR,
            };
        }
        return {
            color: FlowConstants_1.FlowConstants.END_TITLE_COLOR,
        };
    }
    static getPrimarySequenceTitleStyle() {
        return {
            color: FlowConstants_1.FlowConstants.PRIMARY_TITLE_COLOR,
        };
    }
    static getErrorSequenceTitleStyle(sequence) {
        if (sequence.isCollapsed) {
            return {
                color: FlowConstants_1.FlowConstants.ERROR_COLLAPSED_TITLE_COLOR,
            };
        }
        return {
            color: FlowConstants_1.FlowConstants.ERROR_TITLE_COLOR,
        };
    }
    static getSequenceTitleStyle(sequence) {
        // error stack common styles
        if (sequence.isError)
            return this.getErrorSequenceTitleStyle(sequence);
        // end stack common styles
        if (sequence.isEnd)
            return this.getEndSequenceTitleStyle(sequence);
        //primary stack common styles
        if (sequence.isPrimary)
            return this.getPrimarySequenceTitleStyle();
        return {
            color: FlowConstants_1.FlowConstants.DEFAULT_TITLE_COLOR,
        };
    }
    getDefaultPosition = () => {
        return {
            x: this.props.sequence.x,
            y: this.props.editContext.getSequenceY(this.props.sequence),
        };
    };
    dragDropAction = (data, isCombining = false) => {
        this.props.editContext.dragOverSequence = null;
        this.props.sequence.desiredX = data.x;
        this.props.sequence.desiredY = data.y;
        if (!isCombining) {
            StateManager_1.StateManager.propertyChanged(this.props.sequence, FlowStepSequence_1.FlowStepSequence.MOVED);
        }
        this.setState({
            isDragging: false,
        });
    };
    onDragStop = (_e, data) => {
        let sequence = this.props.editContext.getSequenceByXY(data.x, data.y);
        if (sequence) {
            this.props.editContext.dragOverSequence = sequence;
            this.props.editContext.notification = {
                message: "Do you really want to combine these stacks?",
                onSuccess: () => {
                    this.props.editContext.notification = undefined;
                    this.dragDropAction(data, true);
                    this.props.editContext.combineSequences(this.props.sequence, sequence);
                },
                onCancel: () => {
                    this.props.editContext.notification = undefined;
                    this.dragDropAction(data);
                },
            };
        }
        else {
            this.props.editContext.dragOverSequence = null;
            this.dragDropAction(data);
        }
        StateManager_1.StateManager.propertyChanged(this.props.sequence, FlowStepSequence_1.FlowStepSequence.DRAG_END);
    };
    // eslint-disable-next-line
    onDragStart = (_e, _data) => {
        this.props.editContext.clearSelection();
        this.setState({
            isDragging: true,
        });
        StateManager_1.StateManager.propertyChanged(this.props.sequence, FlowStepSequence_1.FlowStepSequence.DRAG_START);
    };
    onDrag = (_e, data) => {
        this.props.sequence.desiredX = data.x;
        this.props.sequence.desiredY = data.y;
        let sequence = this.props.editContext.getSequenceByXY(data.x, data.y);
        if (sequence) {
            this.props.editContext.dragOverSequence = sequence;
        }
        else {
            this.props.editContext.dragOverSequence = null;
        }
        StateManager_1.StateManager.propertyChanged(this.props.sequence, FlowStepSequence_1.FlowStepSequence.DRAG_OVER);
    };
    onSelectSequence = (e) => {
        e.stopPropagation();
        // end / error stacks can not be selected and skip when reordering the steps.
        let isReordering = Reflect.apply(Reflect.get(e.target, "getAttribute"), e.target, ["data-rbd-droppable-id"]);
        if (this.props.sequence.isNormal && !isReordering) {
            this.props.editContext.setSelection(this.props.sequence);
        }
    };
    onMouseDown = () => {
        if (this.props.sequence.isError) {
            this.props.editContext.showErrorOrEndConnections = FlowStepOutputInstructions_1.FlowStepOutputInstructionType.THROW_EXCEPTION;
        }
        else if (this.props.sequence.isEnd) {
            this.props.editContext.showErrorOrEndConnections = FlowStepOutputInstructions_1.FlowStepOutputInstructionType.END_FLOW;
        }
    };
    onMouseUp = () => {
        if (this.props.sequence.isError || this.props.sequence.isEnd) {
            this.props.editContext.showErrorOrEndConnections = null;
        }
    };
    isEnabledPlaceholderWhileDrop(sequence) {
        // no need animation for collapsed and no steps sequence.
        return sequence.steps.length > 0 && !sequence.isCollapsed;
    }
    getSequenceBorderColor(sequence) {
        if (this.props.editContext.selection === sequence._id) {
            return FlowConstants_1.FlowConstants.SELECTED_STACK_COLOR;
        }
        if (sequence.getValidationIssues().length) {
            return FlowConstants_1.FlowConstants.ERROR_STACK_COLOR;
        }
        // While step is dragging over on collapsed sequence..
        if (this.props.editContext.isDraggingOverSequence(sequence) && !this.isEnabledPlaceholderWhileDrop(sequence)) {
            return FlowConstants_1.FlowConstants.SSS_STEP_DROP_OVER_BORDER_COLOR;
        }
        return "transparent";
    }
    getSequenceBackgroundColor(sequence) {
        // background color when candidate or stepsequence is dragging over on this sequence.
        if (this.props.editContext.isDragOver(sequence._id)) {
            return FlowConstants_1.FlowConstants.OVER_SEQUENCE_COLOR;
        }
        return sequence.color;
    }
    render() {
        return ((0, jsx_runtime_1.jsx)(ObserveState_1.ObserveState, { listenTo: this.props.editContext, properties: [FlowEditContext_1.FlowEditContext.DRAG_OVER_SEQUENCE], control: () => {
                return ((0, jsx_runtime_1.jsx)(react_draggable_1.default, { disabled: this.props.sequence.isPrimary || !this.props.sequence.isNormal, defaultPosition: this.getDefaultPosition(), position: this.getDefaultPosition(), onStop: this.onDragStop, onStart: this.onDragStart, onDrag: this.onDrag, handle: `.stack-move`, cancel: ".inline-editor", nodeRef: this.containerRef, children: this.props.sequence.sequenceType === FlowStepSequenceType_1.FlowStepSequenceType.BRANCH_MERGE
                        ? this.RenderBranchStack()
                        : this.RenderNormalStack() }));
            } }));
    }
    RenderNormalStack() {
        return ((0, jsx_runtime_1.jsx)(FlowSequenceDiv, { id: this.props.sequence.getElementId(), padding: "4px", size: this.props.editContext.getSequenceMainSize(this.props.sequence), background: this.getSequenceBackgroundColor(this.props.sequence), position: this.getDefaultPosition(), isDragging: this.state.isDragging, isDisabledDragging: !this.props.sequence.isNormal, selected: this.props.editContext.selection === this.props.sequence._id, onContextMenu: (e) => {
                e.preventDefault();
                this.props.editContext.contextControl = {
                    selectedId: this.props.sequence._id,
                    mouseX: e.clientX,
                    mouseY: e.clientY,
                };
            }, onClick: this.onSelectSequence, borderColor: this.getSequenceBorderColor(this.props.sequence), ref: this.containerRef, children: (0, jsx_runtime_1.jsxs)(material_1.Box, { className: "stack", onMouseDown: this.onMouseDown, onMouseUp: this.onMouseUp, onMouseLeave: this.onMouseUp, display: "flex", children: [this.RenderLoopBack(), (0, jsx_runtime_1.jsxs)(material_1.Box, { width: "100%", children: [(0, jsx_runtime_1.jsx)(RenderSequenceTitle_1.RenderSequenceTitle, { sequence: this.props.sequence }), (0, jsx_runtime_1.jsx)("div", { className: "stack-actions", children: (0, jsx_runtime_1.jsx)("div", { className: "button-group", children: (0, jsx_runtime_1.jsx)(RenderSequenceActions_1.RenderSequenceActions, { editContext: this.props.editContext, sequence: this.props.sequence }) }) }), (0, jsx_runtime_1.jsx)(react_beautiful_dnd_1.Droppable, { droppableId: this.props.sequence._id, direction: "vertical", children: (provided, _snapshot) => {
                                    return ((0, jsx_runtime_1.jsxs)("div", { ...provided.droppableProps, ref: provided.innerRef, children: [(0, jsx_runtime_1.jsx)(RenderSequenceContent_1.RenderSequenceContent, { sequence: this.props.sequence, editContext: this.props.editContext, flow: this.props.flow }), (0, jsx_runtime_1.jsx)("div", { style: {
                                                    display: this.isEnabledPlaceholderWhileDrop(this.props.sequence)
                                                        ? "block"
                                                        : "none",
                                                }, children: provided.placeholder })] }));
                                } }), (0, jsx_runtime_1.jsx)(ObserveState_1.ObserveState, { properties: [FlowStepSequence_1.FlowStepSequence.STRATEGY], listenTo: this.props.editContext, control: () => {
                                    return ((0, jsx_runtime_1.jsx)(RenderSequenceStrategy_1.RenderSequenceStrategy, { editContext: this.props.editContext, sequence: this.props.sequence }));
                                } })] })] }) }));
    }
    RenderBranchStack() {
        return ((0, jsx_runtime_1.jsx)(FlowSequenceDiv, { id: this.props.sequence.getElementId(), padding: "4px", size: this.props.editContext.getSequenceMainSize(this.props.sequence), background: this.getSequenceBackgroundColor(this.props.sequence), position: this.getDefaultPosition(), isDragging: this.state.isDragging, isDisabledDragging: !this.props.sequence.isNormal, selected: this.props.editContext.selection === this.props.sequence._id, onContextMenu: (e) => {
                e.preventDefault();
                this.props.editContext.contextControl = {
                    selectedId: this.props.sequence._id,
                    mouseX: e.clientX,
                    mouseY: e.clientY,
                };
            }, onClick: this.onSelectSequence, borderColor: this.getSequenceBorderColor(this.props.sequence), ref: this.containerRef, children: (0, jsx_runtime_1.jsxs)(material_1.Box, { className: "stack", onMouseDown: this.onMouseDown, onMouseUp: this.onMouseUp, onMouseLeave: this.onMouseUp, display: "flex", flexDirection: "column", children: [this.props.sequence.isCollapsed && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(RenderSequenceTitle_1.RenderSequenceTitle, { sequence: this.props.sequence }), (0, jsx_runtime_1.jsx)("div", { className: "stack-actions", children: (0, jsx_runtime_1.jsx)("div", { className: "button-group", children: (0, jsx_runtime_1.jsx)(RenderSequenceActions_1.RenderSequenceActions, { editContext: this.props.editContext, sequence: this.props.sequence }) }) }), (0, jsx_runtime_1.jsx)(RenderCollapsedStack_1.RenderCollapsedStack, { sequence: this.props.sequence, editContext: this.props.editContext, flow: this.props.flow })] })), !this.props.sequence.isCollapsed &&
                        this.props.sequence.branches.map((b, index) => {
                            return ((0, jsx_runtime_1.jsxs)(material_1.Box, { padding: "10px", border: "1px", borderColor: UIStyleConstants_1.UIStyleConstants.GRAY_COLOR, bgcolor: UIStyleConstants_1.UIStyleConstants.WHITE_DARK_COLOR, style: { borderStyle: "solid" }, marginTop: "5px", borderRadius: "4px", width: "100%", paddingTop: "7px", paddingBottom: "7px", children: [(0, jsx_runtime_1.jsx)(RenderSequenceTitle_1.RenderSequenceTitle, { sequence: this.props.sequence }), (0, jsx_runtime_1.jsx)("div", { className: "stack-actions", children: (0, jsx_runtime_1.jsx)("div", { className: "button-group", children: (0, jsx_runtime_1.jsx)(RenderSequenceActions_1.RenderSequenceActions, { editContext: this.props.editContext, sequence: this.props.sequence }) }) }), (0, jsx_runtime_1.jsx)(react_beautiful_dnd_1.Droppable, { droppableId: this.props.sequence._id + "::" + index, direction: "horizontal", children: (provided, snapshot) => {
                                            return ((0, jsx_runtime_1.jsxs)("div", { ...provided.droppableProps, ref: provided.innerRef, style: {
                                                    display: snapshot.isDraggingOver &&
                                                        this.props.sequence.sequenceType ===
                                                            FlowStepSequenceType_1.FlowStepSequenceType.BRANCH_MERGE
                                                        ? "flex"
                                                        : undefined,
                                                }, children: [(0, jsx_runtime_1.jsx)(RenderSequenceContent_1.RenderBranchSequenceContent, { sequence: this.props.sequence, editContext: this.props.editContext, flow: this.props.flow, steps: b.steps }), (0, jsx_runtime_1.jsx)("div", { style: {
                                                            display: this.isEnabledPlaceholderWhileDrop(this.props.sequence)
                                                                ? "block"
                                                                : "none",
                                                        }, children: provided.placeholder })] }));
                                        } }), (0, jsx_runtime_1.jsx)(ObserveState_1.ObserveState, { properties: [FlowStepSequence_1.FlowStepSequence.STRATEGY], listenTo: this.props.editContext, control: () => {
                                            return ((0, jsx_runtime_1.jsx)(RenderSequenceStrategy_1.RenderSequenceStrategy, { editContext: this.props.editContext, sequence: this.props.sequence }));
                                        } })] }));
                        }), !this.props.sequence.isCollapsed && ((0, jsx_runtime_1.jsx)(material_1.Box, { display: "flex", justifyContent: "end", children: (0, jsx_runtime_1.jsx)(material_1.Link, { style: { paddingTop: "5px", fontSize: "12px" }, onClick: () => {
                                this.props.sequence.addBranch();
                            }, children: "Add Branch" }) }))] }) }));
    }
    RenderLoopBack() {
        let lineColor = UIStyleConstants_1.UIStyleConstants.BLUE_COLOR;
        if (this.props.sequence.sequenceType === FlowStepSequenceType_1.FlowStepSequenceType.ITERATE ||
            this.props.sequence.sequenceType === FlowStepSequenceType_1.FlowStepSequenceType.ITERATE_WHILE ||
            this.props.sequence.sequenceType === FlowStepSequenceType_1.FlowStepSequenceType.ITERATE_PARALLEL) {
            let isWhile = this.props.sequence.sequenceType === FlowStepSequenceType_1.FlowStepSequenceType.ITERATE_WHILE;
            let loopbackWidth = isWhile ? "23px" : "15px";
            return ((0, jsx_runtime_1.jsxs)(material_1.Box, { marginRight: isWhile ? "12px" : "7px", marginLeft: isWhile ? "5px" : "0px", width: "5px", display: "flex", flexDirection: "column", justifyContent: "space-between", borderLeft: "1px", borderRight: "0px", borderTop: "0px", borderBottom: "0px", borderColor: lineColor, padding: "0px", style: { borderStyle: "dashed" }, children: [(0, jsx_runtime_1.jsxs)(material_1.Box, { height: "1px", children: [(0, jsx_runtime_1.jsx)(material_1.Box, { width: loopbackWidth, height: "11px", position: "absolute", marginTop: "-13px", marginLeft: "-1px", borderLeft: "1px", borderRight: "1px", borderTop: "1px", borderBottom: "0px", borderColor: lineColor, style: {
                                    borderStyle: "solid",
                                    borderTopLeftRadius: "7px",
                                    borderTopRightRadius: "7px",
                                } }), (0, jsx_runtime_1.jsx)(material_1.Box, { width: "15px", height: "11px", position: "absolute", marginTop: "-14px", marginLeft: isWhile ? "18px" : "10px", children: (0, jsx_runtime_1.jsx)(DrawArrowHead, {}) }), this.props.sequence.sequenceType === FlowStepSequenceType_1.FlowStepSequenceType.ITERATE_PARALLEL && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.Box, { width: "25px", height: "11px", position: "absolute", marginTop: "-13px", marginLeft: "-1px", borderLeft: "1px", borderRight: "1px", borderTop: "1px", borderBottom: "0px", borderColor: lineColor, style: {
                                            borderStyle: "solid",
                                            borderTopLeftRadius: "7px",
                                            borderTopRightRadius: "7px",
                                        } }), (0, jsx_runtime_1.jsx)(material_1.Box, { width: "15px", height: "11px", position: "absolute", marginTop: "-14px", marginLeft: "20px", children: (0, jsx_runtime_1.jsx)(DrawArrowHead, {}) }), (0, jsx_runtime_1.jsx)(material_1.Box, { width: "35px", height: "11px", position: "absolute", marginTop: "-13px", marginLeft: "-1px", borderLeft: "1px", borderRight: "1px", borderTop: "1px", borderBottom: "0px", borderColor: lineColor, style: {
                                            borderStyle: "solid",
                                            borderTopLeftRadius: "7px",
                                            borderTopRightRadius: "7px",
                                        } }), (0, jsx_runtime_1.jsx)(material_1.Box, { width: "15px", height: "11px", position: "absolute", marginTop: "-14px", marginLeft: "30px", children: (0, jsx_runtime_1.jsx)(DrawArrowHead, {}) })] }))] }), (0, jsx_runtime_1.jsxs)(material_1.Box, { height: "1px", children: [(0, jsx_runtime_1.jsx)(material_1.Box, { width: loopbackWidth, height: "17px", position: "absolute", marginTop: "-1px", marginLeft: "-1px", borderLeft: "1px", borderRight: "1px", borderTop: "0px", borderBottom: "1px", borderColor: lineColor, style: {
                                    borderStyle: "solid",
                                    borderBottomLeftRadius: "7px",
                                    borderBottomRightRadius: "7px",
                                } }), isWhile && ((0, jsx_runtime_1.jsx)(material_1.Box, { width: "25px", height: "25px", border: "1px", style: {
                                    borderStyle: "solid",
                                    borderColor: UIStyleConstants_1.UIStyleConstants.GRAY_LIGHT_COLOR,
                                    borderRadius: "4px",
                                }, bgcolor: "white", position: "absolute", marginTop: "-28px", marginLeft: "-14px", onClick: () => this.setState({ openExpression: true }), children: (0, jsx_runtime_1.jsx)(ExpressionIcon_1.ExpressionIcon, {}) })), this.props.sequence.sequenceType === FlowStepSequenceType_1.FlowStepSequenceType.ITERATE_PARALLEL && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.Box, { width: "25px", height: "17px", position: "absolute", marginTop: "-1px", marginLeft: "-1px", borderLeft: "1px", borderRight: "1px", borderTop: "0px", borderBottom: "1px", borderColor: lineColor, style: {
                                            borderStyle: "solid",
                                            borderBottomLeftRadius: "7px",
                                            borderBottomRightRadius: "7px",
                                        } }), (0, jsx_runtime_1.jsx)(material_1.Box, { width: "35px", height: "17px", position: "absolute", marginTop: "-1px", marginLeft: "-1px", borderLeft: "1px", borderRight: "1px", borderTop: "0px", borderBottom: "1px", borderColor: lineColor, style: {
                                            borderStyle: "solid",
                                            borderBottomLeftRadius: "7px",
                                            borderBottomRightRadius: "7px",
                                        } })] }))] }), (0, jsx_runtime_1.jsx)(ExpressionEditLayer_1.ExpressionEditLayer, { open: this.state.openExpression, expression: this.props.sequence.whileExpression, onClose: () => this.setState({ openExpression: false }) })] }));
        }
    }
}
exports.FlowSequenceStack = FlowSequenceStack;
function DrawArrowHead() {
    return ((0, jsx_runtime_1.jsx)("svg", { width: "7", height: "7", viewBox: "-2.5 -5 75 60", preserveAspectRatio: "none", children: (0, jsx_runtime_1.jsx)("path", { d: "M0,0 l35,50 l35,-50", fill: UIStyleConstants_1.UIStyleConstants.BLUE_COLOR, stroke: "green", "stroke-linecap": "round", "stroke-width": "5" }) }));
}
//# sourceMappingURL=FlowSequenceStack.js.map