import { jsx as _jsx } from "react/jsx-runtime";
import { Button, Link, Tooltip } from "@material-ui/core";
import styled from "styled-components";
import { BaseFlowStep } from "../../Steps/BaseFlowStep";
import { FlowStepOutputInstructionType } from "../../Structure/FlowStepOutputInstructions";
import { FlowStepSequence, FlowStepSequenceStrategy } from "../../Structure/FlowStepSequence";
import { BaseDisplayBehavior } from "./BaseDisplayBehavior";
import { FlowConstants } from "../../CommonUI/FlowConstants";
import { CandidateSequence } from "../CandidateSequence";
import { ObserveState } from "../../../CommonUI/StateManagement/ObserveState";
import { RegularSequenceContent } from "../../DesignerUI/Regular/FlowStackContent";
import { FlowDiagramSequenceContent } from "../../DesignerUI/Diagram/FlowStackContent";
import { HTMLUtilities } from "../../../CommonUI/HTMLUtilities";
import { DiagramStepStrategy } from "../../DesignerUI/Diagram/StepStrategey";
import { DiagramSequenceTitle } from "../../DesignerUI/Diagram/SequenceTitle";
import { RegularSequenceStrategy } from "../../DesignerUI/Regular/SequenceStrategy";
import { DiagramSequenceActions } from "../../DesignerUI/Diagram/SequenceActions";
import { ColorPicker } from "../../../CommonUI/BuildUI/ColorPicker";
import { StateManager } from "../../../CommonUI/StateManagement/StateManager";
const NotificationButton = styled(Button) `
    && {
        width: 50%;
        text-align: center;
        padding: 10px 0 !important;

        .MuiButton-label {
            font-size: 12px !important;
        }
    }
`;
export class DiagramDisplayBehavior extends BaseDisplayBehavior {
    constructor() {
        super(...arguments);
        this.sequenceOuterPadding = "4px";
        this.candidateWidth = FlowConstants.DEFAULT_DIAGRAM_STACK_WIDTH;
        this.candidateHeight = FlowConstants.DEFAULT_DIAGRAM_STACK_HEIGHT;
        this.candidatePadding = "0 15px";
        this.candidateFontSize = 11;
        this.collapsedWidth = FlowConstants.DEFAULT_DIAGRAM_STACK_WIDTH;
        this.collapsedHeight = FlowConstants.DEFAULT_DIAGRAM_STACK_HEIGHT;
        this.errorCollapsedWidth = FlowConstants.COLLAPSED_ERROR_STACK_WIDTH;
        this.sequenceWidth = 210;
        this.emptyTextFontSize = 11;
        this.defaultStackCollapsedBorderColor = "transparent";
        this.sequenceCandidateShift = FlowConstants.SEQUENCE_CANDIDATE_SHIFT;
    }
    isCollapsed(sequence) {
        var _a;
        if (!sequence.isNormal)
            return super.isCollapsed(sequence);
        if (this.editContext.draggingControl && this.editContext.draggingControl.source.parent) {
            if (sequence._id === this.editContext.draggingControl.source.parent)
                return false;
        }
        if (!this.editContext.selection) {
            if (!sequence.isPrimary)
                return true;
            // set the expanded to primary if primary has no steps.
            else if (sequence.steps.length === 0)
                return false;
        }
        if (this.editContext.selection === sequence._id)
            return false;
        if (((_a = this.flow.findSequenceByStepId(this.editContext.selection)) === null || _a === void 0 ? void 0 : _a._id) === sequence._id)
            return false;
        return true;
    }
    setIsCollapsed(sequence, isCollapsed) {
        // only end / error stacks required
        if (!sequence.isNormal)
            return super.setIsCollapsed(sequence, isCollapsed);
    }
    clearSelection() {
        this.editContext.clearSelection();
        this.editContext.onClearSelectionInContext();
    }
    onSetSelection(sequence) {
        // no need to refresh for one step as size is not changed.
        if (sequence.steps.length !== 1) {
            this.editContext.onSequenceExpanded(sequence);
        }
    }
    renderSequenceActions(sequence) {
        return _jsx(DiagramSequenceActions, { sequence: sequence, displayBehavior: this }, void 0);
    }
    renderStepStrategy() {
        return _jsx(DiagramStepStrategy, { editContext: this.editContext }, void 0);
    }
    renderSequenceTitle(sequence) {
        return _jsx(DiagramSequenceTitle, { sequence: sequence, displayBehavior: this }, void 0);
    }
    onSelectStepStrategyConnect(element, step) {
        if (step.sequence && step.sequence.steps.length === 1) {
            this.editContext.setSelectedStepStrategy(element, step.sequence.steps[0]);
        }
        else {
            super.onSelectStepStrategyConnect(element, step);
        }
    }
    addStepToSequence(sequence, step, index) {
        const doAction = (isReplace = false) => {
            if (isReplace) {
                sequence.removeStep(sequence.steps[0]);
            }
            this.editContext.notification = undefined;
            this.flow.add(step, sequence, index);
            this.editContext.onStepAdded(sequence, step);
        };
        if (sequence.steps.length === 1 && sequence.isNormal) {
            this.editContext.notification = {
                message: "Turn this into a step sequence or replace step",
                type: "confirm",
                actions: [
                    {
                        items: [
                            {
                                renderUI: () => {
                                    return (_jsx(NotificationButton, Object.assign({ variant: "contained", color: "primary", size: "small", onClick: () => doAction(true), "data-testid": "btn-dialog-cancel" }, { children: "Replace Step" }), void 0));
                                },
                            },
                            {
                                renderUI: () => {
                                    return (_jsx(NotificationButton, Object.assign({ variant: "contained", color: "primary", size: "small", onClick: () => doAction(false), "data-testid": "btn-dialog-cancel" }, { children: "Turn into sequence" }), void 0));
                                },
                            },
                        ],
                    },
                    {
                        items: [
                            {
                                renderUI: () => {
                                    return (_jsx(Link, Object.assign({ href: "#", onClick: () => {
                                            this.editContext.notification = undefined;
                                        }, "data-testid": "btn-dialog-cancel", style: { marginLeft: 0, marginTop: 20 } }, { children: "Cancel changes" }), void 0));
                                },
                            },
                        ],
                    },
                ],
            };
        }
        else {
            super.addStepToSequence(sequence, step, index);
        }
    }
    moveStepToSequence(step, fromSeq, toSeq, index) {
        const doAction = (isReplace = false) => {
            this.flow.moveToSequence(step, fromSeq, toSeq, index);
            if (isReplace) {
                toSeq.removeStep(toSeq.steps[0]);
            }
            this.editContext.notification = undefined;
            this.editContext.onStepMoved(fromSeq, toSeq, step, index);
        };
        if (toSeq.steps.length === 1 && toSeq.isNormal) {
            this.editContext.notification = {
                message: "Turn this into a step sequence or replace step",
                type: "confirm",
                actions: [
                    {
                        items: [
                            {
                                renderUI: () => {
                                    return (_jsx(NotificationButton, Object.assign({ variant: "contained", color: "primary", size: "small", onClick: () => doAction(true), "data-testid": "btn-dialog-cancel" }, { children: "Replace Step" }), void 0));
                                },
                            },
                            {
                                renderUI: () => {
                                    return (_jsx(NotificationButton, Object.assign({ variant: "contained", color: "primary", size: "small", onClick: () => doAction(false), "data-testid": "btn-dialog-cancel" }, { children: "Turn into sequence" }), void 0));
                                },
                            },
                        ],
                    },
                    {
                        items: [
                            {
                                renderUI: () => {
                                    return (_jsx(Link, Object.assign({ href: "#", onClick: () => {
                                            this.editContext.notification = undefined;
                                        }, "data-testid": "btn-dialog-cancel", style: { marginLeft: 0, marginTop: 20 } }, { children: "Cancel changes" }), void 0));
                                },
                            },
                        ],
                    },
                ],
            };
        }
        else {
            super.moveStepToSequence(step, fromSeq, toSeq, index);
        }
    }
    getLine(value) {
        var _a;
        let targetSequence = this.editContext.getCandidateOrRealSequence(value.toId);
        let mmsLine = undefined;
        if (value.fromSequence.steps.length !== 1) {
            return super.getLine(value);
        }
        let endAnchor = [
            "left",
            "top",
            {
                position: "bottom",
                offset: {
                    x: 20,
                    y: -10,
                },
            },
        ];
        // line to candidate.
        if (targetSequence instanceof CandidateSequence) {
            endAnchor = "left";
        }
        if (mmsLine)
            return mmsLine;
        let firstStep = value.fromSequence.steps[0];
        let isHiddenStep = Reflect.get(value.fromStep, "hidden");
        let startAnchor = [
            {
                position: "bottom",
                offset: {
                    x: 20,
                    y: -4,
                },
            },
            {
                position: "right",
                offset: {
                    y: Math.ceil(value.fromSequence.instructions.filter((ins) => ins.strategy !== FlowStepOutputInstructionType.BRANCH).length / 2) * 16,
                    x: -4,
                },
            },
            "top",
            "left",
        ];
        let tooltip = isHiddenStep
            ? ((_a = firstStep.getOutcomeInstructions()[0]) === null || _a === void 0 ? void 0 : _a.pathName) || "Done"
            : value.fromInstruction.pathName;
        let label = tooltip.length > FlowConstants.MAX_CHARS_STEP_PATH_LABEL
            ? `${tooltip.slice(0, FlowConstants.MAX_CHARS_STEP_PATH_LABEL)}...`
            : tooltip;
        return {
            targetSequence,
            arrow: {
                start: value.fromSequence._id,
                startAnchor: startAnchor,
                end: value.toId,
                endAnchor: endAnchor,
                strokeWidth: 2,
                headSize: 3,
                color: FlowConstants.DEFAULT_RELATION_LINE_COLOR,
                path: this.linePathType,
                avoidRects: this.flow.sequences.map((s) => s._id),
            },
            labels: [
                {
                    label: (_jsx(Tooltip, Object.assign({ title: tooltip }, { children: _jsx("span", { children: label }, void 0) }), void 0)),
                    value,
                    isFlowConnection: false,
                },
            ],
            value,
        };
    }
    renderSequenceContent(sequence) {
        if (sequence.steps.length !== 1 || !sequence.isNormal) {
            return _jsx(RegularSequenceContent, { sequence: sequence, editContext: this.editContext, flow: this.flow }, void 0);
        }
        return _jsx(FlowDiagramSequenceContent, { sequence: sequence, editContext: this.editContext, flow: this.flow }, void 0);
    }
    renderSequenceStrategy(sequence) {
        // SSS no need to render sequenceStrategy separately.
        if (sequence.steps.length === 1)
            return null;
        return _jsx(RegularSequenceStrategy, { sequence: sequence }, void 0);
    }
    getSequenceMainSize(sequence) {
        // MSS and end/error stack candidate size in diagram mode.
        if (sequence.steps.length > 1 || !sequence.isNormal) {
            return super.getSequenceMainSize(sequence);
        }
        return {
            width: this.collapsedWidth,
            height: this.collapsedHeight,
        };
    }
    getSequenceBorderColor(sequence) {
        // for end/error and MSS.
        if (sequence.steps.length !== 1 || !sequence.isNormal) {
            return super.getSequenceBorderColor(sequence);
        }
        // While step is dragging over on this sequence.
        if (this.flow.isDraggingOverSequence(sequence)) {
            return FlowConstants.SSS_STEP_DROP_OVER_BORDER_COLOR;
        }
        if (this.editContext.selection === sequence._id) {
            return FlowConstants.SELECTED_STACK_COLOR;
        }
        // when selecting the step in sequence.
        let selectedSequence = this.flow.findSequenceByStepId(this.editContext.selection);
        if ((selectedSequence === null || selectedSequence === void 0 ? void 0 : selectedSequence._id) === sequence._id)
            return FlowConstants.SELECTED_STACK_COLOR;
        return "transparent";
    }
    getSequenceStepsForPaths(sequence) {
        if (sequence.isOneStep)
            return [sequence.hiddenStep, ...sequence.steps];
        return super.getSequenceStepsForPaths(sequence);
    }
    getPathsForStep(step) {
        if (step.sequence.steps.length !== 1)
            return super.getPathsForStep(step);
        let paths = step.getOutcomeInstructions();
        if (paths.length > 0 && !Reflect.get(step, "hidden")) {
            paths.shift();
        }
        return paths;
    }
    getSequenceInstructions(sequence) {
        return [sequence.hiddenStep, ...sequence.steps].reduce((ss, s) => {
            let insts = this.getPathsForStep(s) || [];
            ss = [...ss, ...insts];
            return ss;
        }, []);
    }
    getInitialSequenceStrategy() {
        return FlowStepSequenceStrategy.LINK;
    }
    setCandidateDesiredPositionForSequenceStrategy(inst) {
        // for MSS
        let seq = this.flow.findSequenceByStepId(inst.stepId);
        if (!seq)
            return null;
        if (seq.steps.length !== 1)
            return super.setCandidateDesiredPositionForSequenceStrategy(inst);
        // for only SSS
        let pos = HTMLUtilities.getGeometry(inst.getElementId(), FlowConstants.DESIGN_SURFACE_ID);
        if (pos) {
            // set above all other path candidates.
            let insty = pos.top - this.getCandidateCommonStyles().height / 2;
            let instx = pos.left + this.pathCandidateShift;
            inst.candidateStackY = insty;
            inst.candidateStackX = instx;
        }
    }
    setCandidateDesiredPositionForSeqeuence(sequence) {
        // MSS
        if (sequence.steps.length !== 1) {
            return super.setCandidateDesiredPositionForSeqeuence(sequence);
        }
        // for SSS, we don't need to check if sequence's collapsed or expanded, just calculated basedon sequence geometry.
        let pos = HTMLUtilities.getGeometry(sequence._id, FlowConstants.DESIGN_SURFACE_ID);
        if (pos) {
            let idx = 0;
            for (let inst of sequence.instructions) {
                let c = this.editContext.getCandidateOrRealSequence(inst.connectedSequenceId);
                if (c instanceof 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;
                }
            }
        }
    }
    isShowStepConnection(step) {
        if (step.sequence.isOneStep)
            return false;
        return super.isShowStepConnection(step);
    }
    isEnabledPlaceholderWhileDrop(sequence) {
        // SSS disable for dropping over animations
        if (sequence.steps.length === 1 && sequence.isNormal)
            return false;
        // disable animations when dropping over primary stack.
        if (sequence.isPrimary && sequence.steps.length === 0)
            return false;
        return super.isEnabledPlaceholderWhileDrop(sequence);
    }
    // render for color picker of stack.
    renderExtraContents(editContext) {
        return (_jsx(ObserveState, { listenTo: editContext, properties: ["selectedForColor"], control: () => {
                if (!editContext.selectedForColor)
                    return null;
                return (_jsx(ColorPicker, { onClose: () => {
                        editContext.selectedForColor = undefined;
                    }, onChange: (color) => {
                        editContext.selectedForColor.instance.color = color;
                        StateManager.propertyChanged(editContext.selectedForColor.instance, "color");
                        editContext.selectedForColor = undefined;
                    }, value: editContext.selectedForColor.instance.color, position: editContext.selectedForColor.position }, void 0));
            } }, void 0));
    }
    renderEditUI(elem) {
        if (!elem)
            return null;
        let sequence;
        if (elem instanceof FlowStepSequence) {
            sequence = elem;
        }
        else if (elem instanceof BaseFlowStep) {
            sequence = this.flow.findSequenceByStepId(elem._id);
        }
        if (sequence) {
            // for MSS.
            if (sequence.steps.length !== 1) {
                return elem.renderEditUI();
            }
            else {
                return sequence.steps[0].renderEditUI();
            }
        }
        else {
            return elem.renderEditUI();
        }
    }
}
//# sourceMappingURL=DiagramDisplayBehavior.js.map