import { pull } from 'lodash';
export class JinjaVariable {
    constructor(name, value, parent, metadata) {
        Object.defineProperty(this, "name", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "path", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "metadata", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "value", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "listeners", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: []
        });
        this.name = name;
        this.value = value;
        this.path = parent ? `${parent}.${name}` : name;
        this.metadata = metadata;
    }
    get() {
        return this.value;
    }
    set(value) {
        this.value = value;
        this.listeners.forEach(l => l(value));
    }
    onChange(listener) {
        this.listeners.push(listener);
        return () => {
            pull(this.listeners, listener);
        };
    }
}
export class JinjaObjectVariable extends JinjaVariable {
    constructor(name, children, value, parent) {
        super(name, value, parent);
        Object.defineProperty(this, "children", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        this.children = children;
        for (const key in children) {
            const child = children[key];
            // fixme: this can lead to a memory leak (crossed reference).
            // Ideally, this listener would be removed before tearing down this object.
            child.onChange(value => this.set({ ...this.get(), [child.name]: value }));
        }
    }
}
export class JinjaExpressionVariable extends JinjaVariable {
    constructor(name, expression, parent, metadata) {
        super(name, undefined, parent, metadata);
        /**
         * The value of the variable is actually a Jinja expression involving other variables. This may cause dependency cycles which
         * must be identified and throw before running.
         */
        Object.defineProperty(this, "expression", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        this.expression = expression;
    }
}
//# sourceMappingURL=JinjaVariable.js.map