"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BuilderRender = exports.MappingBuilder = void 0;
const tslib_1 = require("tslib");
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = tslib_1.__importDefault(require("react"));
const styled_components_1 = tslib_1.__importDefault(require("styled-components"));
const react_xarrows_1 = tslib_1.__importStar(require("react-xarrows"));
const react_beautiful_dnd_1 = require("react-beautiful-dnd");
const XMappingDestination_1 = require("./Components/XMappingDestination");
const XMappingRules_1 = require("./Components/XMappingRules");
const XMappingSource_1 = require("./Components/XMappingSource");
const MappingEditContext_1 = require("./Builder/MappingEditContext");
const MappingConstants_1 = require("@appglue/common/dist/Mapping/MappingConstants");
const ObserveMultiState_1 = require("../CommonUI/StateManagement/ObserveMultiState");
const Sidebar_1 = require("../CommonUI/BuilderUI/Sidebar");
const MappingBuilderPage_1 = require("./Builder/MappingBuilderPage");
const XExecutableTester_1 = require("../CommonUI/Testing/XExecutableTester");
const TestDataIcon_1 = require("../CommonUI/Icon/TestDataIcon");
const Topbar_1 = require("../CommonUI/BuilderUI/Topbar");
const ObserveState_1 = require("../CommonUI/StateManagement/ObserveState");
const DataInputIcon_1 = require("../CommonUI/Icon/DataInputIcon");
const DataOutputIcon_1 = require("../CommonUI/Icon/DataOutputIcon");
const MappingIcon_1 = require("../CommonUI/Icon/MappingIcon");
const ExpressionValueType_1 = require("@appglue/common/dist/Expressions/ExpressionValueType");
const Log_1 = require("@appglue/common/dist/Log");
const LogLevel_1 = require("@appglue/common/dist/Plugins/Logging/LogLevel");
const AutoBind_1 = require("@appglue/common/dist/Common/AutoBind");
const StateManager_1 = require("@appglue/common/dist/Common/StateManager");
const UndefinedDataDefinition_1 = require("@appglue/common/dist/Common/Data/Definitions/UndefinedDataDefinition");
const DataBuilder_1 = require("../DataBuilder/DataBuilder");
class MappingBuilder extends react_1.default.Component {
    editContext;
    tabs;
    constructor(props) {
        super(props);
        this.tabs = this.getDefaultTabs();
        this.editContext = new MappingEditContext_1.MappingEditContext(props.definition);
        if (props.mappingBuilderName) {
            this.editContext.mappingBuilderName = props.mappingBuilderName;
        }
        if (props.onSave) {
            this.editContext.onSave = props.onSave;
        }
        if (props.onCancel) {
            this.editContext.onCancel = props.onCancel;
        }
    }
    getDefaultTabs() {
        return [
            {
                value: MappingBuilderPage_1.MappingBuilderPage.Designer,
                renderUI: () => (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: this.RenderMappingBuilder() }),
                icon: (0, jsx_runtime_1.jsx)(MappingIcon_1.MappingIcon, {}),
            },
            {
                value: MappingBuilderPage_1.MappingBuilderPage.InputData,
                renderUI: () => ((0, jsx_runtime_1.jsx)(DataBuilder_1.DataBuilder, { definition: this.props.definition.getInputDefinition(), readOnly: !this.props.definition.canChangeInputs })),
                icon: (0, jsx_runtime_1.jsx)(DataInputIcon_1.DataInputIcon, {}),
            },
            {
                value: MappingBuilderPage_1.MappingBuilderPage.OutputData,
                renderUI: () => ((0, jsx_runtime_1.jsx)(DataBuilder_1.DataBuilder, { definition: this.props.definition.getExecutionResult(), readOnly: !this.props.definition.canChangeOutputs })),
                icon: (0, jsx_runtime_1.jsx)(DataOutputIcon_1.DataOutputIcon, {}),
            },
            {
                value: MappingBuilderPage_1.MappingBuilderPage.Test,
                renderUI: () => ((0, jsx_runtime_1.jsx)(XExecutableTester_1.XExecutableTester, { saveUnitTest: this.props.saveUnitTest, executable: this.props.definition })),
                icon: (0, jsx_runtime_1.jsx)(TestDataIcon_1.TestDataIcon, {}),
            },
        ];
    }
    onChangedName(newName) {
        this.editContext.mappingBuilderName = newName;
        StateManager_1.StateManager.propertyChanged(this.editContext, "title");
        if (this.props.onMappingBuilderNameUpdate)
            this.props.onMappingBuilderNameUpdate(newName);
    }
    onDragEnd = (result) => {
        this.editContext.isDragging = false;
        if (!result.destination)
            return;
        // mapping rule to source
        if (result.source.droppableId.startsWith(MappingConstants_1.MappingConstants.MAPPING_PREFIX_RULE_ITEM) &&
            result.destination.droppableId.startsWith(MappingConstants_1.MappingConstants.MAPPING_PREFIX_SOURCE_ITEM)) {
            let mappingRule = this.props.definition.find(result.draggableId);
            if (!mappingRule)
                return;
            let sourcePath = result.destination.droppableId.replace(MappingConstants_1.MappingConstants.MAPPING_PREFIX_SOURCE_ITEM, "");
            try {
                mappingRule.mapping.variableName = sourcePath;
                StateManager_1.StateManager.changed(mappingRule);
                StateManager_1.StateManager.changed(this.props.definition);
            }
            catch (e) {
                (0, Log_1.log)("Mapping", LogLevel_1.LogLevel.ERROR, "incorrect source path:", result.destination.droppableId);
            }
        }
        // source to destination
        if (result.source.droppableId.startsWith(MappingConstants_1.MappingConstants.MAPPING_PREFIX_SOURCE_ITEM) &&
            result.destination.droppableId.startsWith(MappingConstants_1.MappingConstants.MAPPING_PREFIX_DESTINATION_ITEM) &&
            result.draggableId.startsWith(MappingConstants_1.MappingConstants.MAPPING_PREFIX_SOURCE_ITEM)) {
            try {
                let sourcePath = result.draggableId
                    .replace(MappingConstants_1.MappingConstants.MAPPING_PREFIX_SOURCE_ITEM, "")
                    .replace(MappingConstants_1.MappingConstants.DRAGGING_CONNECTOR_SUFFIX, "");
                let destinationPath = result.destination.droppableId.replace(MappingConstants_1.MappingConstants.MAPPING_PREFIX_DESTINATION_ITEM, "");
                this.props.definition.hookDirectConnect(sourcePath, destinationPath);
                StateManager_1.StateManager.changed(this.props.definition);
            }
            catch (e) {
                (0, Log_1.log)("Mapping", LogLevel_1.LogLevel.ERROR, "incorrect connection:", result.destination.droppableId, result.draggableId);
            }
        }
        // destination to source
        if (result.source.droppableId.startsWith(MappingConstants_1.MappingConstants.MAPPING_PREFIX_DESTINATION_ITEM) &&
            result.destination.droppableId.startsWith(MappingConstants_1.MappingConstants.MAPPING_PREFIX_SOURCE_ITEM)) {
            console.log("destination to source:", result, result.draggableId, result.destination.droppableId);
            try {
                let destinationPath = result.source.droppableId
                    .replace(MappingConstants_1.MappingConstants.MAPPING_PREFIX_DESTINATION_ITEM, "")
                    .replace(MappingConstants_1.MappingConstants.DRAGGING_CONNECTOR_SUFFIX, "");
                let sourcePath = result.destination.droppableId
                    .replace(MappingConstants_1.MappingConstants.MAPPING_PREFIX_SOURCE_ITEM, "")
                    .replace(MappingConstants_1.MappingConstants.DRAGGING_CONNECTOR_SUFFIX, "");
                this.props.definition.hookDirectConnect(sourcePath, destinationPath);
                StateManager_1.StateManager.changed(this.props.definition);
            }
            catch (e) {
                (0, Log_1.log)("Mapping", LogLevel_1.LogLevel.ERROR, "incorrect connection:", result.destination.droppableId, result.draggableId);
            }
        }
        // source to mapping rule
        if (result.source.droppableId.startsWith(MappingConstants_1.MappingConstants.MAPPING_PREFIX_SOURCE_ITEM) &&
            result.destination.droppableId.startsWith(MappingConstants_1.MappingConstants.MAPPING_PREFIX_RULE_ITEM)) {
            try {
                let sourcePath = result.draggableId.replace(MappingConstants_1.MappingConstants.MAPPING_PREFIX_SOURCE_ITEM, "");
                let mappingRule = this.props.definition.find(result.destination.droppableId.replace(MappingConstants_1.MappingConstants.MAPPING_PREFIX_RULE_ITEM, ""));
                if (!mappingRule)
                    return;
                this.props.definition.hookDirectConnect(sourcePath, mappingRule?.targetPath);
                StateManager_1.StateManager.changed(this.props.definition);
            }
            catch (e) {
                (0, Log_1.log)("Mapping", LogLevel_1.LogLevel.ERROR, "incorrect connection:", result.destination.droppableId, result.draggableId);
            }
        }
        // replace
        if (result.destination.droppableId.startsWith(MappingConstants_1.MappingConstants.MAPPING_PREFIX_DESTINATION_ITEM) &&
            result.source.droppableId.startsWith(MappingConstants_1.MappingConstants.MAPPING_PREFIX_DESTINATION_ITEM) &&
            result.draggableId.startsWith(MappingConstants_1.MappingConstants.MAPPING_PREFIX_RULE_ITEM)) {
            let newMappingRule = this.props.definition.find(result.draggableId
                .replace(MappingConstants_1.MappingConstants.MAPPING_PREFIX_RULE_ITEM, "")
                .replace(MappingConstants_1.MappingConstants.DRAGGING_CONNECTOR_SUFFIX, ""));
            if (!newMappingRule)
                return;
            let oldMappingRule = this.props.definition.getMappingRuleByTargetPath(result.destination.droppableId.replace(MappingConstants_1.MappingConstants.MAPPING_PREFIX_DESTINATION_ITEM, ""));
            if (!oldMappingRule)
                return;
            if (oldMappingRule.id === newMappingRule.id)
                return;
            newMappingRule.mapping.executionResult = oldMappingRule.mapping.getRuleResult();
            newMappingRule.targetPath = oldMappingRule.targetPath;
            if (oldMappingRule.mapping.valueType === ExpressionValueType_1.ExpressionValueType.UNSET) {
                this.props.definition.removeMappingRule(oldMappingRule.id, false);
            }
            else {
                oldMappingRule.targetPath = "";
                oldMappingRule.mapping.executionResult = new UndefinedDataDefinition_1.UndefinedDataDefinition();
            }
            StateManager_1.StateManager.changed(this.props.definition);
        }
    };
    onDragStart = () => {
        this.editContext.isDragging = true;
    };
    RenderMappingBuilder() {
        const { definition } = this.props;
        return ((0, jsx_runtime_1.jsx)(react_beautiful_dnd_1.DragDropContext, { onDragEnd: this.onDragEnd, onBeforeDragStart: this.onDragStart, children: (0, jsx_runtime_1.jsx)(XMappingEditorRender, { children: (0, jsx_runtime_1.jsxs)(react_xarrows_1.Xwrapper, { children: [(0, jsx_runtime_1.jsx)(XMappingSource_1.XMappingSource, { dataDefinition: definition.getInputDefinition(), editContext: this.editContext }), (0, jsx_runtime_1.jsx)(XMappingRules_1.XMappingRules, { definition: definition, editContext: this.editContext }), (0, jsx_runtime_1.jsx)(XMappingDestination_1.XMappingDestination, { editContext: this.editContext, definition: definition }), (0, jsx_runtime_1.jsx)(ObserveMultiState_1.ObserveMultiState, { listenTo: [definition, this.editContext], control: () => ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: definition.mappingRules.map((mappingRule) => {
                                    let paths = mappingRule.getInboundPaths();
                                    let isCollapsed = this.editContext.isDestinationCollapsed(mappingRule.targetPath);
                                    let highlighted = this.editContext.isHighlighted(mappingRule.id);
                                    // if (paths.length === 1) return null;
                                    return ((0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: paths.map((p) => {
                                            let source = this.editContext.sourceDragId(p);
                                            let dest = isCollapsed
                                                ? `${MappingConstants_1.MappingConstants.MAPPING_PREFIX_RULE_ITEM}${mappingRule.targetPath}_connector_formappingrule`
                                                : this.editContext.ruleIdForSource(mappingRule.id);
                                            return ((0, jsx_runtime_1.jsx)(react_xarrows_1.default, { start: source, end: dest, startAnchor: "right", color: highlighted
                                                    ? MappingConstants_1.MappingConstants.HIGHLIGHT_MAPPING_LINE_COLOR
                                                    : MappingConstants_1.MappingConstants.MAPPING_LINE_COLOR, strokeWidth: highlighted ? 2 : 1, showHead: false }, p));
                                        }) }, mappingRule.id));
                                }) })) })] }) }) }));
    }
    render() {
        return ((0, jsx_runtime_1.jsxs)(exports.BuilderRender, { children: [(0, jsx_runtime_1.jsx)(ObserveState_1.ObserveState, { listenTo: this.editContext, properties: ["title"], control: () => {
                        return ((0, jsx_runtime_1.jsx)(Topbar_1.Topbar, { onChangeName: this.onChangedName, editContext: this.editContext, name: this.editContext.mappingBuilderName, isActionDisabled: true, isRequiredActionGroup: false, onSave: this.editContext.onSave
                                ? () => {
                                    if (this.editContext.onSave) {
                                        this.editContext.onSave();
                                    }
                                }
                                : undefined, onClose: this.editContext.onCancel }));
                    } }), (0, jsx_runtime_1.jsx)(ObserveState_1.ObserveState, { listenTo: this.editContext, properties: ["mode"], control: () => ((0, jsx_runtime_1.jsx)(Sidebar_1.Sidebar, { items: this.tabs, value: this.editContext.mode, onChange: (mode) => {
                            Reflect.set(this.editContext, "mode", mode);
                            StateManager_1.StateManager.propertyChanged(this.editContext, "mode");
                        } })) })] }));
    }
}
tslib_1.__decorate([
    AutoBind_1.AutoBind
], MappingBuilder.prototype, "onChangedName", null);
exports.MappingBuilder = MappingBuilder;
const XMappingEditorRender = styled_components_1.default.div `
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: row;
    background: rgba(64, 80, 166, 0.05);
`;
exports.BuilderRender = styled_components_1.default.div `
    width: 100%;
    height: 100vh;
    display: flex;
    flex-direction: column;
`;
//# sourceMappingURL=MappingBuilder.js.map