import { DataUtilities } from "../Common/DataUtilities";
import { ValidationIssue } from "../Common/IDesignValidationProvider";
import { XExpressionDefinition } from "../Expressions/XExpressionDefinition";
export var FormRuleType;
(function (FormRuleType) {
    FormRuleType["VALIDATION"] = "Data Validation";
    FormRuleType["CONTROL_ENABLED"] = "Control Enabled";
    FormRuleType["CONTROL_VISIBILITY"] = "Control Visibility";
    FormRuleType["CHANGE_VALUE"] = "Change Value";
    FormRuleType["EXIT_FORM"] = "Exit Form";
    FormRuleType["CHANGE_FOCUS"] = "Change Focus";
})(FormRuleType || (FormRuleType = {}));
// todo: implement config storage and validation
// todo: unit test config storage and validation
// todo: unit test form config storage and validation
class FormRuleData {
    constructor(type) {
        this.type = type;
    }
    getStorageData() {
        let obj = {};
        Reflect.set(obj, "type", this.type);
        return obj;
    }
    setStorageData(data) {
        this.type = Reflect.get(data, "type");
    }
}
export class FormRuleValidationData extends FormRuleData {
    constructor(validationMessage, controlId) {
        super(FormRuleType.VALIDATION);
        this.validationMessage = validationMessage;
        this.controlId = controlId;
    }
    getStorageData() {
        let obj = {};
        obj = super.getStorageData();
        Reflect.set(obj, "validationMessage", this.validationMessage);
        return obj;
    }
    setStorageData(data) {
        super.setStorageData(data);
        this.validationMessage = Reflect.get(data, "validationMessage");
    }
    getDesignValidationIssues(form) {
        let issues = [];
        if (this.validationMessage === "") {
            issues.push(new ValidationIssue("Validation Message is missing!"));
        }
        if (this.controlId === "") {
            issues.push(new ValidationIssue("datapath is missing!"));
        }
        try {
            DataUtilities.getFieldFromDataDefinitionByProperty(form.getFormDatDefinition().fields, this.controlId, "name");
        }
        catch (e) {
            if (e.message === `Can not find the field by path: ${this.controlId}`) {
                issues.push(new ValidationIssue("Datapath is not valid!"));
            }
        }
        return issues;
    }
}
export class FormRuleControlVisibilityData extends FormRuleData {
    constructor(controlId) {
        super(FormRuleType.CONTROL_VISIBILITY);
        this.controlId = controlId;
    }
    getStorageData() {
        let obj = {};
        obj = super.getStorageData();
        Reflect.set(obj, "controlId", this.controlId);
        return obj;
    }
    setStorageData(data) {
        super.setStorageData(data);
        this.controlId = Reflect.get(data, "controlId");
    }
    getDesignValidationIssues(form) {
        let issues = [];
        if (this.controlId === "") {
            issues.push(new ValidationIssue("Control Id is missing!"));
        }
        if (typeof this.controlId === 'string' && form.find(this.controlId) === null) {
            issues.push(new ValidationIssue("Control Id is not valid!"));
        }
        if (typeof this.controlId === 'object') {
            for (const controlId of this.controlId) {
                if (form.find(controlId) === null) {
                    issues.push(new ValidationIssue(`Control Id ${controlId} is not valid!`));
                }
            }
        }
        return issues;
    }
}
export class FormRuleControlEnabledData extends FormRuleData {
    constructor(controlId) {
        super(FormRuleType.CONTROL_ENABLED);
        this.controlId = controlId;
    }
    getStorageData() {
        let obj = {};
        obj = super.getStorageData();
        Reflect.set(obj, "controlId", this.controlId);
        return obj;
    }
    setStorageData(data) {
        super.setStorageData(data);
        this.controlId = Reflect.get(data, "controlId");
    }
    getDesignValidationIssues(form) {
        let issues = [];
        if (this.controlId === "") {
            issues.push(new ValidationIssue("Control Id is missing!"));
        }
        if (typeof this.controlId === 'string' && form.find(this.controlId) === null) {
            issues.push(new ValidationIssue("Control Id is not valid!"));
        }
        if (typeof this.controlId === 'object') {
            for (const controlId of this.controlId) {
                if (form.find(controlId) === null) {
                    issues.push(new ValidationIssue(`Control Id ${controlId} is not valid!`));
                }
            }
        }
        return issues;
    }
}
export class FormRuleChangeFocusData extends FormRuleData {
    constructor(controlId) {
        super(FormRuleType.CHANGE_FOCUS);
        this.controlId = controlId;
    }
    getStorageData() {
        let obj = {};
        obj = super.getStorageData();
        Reflect.set(obj, "controlId", this.controlId);
        return obj;
    }
    setStorageData(data) {
        super.setStorageData(data);
        this.controlId = Reflect.get(data, "controlId");
    }
    getDesignValidationIssues(form) {
        let issues = [];
        if (this.controlId === "") {
            issues.push(new ValidationIssue("Control Id is missing!"));
        }
        if (typeof this.controlId === 'string' && form.find(this.controlId) === null) {
            issues.push(new ValidationIssue("Control Id is not valid!"));
        }
        if (typeof this.controlId === 'object') {
            for (const controlId of this.controlId) {
                if (form.find(controlId) === null) {
                    issues.push(new ValidationIssue(`Control Id ${controlId} is not valid!`));
                }
            }
        }
        return issues;
    }
}
export class FormRuleChangeValueData extends FormRuleData {
    constructor(dataPath, value) {
        super(FormRuleType.CHANGE_VALUE);
        this.dataPath = dataPath;
        this.value = value;
    }
    getStorageData() {
        let obj = {};
        obj = super.getStorageData();
        Reflect.set(obj, "dataPath", this.dataPath);
        Reflect.set(obj, "value", this.value.getStorageData());
        return obj;
    }
    setStorageData(data) {
        super.setStorageData(data);
        this.dataPath = Reflect.get(data, "dataPath");
        this.value.setStorageData(Reflect.get(data, "value"));
    }
    getDesignValidationIssues(form) {
        let issues = [];
        if (this.dataPath === "") {
            issues.push(new ValidationIssue("Data Path is missing!"));
        }
        // try {
        //     DataUtilities.getFieldFromDataDefinitionByProperty(form.getFormDatDefinition().fields, this.dataPath, "name");
        // } catch (e: any) {
        //     if (e.message === `Can not find the field by path: ${this.dataPath}`) {
        //         issues.push(new ValidationIssue("Value Change Path is not valid!"));
        //     }
        // }
        return [...issues, ...this.value.expressionRoot.getValidationIssues()];
    }
}
export class FormRuleExitFormData extends FormRuleData {
    constructor(exitOnPath) {
        super(FormRuleType.EXIT_FORM);
        this.exitOnPath = exitOnPath;
    }
    getStorageData() {
        let obj = {};
        obj = super.getStorageData();
        Reflect.set(obj, "exitOnPath", this.exitOnPath);
        return obj;
    }
    setStorageData(data) {
        super.setStorageData(data);
        this.exitOnPath = Reflect.get(data, "exitOnPath");
    }
    getDesignValidationIssues(form) {
        let issues = [];
        if (this.exitOnPath === "") {
            issues.push(new ValidationIssue("Exit on Path is missing!"));
        }
        // try {
        //     DataUtilities.getFieldFromDataDefinitionByProperty(form.getFormDatDefinition().fields, this.exitOnPath, "name");
        // } catch (e: any) {
        //     if (e.message === `Can not find the field by path: ${this.exitOnPath}`) {
        //         issues.push(new ValidationIssue("Exit on Path is not valid!"));
        //     }
        // }
        return issues;
    }
}
export class FormRule {
    constructor(expression, watchingValues = [], watchingValuesMode = 'value used in rule') {
        this.enabled = true;
        this._ruleType = FormRuleType.VALIDATION;
        this.expression = expression;
        this.watchingValues = watchingValues;
        this.watchingValuesMode = watchingValuesMode;
        this.data = new FormRuleValidationData("", "");
    }
    getStorageData() {
        var _a;
        let obj = {};
        Reflect.set(obj, "enabled", this.enabled);
        Reflect.set(obj, "ruleType", this.ruleType);
        Reflect.set(obj, "expression", this.expression.getStorageData());
        Reflect.set(obj, "watchingValues", this.watchingValues);
        Reflect.set(obj, "watchingValuesMode", this.watchingValuesMode);
        Reflect.set(obj, "data", (_a = this.data) === null || _a === void 0 ? void 0 : _a.getStorageData());
        return obj;
    }
    setStorageData(data) {
        var _a;
        this.enabled = Reflect.get(data, "enabled");
        this.ruleType = Reflect.get(data, "ruleType");
        this.expression.setStorageData(Reflect.get(data, "expression"));
        this.watchingValues = Reflect.get(data, "watchingValues");
        this.watchingValuesMode = Reflect.get(data, "watchingValuesMode");
        (_a = this.data) === null || _a === void 0 ? void 0 : _a.setStorageData(Reflect.get(data, "data"));
    }
    getDesignValidationIssues(form) {
        var _a;
        let issues = ((_a = this.data) === null || _a === void 0 ? void 0 : _a.getDesignValidationIssues(form)) || [];
        if (!this.data) {
            issues.push(new ValidationIssue("Data is missing"));
        }
        if (!this.expression) {
            issues.push(new ValidationIssue("Expression is missing"));
        }
        else {
            issues.concat(this.expression.getDesignValidationIssues());
        }
        return issues;
    }
    set ruleType(type) {
        switch (type) {
            case FormRuleType.VALIDATION:
                this.data = new FormRuleValidationData("", "");
                break;
            case FormRuleType.CHANGE_FOCUS:
                this.data = new FormRuleChangeFocusData("");
                break;
            case FormRuleType.CHANGE_VALUE:
                let value = new XExpressionDefinition();
                value.inputData = () => {
                    return this.expression.getInputDefinition();
                };
                this.data = new FormRuleChangeValueData("", value);
                break;
            case FormRuleType.EXIT_FORM:
                this.data = new FormRuleExitFormData("");
                break;
            case FormRuleType.CONTROL_ENABLED:
                this.data = new FormRuleControlEnabledData("");
                break;
            case FormRuleType.CONTROL_VISIBILITY:
                this.data = new FormRuleControlVisibilityData("");
                break;
        }
        this._ruleType = type;
    }
    get ruleType() {
        return this._ruleType;
    }
}
//# sourceMappingURL=FormRule.js.map