import { __decorate, __metadata } from "tslib";
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import React from "react";
import styled from "styled-components";
import { FlowStepRegistration } from "./Utilities/RegisterFlowStep";
import { DragDropContext, } from "react-beautiful-dnd";
import { AutoBind } from "../Common/AutoBind";
import { Button } from "@material-ui/core";
import { TopbarViewButton } from "../CommonUI/CommonStyles";
import { StateManager } from "../CommonUI/StateManagement/StateManager";
import { ObserveState } from "../CommonUI/StateManagement/ObserveState";
import { FlowConstants } from "./CommonUI/FlowConstants";
import { FlowEditContext } from "./FlowEditContext";
import { ObserveMultiStateProperties } from "../CommonUI/StateManagement/ObserveMultiStateProperties";
import { CandidateSequence } from "./Structure/CandidateSequence";
import { Topbar, IInjectTopItemType } from "../CommonUI/BuildUI/Topbar";
import { Sidebar } from "../CommonUI/BuildUI/Sidebar";
import { ViewIcon } from "../CommonUI/Icon/ViewIcon";
import { ToolBox } from "./Components/ToolBox";
import { RegisterFlowElements } from "./registerElements";
import { NormalModeIcon } from "../CommonUI/Icon/NormalModeIcon";
import { DiagramModeIcon } from "../CommonUI/Icon/DiagramModeIcon";
import { XDefinitionEditor } from "../CommonUI/DataDesigner/XDefinitionEditor";
import { HorizontalModeIcon } from "../CommonUI/Icon/HorizontalModeIcon";
import { FlowDesignPage } from "./Components/XFlowEditor.Designer";
import { FlowViewMode } from "./DesignerUI/FlowViewMode";
import { FlowBuilderPage } from "./DesignerUI/FlowBuilderPage";
import { FlowStepSequence } from "./Structure/FlowStepSequence";
import { FlowIcon } from "../CommonUI/Icon/FlowIcon";
import { DataGrayIcon } from "../CommonUI/Icon/DataGrayIcon";
import { CodeIcon } from "../CommonUI/Icon/CodeIcon";
import { TestDataIcon } from "../CommonUI/Icon/TestDataIcon";
const FlowEditorDiv = styled.div `
    width: 100%;
    height: 100vh;
    display: flex;
    flex-direction: column;

    *::-webkit-scrollbar-track {
        -webkit-box-shadow: inset 0 0 2px rgba(147, 169, 191, 0.28);
        background-color: transparent;
    }

    *::-webkit-scrollbar {
        width: 5px;
        background-color: transparent;
    }

    *::-webkit-scrollbar-thumb {
        background-color: rgba(64, 80, 166, 0.8);
    }
`;
export class XFlowEditor extends React.Component {
    constructor(props) {
        super(props);
        this.editContext = new FlowEditContext(this);
        this.mousePosition = {
            x: 0,
            y: 0,
        };
        this.tabs = [];
        this.onMouseMove = (event) => {
            this.mousePosition = {
                x: event.clientX,
                y: event.clientY,
            };
        };
        // ensure flow steps are registered
        RegisterFlowElements.doRegistration();
        props.flow.context = this.editContext;
        this.tabs = this.getDefaultTabs();
        if (props.flowTitle) {
            this.editContext.flowTitle = props.flowTitle;
        }
        if (props.viewAPIUrl) {
            this.editContext.viewAPIUrl = props.viewAPIUrl;
        }
        if (props.onFlowSave) {
            this.editContext.onFlowSave = props.onFlowSave;
        }
        if (props.onFlowCancel) {
            this.editContext.onFlowCancel = props.onFlowCancel;
        }
        if (props.flowStartDataDefinition) {
            props.flow.inputData = props.flowStartDataDefinition;
        }
        if (props.flow.sequences.length > 0) {
            for (let seq of [...props.flow.sequences, props.flow.errorSequence, props.flow.endSequence]) {
                seq.flow = props.flow;
            }
        }
        window.addEventListener("mousemove", this.onMouseMove);
    }
    componentWillUnmount() {
        window.removeEventListener("mousemove", this.onMouseMove);
    }
    get flow() {
        return this.props.flow;
    }
    getDefaultTabs() {
        return [
            {
                value: FlowBuilderPage.Flow,
                renderUI: () => (_jsxs(_Fragment, { children: [_jsx(ObserveState, { listenTo: this.editContext, properties: ["draggingControl"], control: () => _jsx(ToolBox, { editContext: this.editContext, flow: this.flow }, void 0) }, void 0),
                        _jsx(ObserveMultiStateProperties, { listeners: [
                                {
                                    listenTo: this.props.flow,
                                    propertyName: "sequences",
                                },
                                {
                                    listenTo: this.editContext,
                                    propertyName: "propName",
                                },
                            ], control: () => _jsx(FlowDesignPage, { flow: this.props.flow, editContext: this.editContext }, void 0) }, void 0)] }, void 0)),
                icon: _jsx(FlowIcon, {}, void 0),
            },
            {
                value: FlowBuilderPage.Data,
                renderUI: () => (_jsx(XDefinitionEditor, { definition: this.props.flow.getInputDefinition(), readOnly: !this.props.flow.canChangeInputs }, void 0)),
                icon: _jsx(DataGrayIcon, {}, void 0),
            },
            {
                value: FlowBuilderPage.Configuration,
                renderUI: () => _jsx(_Fragment, {}, void 0),
                icon: _jsx(CodeIcon, {}, void 0),
            },
            {
                value: FlowBuilderPage.Test,
                renderUI: () => _jsx(_Fragment, {}, void 0),
                icon: _jsx(TestDataIcon, {}, void 0),
            },
        ];
    }
    onChangeFlowTitle(event) {
        this.editContext.flowTitle = event.target.value;
        StateManager.propertyChanged(this.editContext, "flowTitle");
    }
    render() {
        let afterElems = [];
        if (this.props.viewAPIUrl) {
            afterElems.push(_jsx(TopbarViewButton, Object.assign({ color: "primary", startIcon: _jsx(ViewIcon, {}, void 0), href: this.editContext.viewAPIUrl }, { children: "View API" }), void 0));
        }
        return (_jsx(ObserveState, { listenTo: this, control: () => (_jsx(DragDropContext, Object.assign({ onBeforeCapture: this.onBeforeCapture, onBeforeDragStart: this.onBeforeDragStart, onDragEnd: this.onDragEnd, onDragUpdate: this.onDragUpdate }, { children: _jsxs(FlowEditorDiv, { children: [_jsx(ObserveState, { listenTo: this.editContext, properties: [
                                "flowTitle",
                                "selectionElement",
                                "isShowDescription",
                                "isShowErrorBranch",
                                "isCollapsed",
                                "viewMode",
                            ], control: () => {
                                let afterItems = [
                                    {
                                        label: "Type",
                                        type: IInjectTopItemType.ICONBUTTONGROUP,
                                        value: this.editContext.viewMode,
                                        onSelect: (value) => {
                                            this.editContext.viewMode = value;
                                        },
                                        items: [
                                            {
                                                value: FlowViewMode.NORMAL,
                                                icon: _jsx(NormalModeIcon, {}, void 0),
                                            },
                                            {
                                                value: FlowViewMode.DIAGRAM,
                                                icon: _jsx(DiagramModeIcon, {}, void 0),
                                            },
                                            {
                                                value: FlowViewMode.HORIZONTAL,
                                                icon: _jsx(HorizontalModeIcon, {}, void 0),
                                            },
                                        ],
                                        wrapperStyle: { border: "none" },
                                    },
                                    this.editContext.displayBehavior.getShowTopItems(),
                                ];
                                return (_jsx(Topbar, { name: this.editContext.flowTitle, onChangeName: this.onChangeFlowTitle, editContext: this.editContext, isActionDisabled: !this.editContext.lastSelectionElement, isRequiredActionGroup: true, onSave: this.editContext.onFlowSave
                                        ? (data) => {
                                            if (this.editContext.onFlowSave) {
                                                this.editContext.onFlowSave();
                                            }
                                        }
                                        : undefined, onClose: this.editContext.onFlowCancel, prevElems: [
                                        _jsx(Button, Object.assign({ onClick: () => {
                                                this.editContext.positionCandidateSequences(true);
                                                this.editContext.refreshSequences();
                                            } }, { children: "position and refresh" }), void 0),
                                        _jsx(Button, Object.assign({ onClick: () => {
                                                this.editContext.refreshSequences();
                                            } }, { children: "refresh" }), void 0),
                                    ], afterItems: afterItems, afterElems: afterElems }, void 0));
                            } }, void 0),
                        _jsx(ObserveState, { listenTo: this.editContext, properties: ["mode"], control: () => (_jsx(Sidebar, { items: this.tabs, value: this.editContext.mode, onChange: (mode) => {
                                    Reflect.set(this.editContext, "mode", mode);
                                    StateManager.propertyChanged(this.editContext, "mode");
                                } }, void 0)) }, void 0)] }, void 0) }), void 0)) }, void 0));
    }
    onBeforeCapture(before) {
        this.editContext.draggingControl = {
            source: {
                current: before.draggableId,
            },
            pos: this.mousePosition,
        };
    }
    onBeforeDragStart(initial) {
        this.editContext.clearSelection();
        this.editContext.draggingControl = {
            source: {
                parent: initial.source.droppableId,
                current: initial.draggableId,
            },
            pos: this.editContext.draggingControl.pos,
        };
    }
    onDragUpdate(initial, _provided) {
        var _a;
        this.editContext.draggingControl = {
            source: {
                parent: initial.source.droppableId,
                current: initial.draggableId,
            },
            destination: (_a = initial.destination) === null || _a === void 0 ? void 0 : _a.droppableId,
            pos: this.editContext.draggingControl.pos,
        };
    }
    onDragEnd(result) {
        this.editContext.draggingControl = null;
        // if not destination... then we should not do anything
        if (!result.destination)
            return;
        // do not drag in toolbox
        if (result.destination.droppableId === FlowConstants.ToolboxId)
            return;
        // do not drag from normal sequences to error sequence, vice versa.
        if ((result.destination.droppableId === FlowConstants.ERROR_SEQUENCE &&
            result.source.droppableId !== FlowConstants.ToolboxId) ||
            result.source.droppableId === FlowConstants.ERROR_SEQUENCE)
            return;
        let control;
        let registeredControl = FlowStepRegistration.getByName(result.draggableId);
        if (registeredControl) {
            control = registeredControl.create();
        }
        else {
            control = this.props.flow.find(result.draggableId);
        }
        try {
            if (control) {
                let toSeq = this.editContext.getCandidateOrRealSequence(result.destination.droppableId);
                let fromSeq = this.editContext.getCandidateOrRealSequence(result.source.droppableId);
                if (!toSeq) {
                    throw new Error("Can not find the droppable sequence");
                }
                if (result.destination.droppableId === result.source.droppableId) {
                    // changing order
                    this.props.flow.moveInSequence(control, result.destination.droppableId, result.destination.index);
                    this.editContext.onStepMovedInSequence(toSeq, control, result.destination.index);
                }
                else {
                    if (toSeq instanceof CandidateSequence) {
                        if (!fromSeq) {
                            // dropping on candidate from toolbox
                            this.flow.addStepToCandidate(control, toSeq);
                            this.editContext.onStepAdded(toSeq, control);
                        }
                        else if (fromSeq instanceof FlowStepSequence) {
                            // dropping on candidate from real sequences.
                            this.flow.moveStepToCandidate(control, fromSeq, toSeq);
                            this.editContext.onStepMoved(fromSeq, toSeq, control);
                        }
                    }
                    else if (toSeq instanceof FlowStepSequence) {
                        if (!fromSeq) {
                            // dropping on real sequence from toolbox.
                            this.editContext.displayBehavior.addStepToSequence(toSeq, control, result.destination.index);
                            this.editContext.onStepAdded(toSeq, control);
                        }
                        else if (fromSeq instanceof FlowStepSequence) {
                            // dropping on real sequence from real sequences.
                            this.editContext.displayBehavior.moveStepToSequence(control, fromSeq, toSeq, result.destination.index);
                            this.editContext.onStepMoved(fromSeq, toSeq, control);
                        }
                    }
                }
            }
        }
        catch (e) {
            this.editContext.notification = {
                message: e.message,
                onSuccess: () => { },
            };
        }
        // if (control) {
        //     this.editContext.setSelection(control);
        // }
        // else {
        //     this.editContext.clearSelection();
        // }
    }
}
__decorate([
    AutoBind,
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", void 0)
], XFlowEditor.prototype, "onChangeFlowTitle", null);
__decorate([
    AutoBind,
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", void 0)
], XFlowEditor.prototype, "onBeforeCapture", null);
__decorate([
    AutoBind,
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", void 0)
], XFlowEditor.prototype, "onBeforeDragStart", null);
__decorate([
    AutoBind,
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object, Object]),
    __metadata("design:returntype", void 0)
], XFlowEditor.prototype, "onDragUpdate", null);
__decorate([
    AutoBind,
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", void 0)
], XFlowEditor.prototype, "onDragEnd", null);
//# sourceMappingURL=XFlowEditor.js.map