import { jsx as _jsx } from "react/jsx-runtime";
import { ExpressionValueType } from "./ExpressionValueType";
import { ExpressionEditContext } from "./Utilities/ExpressionEditContext";
import { RootExpression } from "./Utilities/RootExpression";
import { DataUtilities } from "../Common/DataUtilities";
import { RuleExecutable } from "../Common/Execution/RuleExecutable";
import { ExpressionTestResult } from "./Testing/ExpressionTestResult";
import { ValidationIssue } from "../Common/IDesignValidationProvider";
import { XExpressionEditor } from "./XExpressionEditor";
import { EventLog, EventLogType } from "../Common/Event/EventLog";
import { ExpressionConstants } from "./ExpressionContants";
export class XExpressionDefinition extends RuleExecutable {
    constructor() {
        super();
        this.canSelect = true;
        this._id = DataUtilities.generateUniqueId();
        this.rootExpression = new RootExpression();
        this.editContext = new ExpressionEditContext(this);
        this.rootExpression.setEditContext(this.editContext, this);
        this.rootExpression.expressionRoot.expectedType = this.getRuleResult();
        this.editContext.definition = this;
    }
    run(data, testContext) {
        // create test context for expression.
        let subContext;
        if (testContext) {
            subContext = new ExpressionTestResult(this._id);
            subContext.render = () => _jsx(XExpressionEditor, { expression: this }, void 0);
            testContext.addTestResultItem(subContext);
            subContext.addLogItem(new EventLog("ExpressionDefinition: start evaluating"));
        }
        try {
            let res = this.rootExpression.evaluate(data, subContext);
            if (subContext) {
                subContext.result = res !== undefined ? res.toString() : "undefined";
                subContext.addLogItem(new EventLog(`ExpressionDefinition: end evaluating with result [${res}]`));
            }
            return res;
        }
        catch (e) {
            if (subContext) {
                subContext.addLogItem(new EventLog(e.message, EventLogType.ERROR));
                subContext.isError = true;
                subContext.result = e.message;
            }
            throw e;
        }
    }
    getAllVariables() {
        let allVars = this.rootExpression.expressionRoot.getAllVariables();
        // remove dups
        return allVars;
    }
    get executionResult() {
        return this._executionResult;
    }
    set executionResult(value) {
        var _a;
        this._executionResult = value;
        this.rootExpression.expressionValueType = this.getRuleResult();
        this.rootExpression.expressionRoot.expectedType = this.getRuleResult();
        if (((_a = this.expression) === null || _a === void 0 ? void 0 : _a.__type) === ExpressionConstants.IfThenExpressionType) {
            this.expression.expressionValueType = this.getRuleResult();
        }
        if (this.editContext)
            this.editContext.refresh();
    }
    setEditContext(selection, owner) {
        this.editContext = selection;
        this.rootExpression.setEditContext(this.editContext, this);
    }
    render() {
        return this.rootExpression.render();
    }
    get expression() {
        return this.rootExpression.expressionRoot.subExpression;
    }
    set expression(value) {
        this.rootExpression.expressionRoot.subExpression = value;
        if (this.editContext)
            this.editContext.refresh();
    }
    get variableName() {
        return this.rootExpression.expressionRoot.variableName;
    }
    set variableName(value) {
        this.rootExpression.expressionRoot.variableName = value;
        if (this.editContext)
            this.editContext.refresh();
    }
    get value() {
        return this.rootExpression.expressionRoot.value;
    }
    set value(value) {
        this.rootExpression.expressionRoot.value = value;
        if (this.editContext)
            this.editContext.refresh();
    }
    get valueType() {
        return this.rootExpression.expressionRoot.valueType;
    }
    set valueType(value) {
        this.rootExpression.expressionRoot.valueType = value;
        if (this.editContext)
            this.editContext.refresh();
    }
    get expressionRoot() {
        return this.rootExpression.expressionRoot;
    }
    getStorageData() {
        let data = super.getStorageData();
        Reflect.set(data, "_id", this._id);
        Reflect.set(data, "rootExpression", this.rootExpression.getStorageData());
        return data;
    }
    setStorageData(data) {
        super.setStorageData(data);
        this._id = Reflect.get(data, "_id");
        this.rootExpression.setStorageData(Reflect.get(data, "rootExpression"));
    }
    getDesignValidationIssues() {
        var _a;
        let issues = [];
        let find = this.requiredVariable ? false : true;
        for (let v of this.rootExpression.getAllExpressionValues()) {
            issues.push(...v.getValidationIssues());
            if (v.valueType === ExpressionValueType.VARIABLE && v.variableName === ((_a = this.requiredVariable) === null || _a === void 0 ? void 0 : _a.name)) {
                find = true;
            }
        }
        if (this.getRuleResult().type !== this.rootExpression.expressionRoot.expectedType.type ||
            this.getRuleResult().list !== this.rootExpression.expressionRoot.expectedType.list) {
            issues.push(new ValidationIssue(`${this.getRuleResult().type} expression not set`));
        }
        if (find) {
            return issues;
        }
        if (this.requiredVariable)
            issues.push(new ValidationIssue(`Expression not using required variable: ${this.requiredVariable.name}`));
        return issues;
    }
    getUsedVariables() {
        var _a;
        const variables = (_a = this.expression) === null || _a === void 0 ? void 0 : _a.getVarialbleNames();
        return variables || [];
    }
    getVariableName() {
        var _a;
        if (this.variableName) {
            return this.variableName;
        }
        else {
            const variables = (_a = this.expression) === null || _a === void 0 ? void 0 : _a.getVarialbleNames();
            if (variables && variables.length > 0) {
                return variables.slice(-1)[0];
            }
            return null;
        }
    }
}
//# sourceMappingURL=XExpressionDefinition.js.map