import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import React from "react";
import { Droppable } from "react-beautiful-dnd";
import styled from "styled-components";
import { Collapse, Divider, IconButton, Typography } from "@material-ui/core";
import { DataUtilities } from "../Common/DataUtilities";
import { FormDesignConstants, FormMode, LinkControlType, } from "./FormDesignConstants";
import { UIControlRegistration } from "./Utilities/RegisterUIControl";
import { PropertyEditorInteger } from "../CommonUI/PropertyEditing/PropertyEditorInteger";
import { PropertyEditorBoolean } from "../CommonUI/PropertyEditing/PropertyEditorBoolean";
import { PropertyEditorSelect } from "../CommonUI/PropertyEditing/PropertyEditorSelect";
import { PropertyEditorColor } from "../CommonUI/PropertyEditing/PropertyEditorColor";
import { XStackContainer } from "./Containers/XStackContainer";
import { PropertyEditorTextSizeSelection, PropertyEditorTextStyleSelection, } from "../CommonUI/PropertyEditing/TextSelectionButtonGroups";
import { PinIcon } from "../CommonUI/Icon/PinIcon";
import { ScrollIcon } from "../CommonUI/Icon/ScrollIcon";
import { XContainerDesignWrapper } from "./Utilities/XContainerDesignWrapper";
import { ContainerDiv, ContainerDivider, RowDiv } from "../CommonUI/CommonStyles";
import { RegisterFormElements } from "./registerElements";
import { MultiExecutable, MultiExecutableOutputDefinition } from "../Common/Execution/MultiExecutable";
import { XButton } from "./Controls/XButton";
import { XLink } from "./Controls/XLink";
import { BooleanDataDefinition } from "../Common/Data/Definitions/BooleanDataDefinition";
import { XDataDefinition } from "../Common/Data/XDataDefinition";
import { FormRuleType } from './FormRule';
import { ValidationIssue, } from "../Common/IDesignValidationProvider";
export const PinnedNotifyDiv = styled("div") `
    position: absolute;
    right: calc(100% + ${(props) => (props.moveRightPX ? props.moveRightPX + 34 : 34)}px);
    border-right: solid ${(props) => props.borderWidth || 2}px ${(props) => props.color || "#1873B9"};
    display: flex;
    align-items: center;
    height: 100%;
`;
export const ContainerSectionDiv = styled("div") `
    position: ${(props) => (props.pinned ? "relative" : "static")};
`;
export class XFormConfiguration extends MultiExecutable {
    constructor(container) {
        super();
        this.containers = [];
        this.designFormWidth = FormDesignConstants.DESIGN_WIDTH;
        // setting this to -1 means not set
        this.runtimeWidth = FormDesignConstants.RUNTIME_WIDTH;
        this.gapBetweenContainers = FormDesignConstants.GAP_BETWEEN_CONTAINERS;
        this.formMargin = FormDesignConstants.FORM_MARGIN;
        this.defaultInnerContainerMargin = FormDesignConstants.INNER_CONTAINER_MARGIN;
        this.defaultInnerColumnMargin = FormDesignConstants.INNER_COLUMN_MARGIN;
        this.defaultInterControlSpacing = FormDesignConstants.INTER_CONTROL_SPACING;
        // first container
        this.doNotScrollLastContainerOnForm = false;
        this.doNotScrollFirstContainerOnForm = false;
        this.defaultShowContainerBorder = FormDesignConstants.SHOW_CONTAINER_BORDER;
        this.defaultContainerBorderRadius = FormDesignConstants.CONTAINER_BORDER_RADIOUS;
        this.defaultContainerBorderWidth = FormDesignConstants.CONTAINER_BORDER_WIDTH;
        this.defaultContainerBorderColor = FormDesignConstants.CONTAINER_BORDER_COLOR;
        this.defaultContainerBorderStyle = FormDesignConstants.CONTAINER_BORDER_STYLE;
        this.showLinesBetweenContainers = false;
        this.defaultLineBetweenContainerWidth = FormDesignConstants.CONTAINER_BORDER_WIDTH;
        this.defaultLineBetweenContainerColor = FormDesignConstants.CONTAINER_BORDER_COLOR;
        this.defaultLineBetweenContainerStyle = FormDesignConstants.CONTAINER_BORDER_STYLE;
        this.formBackgroundColor = FormDesignConstants.FORM_BACKGROUND_COLOR;
        this.defaultContainerBackgroundColor = FormDesignConstants.CONTAINER_BACKGROUND_COLOR;
        this.defaultTextStyle = FormDesignConstants.DEFAULT_TEXT_STYLE;
        this.defaultTextSize = FormDesignConstants.DEFAULT_TEXT_SIZE;
        this.defaultButtonSize = FormDesignConstants.DEFAULT_BUTTON_SIZE;
        this.defaultLinkUnderline = FormDesignConstants.DEFAULT_LINK_UNDERLINE;
        this.defaultLinkType = FormDesignConstants.DEFAULT_LINK_TYPE;
        // this is either designer or runtime form
        this._formContext = null;
        this._rules = [];
        this.refreshDesigner = () => {
            var _a;
            if (this._formContext) {
                (_a = this._formContext) === null || _a === void 0 ? void 0 : _a.refreshDesigner();
            }
        };
        // ensure controls are registered.
        RegisterFormElements.doRegistration();
        this.containers = container !== null && container !== void 0 ? container : [];
        if (this.containers) {
            for (let bc of this.containers) {
                if (this._formContext)
                    bc.setFormContext(this._formContext);
            }
        }
    }
    getFormContext() {
        return this._formContext;
    }
    setFormContext(value) {
        if (!value)
            throw new Error("cannot set form context to null (Form Config)");
        this._formContext = value;
        if (value) {
            for (let cont of this.containers) {
                cont.setFormContext(value);
            }
        }
    }
    add(container, index) {
        // set control order
        if (index === undefined || index === null) {
            this.containers.push(container);
        }
        else {
            this.containers.splice(index, 0, container);
        }
        if (this.getFormContext()) {
            container.setFormContext(this.getFormContext());
        }
    }
    remove(control) {
        const index = this.containers.indexOf(control, 0);
        if (index > -1) {
            this.containers.splice(index, 1);
        }
        else {
            for (let cont of this.containers) {
                cont.remove(control);
            }
        }
    }
    setOrder(id, order) {
        let controlToMove;
        for (let c of this.containers) {
            if (c.id === id) {
                controlToMove = c;
            }
        }
        if (controlToMove) {
            this.remove(controlToMove);
            this.add(controlToMove, order);
        }
    }
    getContainers() {
        return this.containers;
    }
    getMode() {
        var _a, _b;
        return (_b = (_a = this.getFormContext()) === null || _a === void 0 ? void 0 : _a.mode) !== null && _b !== void 0 ? _b : FormMode.Runtime;
    }
    getWidth() {
        return this.getMode() === FormMode.Runtime && !!this.runtimeWidth ? this.runtimeWidth : this.designFormWidth;
    }
    getContentWidth() {
        const formWidth = this.getWidth();
        return formWidth - 2 * this.formMargin;
    }
    isDevice() {
        var _a, _b;
        return ([
            FormDesignConstants.FORM_MODE_TABLET_VERTICAL,
            FormDesignConstants.FORM_MODE_TABLET_HORIZONTAL,
            FormDesignConstants.FORM_MODE_PHONE_VERTICAL,
            FormDesignConstants.FORM_MODE_PHONE_HORIZONTAL,
        ].indexOf(((_b = (_a = this.getFormContext()) === null || _a === void 0 ? void 0 : _a.designConfig) === null || _b === void 0 ? void 0 : _b.mode) || "") >= 0);
    }
    getFormDatDefinition() {
        var _a;
        const ruleDataDef = new XDataDefinition();
        const dataDef = this.getInputDefinition();
        const formDataDefFeilds = this.getAllFormData();
        ruleDataDef.fields = [...dataDef.fields, ...formDataDefFeilds];
        const formValue = (_a = this.getFormContext()) === null || _a === void 0 ? void 0 : _a.getFormData();
        if (formValue) {
            ruleDataDef.value = Object.assign(Object.assign({}, dataDef.value), formValue);
        }
        else {
            ruleDataDef.value = dataDef.value;
        }
        return ruleDataDef;
    }
    set rules(rules) {
        this._rules = rules;
        for (let rule of rules) {
            rule.expression.inputData = () => {
                return this.getFormDatDefinition();
            };
            rule.expression.executionResult = new BooleanDataDefinition();
        }
    }
    get rules() {
        return this._rules;
    }
    render() {
        // if there are no containers, ensure we have at least one (stack)
        if (this.containers.length === 0) {
            //	console.log('adding empty xstack')
            this.add(new XStackContainer());
        }
        let mode = this.getMode();
        const formStyles = {
            padding: this.formMargin,
            backgroundColor: this.formBackgroundColor ? this.formBackgroundColor : "#fff",
            position: "relative",
            minHeight: 2 * this.gapBetweenContainers + 75,
        };
        let firstContainer = null;
        let lastContainer = null;
        let scrollableContrainers = this.containers.map((c) => c);
        if (this.doNotScrollFirstContainerOnForm) {
            firstContainer = this.containers[0];
            scrollableContrainers.splice(0, 1);
        }
        if (this.doNotScrollLastContainerOnForm && this.containers.length > 1) {
            lastContainer = this.containers[this.containers.length - 1];
            scrollableContrainers.splice(-1);
        }
        const pinned = (this.doNotScrollFirstContainerOnForm || this.doNotScrollLastContainerOnForm) &&
            scrollableContrainers.length > 0;
        const gap = this.gapBetweenContainers / 2;
        if (mode === FormMode.LayoutDesign) {
            return (_jsx("div", Object.assign({ className: "App", style: formStyles }, { children: _jsx(Droppable, Object.assign({ droppableId: FormDesignConstants.LAYOUT_FORM_KEY_NAME }, { children: (provided, snapshot) => {
                        return (_jsx("div", Object.assign({ ref: provided.innerRef, style: { position: "relative", minHeight: 75 } }, provided.droppableProps, { children: _jsxs(RowDiv, Object.assign({ colGap: gap, hasOverflow: !(this.doNotScrollLastContainerOnForm ||
                                    this.doNotScrollFirstContainerOnForm) }, { children: [firstContainer && (_jsxs(ContainerSectionDiv, Object.assign({ pinned: true }, { children: [_jsx(PinnedNotifyDiv, Object.assign({ moveRightPX: this.formMargin }, { children: _jsx(IconButton, Object.assign({ color: "primary" }, { children: _jsx(PinIcon, {}, void 0) }), void 0) }), void 0),
                                            _jsx(ContainerDiv, Object.assign({ colGap: gap }, { children: _jsx(XContainerDesignWrapper, { id: firstContainer.id, index: 0, innerComponent: firstContainer, editContext: this.getFormContext() }, void 0) }), void 0)] }), void 0)),
                                    _jsxs(ContainerSectionDiv, Object.assign({ pinned: pinned }, { children: [pinned && (_jsx(PinnedNotifyDiv, Object.assign({ color: "#F65C66", moveRightPX: this.formMargin }, { children: _jsx(IconButton, Object.assign({ color: "secondary" }, { children: _jsx(ScrollIcon, {}, void 0) }), void 0) }), void 0)),
                                            scrollableContrainers.map((c, i) => {
                                                return (_jsxs(React.Fragment, { children: [this.showLinesBetweenContainers &&
                                                            (firstContainer || i !== 0) && (_jsx(ContainerDivider, { "data-testid": "line-between-containers", lineColorBetweenContainers: this.defaultLineBetweenContainerColor, lineStyleBetweenContrainers: this.defaultLineBetweenContainerStyle, lineWidthBetweenContainers: this.defaultLineBetweenContainerWidth, colGap: gap }, void 0)),
                                                        _jsx(ContainerDiv, Object.assign({ colGap: gap }, { children: _jsx(XContainerDesignWrapper, { id: c.id, index: i, innerComponent: c, editContext: this.getFormContext() }, void 0) }), void 0)] }, c.id));
                                            })] }), void 0),
                                    lastContainer && (_jsxs(_Fragment, { children: [this.showLinesBetweenContainers && (_jsx(ContainerDivider, { "data-testid": "line-between-containers", lineColorBetweenContainers: this.defaultLineBetweenContainerColor, lineStyleBetweenContrainers: this.defaultLineBetweenContainerStyle, lineWidthBetweenContainers: this.defaultLineBetweenContainerWidth, colGap: gap }, void 0)),
                                            _jsxs(ContainerSectionDiv, Object.assign({ pinned: true }, { children: [_jsx(PinnedNotifyDiv, Object.assign({ moveRightPX: this.formMargin }, { children: _jsx(IconButton, Object.assign({ color: "primary" }, { children: _jsx(PinIcon, {}, void 0) }), void 0) }), void 0),
                                                    _jsx(ContainerDiv, Object.assign({ colGap: gap }, { children: _jsx(XContainerDesignWrapper, { id: lastContainer.id, index: this.containers.length - 1, innerComponent: lastContainer, editContext: this.getFormContext() }, void 0) }), void 0)] }), void 0)] }, void 0)), provided.placeholder] }), void 0) }), void 0));
                    } }), "baselayoutform") }), "baseformcontainer"));
        }
        else if ((this.isDevice() || mode === FormMode.Runtime) &&
            (this.doNotScrollLastContainerOnForm || this.doNotScrollFirstContainerOnForm) &&
            this.containers.length > 0) {
            formStyles.height = "100%";
            return (_jsx("div", Object.assign({ className: "App", style: formStyles }, { children: _jsxs(RowDiv, Object.assign({ colGap: gap, style: { flexFlow: "column", maxHeight: "100%", overflow: "hidden", display: "flex" } }, { children: [firstContainer && (_jsx(ContainerDiv, Object.assign({ colGap: gap }, { children: _jsx(XContainerDesignWrapper, { id: firstContainer.id, index: 0, innerComponent: firstContainer, editContext: this.getFormContext() }, void 0) }), void 0)),
                        _jsx("div", Object.assign({ style: {
                                flex: 1,
                                overflowY: "auto",
                                overflowX: "hidden",
                                position: pinned ? "relative" : "static",
                            }, "data-testid": "no-pinned-section" }, { children: scrollableContrainers.map((c, i) => {
                                return (_jsxs(React.Fragment, { children: [this.showLinesBetweenContainers && (firstContainer || i !== 0) && (_jsx(ContainerDivider, { "data-testid": "line-between-containers", lineColorBetweenContainers: this.defaultLineBetweenContainerColor, lineStyleBetweenContrainers: this.defaultLineBetweenContainerStyle, lineWidthBetweenContainers: this.defaultLineBetweenContainerWidth, colGap: gap }, void 0)),
                                        _jsx(ContainerDiv, Object.assign({ colGap: gap }, { children: _jsx(XContainerDesignWrapper, { id: c.id, index: firstContainer ? i + 1 : i, innerComponent: c, editContext: this.getFormContext() }, void 0) }), void 0)] }, c.id));
                            }) }), void 0),
                        lastContainer && (_jsx(ContainerDiv, Object.assign({ colGap: gap }, { children: _jsxs(_Fragment, { children: [this.showLinesBetweenContainers && (_jsx(ContainerDivider, { "data-testid": "line-between-containers", lineColorBetweenContainers: this.defaultLineBetweenContainerColor, lineStyleBetweenContrainers: this.defaultLineBetweenContainerStyle, lineWidthBetweenContainers: this.defaultLineBetweenContainerWidth, colGap: gap }, void 0)),
                                    _jsx(XContainerDesignWrapper, { id: lastContainer.id, index: this.containers.length - 1, innerComponent: lastContainer, editContext: this.getFormContext() }, void 0)] }, void 0) }), void 0))] }), void 0) }), "form"));
        }
        else {
            return (_jsx("div", Object.assign({ className: "App", style: formStyles }, { children: _jsxs(RowDiv, Object.assign({ colGap: gap, hasOverflow: mode !== FormMode.Runtime &&
                        !(this.doNotScrollLastContainerOnForm || this.doNotScrollFirstContainerOnForm) }, { children: [firstContainer && (_jsxs(ContainerSectionDiv, Object.assign({ pinned: true, "data-testid": "pin-first-container" }, { children: [_jsx(PinnedNotifyDiv, Object.assign({ moveRightPX: this.formMargin }, { children: _jsx(IconButton, Object.assign({ color: "primary" }, { children: _jsx(PinIcon, {}, void 0) }), void 0) }), void 0),
                                _jsx(ContainerDiv, Object.assign({ colGap: gap }, { children: _jsx(XContainerDesignWrapper, { id: firstContainer.id, index: 0, innerComponent: firstContainer, editContext: this.getFormContext() }, void 0) }), void 0)] }), void 0)),
                        _jsxs(ContainerSectionDiv, Object.assign({ pinned: pinned }, { children: [pinned && (_jsx(PinnedNotifyDiv, Object.assign({ color: "#F65C66", moveRightPX: this.formMargin, "data-testid": "pin-middle-container" }, { children: _jsx(IconButton, Object.assign({ color: "secondary" }, { children: _jsx(ScrollIcon, {}, void 0) }), void 0) }), void 0)),
                                scrollableContrainers.map((c, i) => {
                                    return (_jsxs(React.Fragment, { children: [this.showLinesBetweenContainers && (firstContainer || i !== 0) && (_jsx(ContainerDivider, { "data-testid": "line-between-containers", lineColorBetweenContainers: this.defaultLineBetweenContainerColor, lineStyleBetweenContrainers: this.defaultLineBetweenContainerStyle, lineWidthBetweenContainers: this.defaultLineBetweenContainerWidth, colGap: gap }, void 0)),
                                            _jsx(ContainerDiv, Object.assign({ colGap: gap }, { children: _jsx(XContainerDesignWrapper, { id: c.id, index: i, innerComponent: c, editContext: this.getFormContext() }, void 0) }), void 0)] }, c.id));
                                })] }), void 0),
                        lastContainer && (_jsxs(_Fragment, { children: [this.showLinesBetweenContainers && (_jsx(ContainerDivider, { "data-testid": "line-between-containers", lineColorBetweenContainers: this.defaultLineBetweenContainerColor, lineStyleBetweenContrainers: this.defaultLineBetweenContainerStyle, lineWidthBetweenContainers: this.defaultLineBetweenContainerWidth, colGap: gap }, void 0)),
                                _jsxs(ContainerSectionDiv, Object.assign({ pinned: true, "data-testid": "pin-last-container" }, { children: [_jsx(PinnedNotifyDiv, Object.assign({ moveRightPX: this.formMargin }, { children: _jsx(IconButton, Object.assign({ color: "primary" }, { children: _jsx(PinIcon, {}, void 0) }), void 0) }), void 0),
                                        _jsx(ContainerDiv, Object.assign({ colGap: gap }, { children: _jsx(XContainerDesignWrapper, { id: lastContainer.id, index: this.containers.length - 1, innerComponent: lastContainer, editContext: this.getFormContext() }, void 0) }), void 0)] }), void 0)] }, void 0))] }), void 0) }), "form"));
        }
    }
    find(id) {
        if (!this.containers)
            return null;
        for (let cont of this.containers) {
            if (cont.id === id)
                return cont;
            let res = cont.find(id);
            if (res)
                return res;
        }
        return null;
    }
    getAllControls() {
        let controls;
        controls = [];
        for (let container of this.containers) {
            controls.push(...container.getControls());
        }
        return controls;
    }
    getStorageData() {
        let retData = DataUtilities.cloneWithoutReact(this, [
            "containers",
            "host",
            "_formContext",
            "_formRuntimeContext",
        ]);
        let containers = [];
        for (let container of this.containers) {
            containers.push(container.getStorageData());
        }
        Reflect.set(retData, "__containers", containers);
        return retData;
    }
    setStorageData(data) {
        DataUtilities.spreadData(this, data, ["__containers"]);
        this.containers = [];
        let containerArray = Reflect.get(data, "__containers");
        let editContext = this.getFormContext();
        if (containerArray && containerArray instanceof Array && containerArray.length !== 0) {
            for (let container of containerArray) {
                let typeName = Reflect.get(container, "__type");
                if (typeName) {
                    let registeredControl = UIControlRegistration[typeName];
                    let val = new registeredControl.prototype.constructor();
                    // @ts-ignore
                    let control = val;
                    if (editContext)
                        control.setFormContext(editContext);
                    control.setStorageData(container);
                    this.containers.push(control);
                }
            }
        }
    }
    renderEditUI() {
        return (_jsxs(_Fragment, { children: [_jsx(PropertyEditorBoolean, { editObject: this, label: "Layout Borders", propertyName: "defaultShowContainerBorder", updateCallback: this.refreshDesigner }, void 0),
                _jsxs(Collapse, Object.assign({ in: this.defaultShowContainerBorder }, { children: [_jsx(PropertyEditorInteger, { editObject: this, label: "Borders Width", propertyName: "defaultContainerBorderWidth", updateCallback: this.refreshDesigner }, void 0),
                        _jsx(PropertyEditorInteger, { editObject: this, label: "Borders Radius", propertyName: "defaultContainerBorderRadius", updateCallback: this.refreshDesigner }, void 0),
                        _jsx(PropertyEditorColor, { editObject: this, label: "Borders Color", propertyName: "defaultContainerBorderColor", updateCallback: this.refreshDesigner, parentDefaultValue: FormDesignConstants.FORM_BACKGROUND_COLOR }, void 0),
                        _jsx(PropertyEditorSelect, { editObject: this, label: "Borders Style", propertyName: "defaultContainerBorderStyle", updateCallback: this.refreshDesigner, options: FormDesignConstants.BORDER_STYLES }, void 0)] }), void 0),
                _jsx(PropertyEditorColor, { editObject: this, label: "Form Color", propertyName: "formBackgroundColor", updateCallback: this.refreshDesigner, parentDefaultValue: FormDesignConstants.FORM_BACKGROUND_COLOR }, void 0),
                _jsx(Typography, Object.assign({ color: "textSecondary", display: "block", variant: "caption", style: { marginTop: FormDesignConstants.FORM_SECTION_MARGIN } }, { children: "Pinned Sections" }), void 0),
                _jsx(Divider, {}, void 0),
                _jsx(PropertyEditorBoolean, { label: "Pin First Container", editObject: this, propertyName: "doNotScrollFirstContainerOnForm", updateCallback: this.refreshDesigner }, void 0),
                _jsx(PropertyEditorBoolean, { label: "Pin Last Container", editObject: this, propertyName: "doNotScrollLastContainerOnForm", updateCallback: this.refreshDesigner }, void 0),
                _jsx(Typography, Object.assign({ color: "textSecondary", display: "block", variant: "caption", style: { marginTop: FormDesignConstants.FORM_SECTION_MARGIN } }, { children: "Form Size" }), void 0),
                _jsx(Divider, {}, void 0),
                _jsx(PropertyEditorInteger, { label: "Design Form Width", editObject: this, propertyName: "designFormWidth", updateCallback: this.refreshDesigner }, void 0),
                _jsx(PropertyEditorInteger, { label: "Runtime Width", editObject: this, propertyName: "runtimeWidth", updateCallback: this.refreshDesigner }, void 0),
                _jsx(Typography, Object.assign({ color: "textSecondary", display: "block", variant: "caption", style: { marginTop: FormDesignConstants.FORM_SECTION_MARGIN } }, { children: "Spacing" }), void 0),
                _jsx(Divider, {}, void 0),
                _jsx(PropertyEditorInteger, { label: "Between Layouts", editObject: this, propertyName: "gapBetweenContainers", updateCallback: this.refreshDesigner, parentDefaultValue: FormDesignConstants.GAP_BETWEEN_CONTAINERS }, void 0),
                _jsx(PropertyEditorBoolean, { editObject: this, label: "Line Between Containers", propertyName: "showLinesBetweenContainers", updateCallback: this.refreshDesigner }, void 0),
                _jsxs(Collapse, Object.assign({ in: this.showLinesBetweenContainers }, { children: [_jsx(PropertyEditorInteger, { editObject: this, label: "Line Width", propertyName: "defaultLineBetweenContainerWidth", updateCallback: this.refreshDesigner }, void 0),
                        _jsx(PropertyEditorColor, { editObject: this, label: "Line Color", propertyName: "defaultLineBetweenContainerColor", updateCallback: this.refreshDesigner }, void 0),
                        _jsx(PropertyEditorSelect, { editObject: this, label: "Line Style", propertyName: "defaultLineBetweenContainerStyle", updateCallback: this.refreshDesigner, options: FormDesignConstants.BORDER_STYLES }, void 0)] }), void 0),
                _jsx(PropertyEditorInteger, { label: "Around Form", editObject: this, propertyName: "formMargin", updateCallback: this.refreshDesigner }, void 0),
                _jsx(Typography, Object.assign({ color: "textSecondary", display: "block", variant: "caption", style: { marginTop: FormDesignConstants.FORM_SECTION_MARGIN } }, { children: "Default Text Field Style" }), void 0),
                _jsx(Divider, {}, void 0),
                _jsx(PropertyEditorTextStyleSelection, { updateCallback: this.refreshDesigner, propertyName: "defaultTextStyle", editObject: this }, void 0),
                _jsx(PropertyEditorTextSizeSelection, { updateCallback: this.refreshDesigner, propertyName: "defaultTextSize", editObject: this }, void 0),
                _jsx(Typography, Object.assign({ color: "textSecondary", display: "block", variant: "caption", style: { marginTop: FormDesignConstants.FORM_SECTION_MARGIN } }, { children: "Defaults" }), void 0),
                _jsx(Divider, {}, void 0),
                _jsx(PropertyEditorInteger, { label: "Container Inner Margin", editObject: this, propertyName: "defaultInnerContainerMargin", updateCallback: this.refreshDesigner }, void 0),
                _jsx(PropertyEditorInteger, { label: "Column Inner Margin", editObject: this, propertyName: "defaultInnerColumnMargin", updateCallback: this.refreshDesigner }, void 0),
                _jsx(PropertyEditorInteger, { label: "Space Between Controls", editObject: this, propertyName: "defaultInterControlSpacing", updateCallback: this.refreshDesigner }, void 0),
                _jsx(PropertyEditorColor, { editObject: this, label: "Container Color", propertyName: "defaultContainerBackgroundColor", updateCallback: this.refreshDesigner, parentDefaultValue: FormDesignConstants.CONTAINER_BACKGROUND_COLOR }, void 0)] }, void 0));
    }
    // this is all the form data, both input and output
    getAllFormData() {
        const controls = this.getAllControls();
        const formDataDefs = [];
        for (const control of controls) {
            const controlDataDef = control.getAddedData();
            if (controlDataDef) {
                if (Array.isArray(controlDataDef)) {
                    formDataDefs.concat(controlDataDef);
                }
                else {
                    formDataDefs.push(controlDataDef);
                }
            }
        }
        return formDataDefs;
        // todo: needs to be completed
        // - input data
        // - all controls, add the data
        //  - if a value is not a root value, can eliminate it here.  like person.name.
    }
    getOutcomes() {
        let result = [];
        for (let c of this.containers) {
            for (let cnt of c.getControls()) {
                if (cnt instanceof XButton) {
                    // should look at all buttons, and return.  later we will gather the data we need for each button
                    result.push(new MultiExecutableOutputDefinition(cnt.getOutcomeName(), []));
                }
                else if (cnt instanceof XLink) {
                    if (cnt.type === LinkControlType.ACTION) {
                        result.push(new MultiExecutableOutputDefinition(cnt.getOutcomeName(), []));
                    }
                }
                //todo: add the data to each
            }
        }
        // todo: if no outcomes are defined, need to add general one
        // todo: what if a piece of data is outside the outcome
        return result;
    }
    getRuleValidationIssues(fieldName) {
        const validationIssues = [];
        const runableRules = this.getRunableRules(fieldName);
        const data = this.getFormDatDefinition().value;
        for (const rule of runableRules.filter(rule => rule.ruleType === FormRuleType.VALIDATION)) {
            const ruleResult = rule.expression.run(data, undefined);
            if (ruleResult) {
                const message = Reflect.get(rule.data, "validationMessage");
                const variable = Reflect.get(rule.data, "controlId");
                if (variable) {
                    validationIssues.push(new ValidationIssue(message, variable));
                }
            }
        }
        return validationIssues;
    }
    dataChangeByRule(fieldName) {
        const runableRules = this.getRunableRules(fieldName);
        const data = this.getFormDatDefinition().value;
        for (const rule of runableRules.filter(rule => rule.ruleType === FormRuleType.CHANGE_VALUE)) {
            const ruleResult = rule.expression.run(data, undefined);
            if (ruleResult) {
                const datapath = Reflect.get(rule.data, "dataPath");
                const value = Reflect.get(rule.data, "value");
                const valueResult = value.run(data, undefined);
                this.getFormContext().setFormDataValue(datapath, valueResult);
            }
        }
    }
    hideControlByRule() {
        const runableRules = this.rules;
        const data = this.getFormDatDefinition().value;
        let hideControls = [];
        for (const rule of runableRules.filter(rule => rule.ruleType === FormRuleType.CONTROL_VISIBILITY)) {
            const ruleResult = rule.expression.run(data, undefined);
            if (ruleResult) {
                const controlId = Reflect.get(rule.data, "controlId");
                if (typeof controlId === 'object') {
                    hideControls = [...hideControls, ...controlId];
                }
                else {
                    hideControls.push(controlId);
                }
            }
        }
        this.getFormContext().runtimeContext.hideControls = hideControls;
    }
    disableControlByRule() {
        const runableRules = this.rules;
        const data = this.getFormDatDefinition().value;
        let disabledControls = [];
        for (const rule of runableRules.filter(rule => rule.ruleType === FormRuleType.CONTROL_ENABLED)) {
            const ruleResult = rule.expression.run(data, undefined);
            if (ruleResult) {
                const controlId = Reflect.get(rule.data, "controlId");
                if (typeof controlId === 'object') {
                    disabledControls = [...disabledControls, ...controlId];
                }
                else {
                    disabledControls.push(controlId);
                }
            }
        }
        this.getFormContext().runtimeContext.disabledControls = disabledControls;
    }
    focusControlByRule() {
        const runableRules = this.rules;
        const data = this.getFormDatDefinition().value;
        let focusControls = [];
        for (const rule of runableRules.filter(rule => rule.ruleType === FormRuleType.CHANGE_FOCUS)) {
            try {
                const ruleResult = rule.expression.run(data, undefined);
                if (ruleResult) {
                    const controlId = Reflect.get(rule.data, "controlId");
                    if (typeof controlId === 'object') {
                        focusControls = [...focusControls, ...controlId];
                    }
                    else {
                        focusControls.push(controlId);
                    }
                }
            }
            catch (e) {
                console.error(e);
            }
        }
        for (const focusControl of focusControls) {
            const control = this.find(focusControl);
            if (control && control.ref.current) {
                control.focusControl();
            }
        }
    }
    getRunableRules(fieldName) {
        const runableRules = [];
        for (const rule of this.rules) {
            const watchingValuesMode = rule.watchingValuesMode;
            let watchingValues = rule.watchingValues;
            if (watchingValuesMode === 'value used in rule') {
                watchingValues = rule.expression.getUsedVariables();
            }
            if (rule.enabled && watchingValues.indexOf(fieldName) > -1 && rule.getDesignValidationIssues(this).length === 0) {
                runableRules.push(rule);
            }
        }
        return runableRules;
    }
    // todo: this needs to be a callback type
    run(data, testContext) {
        throw new Error("Method not implemented.");
    }
    toString() {
        return "Form Config";
    }
}
//# sourceMappingURL=XFormConfiguration.js.map