import { ExpressionValue } from "./ExpressionValue";
import { DataUtilities } from "../Common/DataUtilities";
import { NumberDataDefinition } from "../Common/Data/Definitions/NumberDataDefinition";
import { ExpressionValueType } from "./ExpressionValueType";
export class BaseExpression {
    constructor() {
        this.canSelect = true;
        this._expressionValueType = new NumberDataDefinition();
        this._id = DataUtilities.generateUniqueId();
        this.values = [];
    }
    get expressionValueType() {
        return this._expressionValueType;
    }
    set expressionValueType(expressionValueType) {
        this._expressionValueType = expressionValueType;
    }
    setEditContext(editContext, owner) {
        this.editContext = editContext;
        editContext.register(this, owner);
        for (let v of this.values) {
            v.setEditContext(editContext, this);
        }
    }
    setEditContextWithoutRegister(editContext) {
        this.editContext = editContext;
        for (let v of this.values) {
            v.setEditContext(editContext, this);
        }
    }
    getExpressionValues() {
        return this.values;
    }
    getAllExpressionValues() {
        let values = [...this.getExpressionValues()];
        for (let val of this.getExpressionValues()) {
            if (val.valueType === ExpressionValueType.SUBEXPRESSION && val.subExpression instanceof BaseExpression) {
                values.push(...val.subExpression.getAllExpressionValues());
            }
        }
        return values;
    }
    createExpressionValue(name, createValueType) {
        this.getExpressionValue(name, true, createValueType);
    }
    getExpressionValue(name, createIfMissing = true, createValueType = null) {
        for (let v of this.values) {
            if (v.name === name) {
                return v;
            }
        }
        if (createIfMissing) {
            let v = new ExpressionValue();
            v.name = name;
            if (createValueType)
                v.expectedType = createValueType;
            this.values.push(v);
            return v;
        }
        return null;
    }
    registerExpressionValue(expressionValue) {
        this.values.push(expressionValue);
        if (this.editContext) {
            this.editContext.register(expressionValue, this);
            expressionValue.setEditContext(this.editContext, this);
        }
    }
    // this method can be overridden
    getAllVariables() {
        let output = [];
        if (this.values) {
            for (let f of this.values) {
                output.push(...f.getAllVariables());
            }
        }
        return output;
    }
    // most expressions only have expression values.  The default implementation look for these expresssion values and read/write
    // this data.  These methods can be overridden for other storage.
    getStorageData() {
        let data = {};
        Reflect.set(data, "__type", this.__type);
        for (let fieldName of Object.getOwnPropertyNames(this)) {
            let d = Reflect.get(this, fieldName);
            if (d instanceof ExpressionValue) {
                Reflect.set(data, fieldName, d.getStorageData());
            }
        }
        return data;
    }
    setStorageData(data) {
        for (let fieldName of Object.getOwnPropertyNames(this)) {
            let d = Reflect.get(this, fieldName);
            if (d instanceof ExpressionValue) {
                let evData = Reflect.get(data, fieldName);
                if (evData) {
                    d.setStorageData(evData);
                }
            }
        }
    }
    getValidationIssues() {
        return this.getExpressionValues().reduce((result, current) => {
            result = [...result, ...current.getValidationIssues()];
            return result;
        }, []);
    }
    getVarialbleNames() {
        let variables = [];
        for (const value of this.values) {
            const variableNames = value.getVariableNames();
            if (variableNames && variableNames.length > 0) {
                variables = variables.concat(variableNames);
            }
        }
        const elements = Reflect.get(this, "elements");
        if (elements) {
            for (const value of elements) {
                const variableNames = value.getVariableNames();
                if (variableNames && variableNames.length > 0) {
                    variables = variables.concat(variableNames);
                }
            }
        }
        return variables;
    }
}
//# sourceMappingURL=BaseExpression.js.map