import { __values } from "tslib";
import _ from "lodash";
/**
 * A class implementing the cascade mode for multi article traversal.
 * A cascade starts with a MA and lists all its properties and available values.
 * After setting a value, properties of the descendants which fit the config are also shown.
 */
var CascadeMode = /** @class */ (function () {
    /**
     * The constructor
     * @param multiArticles
     * @param root
     */
    function CascadeMode(multiArticles, root) {
        this.multiArticles = multiArticles;
        this._root = root;
        this.rootDescendants = this.multiArticles.getDescendants(this._root);
        this.rootConfiguration = this.multiArticles.getConfiguration(this._root);
        this.rootProperties = this.multiArticles.accumulatedProperties(this._root);
    }
    Object.defineProperty(CascadeMode.prototype, "root", {
        get: function () {
            return this._root;
        },
        set: function (newRoot) {
            this._root = newRoot;
            this.rootDescendants = this.multiArticles.getDescendants(this._root);
            this.rootConfiguration = this.multiArticles.getConfiguration(this._root);
            this.rootProperties = this.multiArticles.accumulatedProperties(this._root);
        },
        enumerable: true,
        configurable: true
    });
    /**
     * Get all properties for the configuration
     * @param configuration
     * @returns {any}
     */
    CascadeMode.prototype.getProperties = function (configuration) {
        var _this = this;
        // if nothing is set in the configuration, return just the root properties
        if (_.isEmpty(configuration)) {
            return this.rootProperties;
        }
        // for an article to be viable, it has to implement at least one property that is set in the configuration.
        var articlesFittingConfiguration = this.rootDescendants.filter(function (article) {
            var accumulatedArticleProperties = _this.multiArticles.accumulatedProperties(article);
            return accumulatedArticleProperties.some(function (prop) {
                return Boolean(configuration[prop]);
            });
        });
        var articleProperties = _.flatMap(articlesFittingConfiguration, function (article) { return _this.multiArticles.getProperties(article); });
        return _.uniq(this.rootProperties.concat(articleProperties));
    };
    /**
     * Get all property values. For this, look for articles that match the configuration.
     * The article is allowed to differ in its own properties.
     * @param property
     * @param configuration
     * @returns possible property values
     */
    CascadeMode.prototype.getPropertyValues = function (property, configuration) {
        var e_1, _a, e_2, _b, e_3, _c;
        if (this.rootConfiguration[property]) {
            return [this.rootConfiguration[property]];
        }
        var viableArticles = new Array();
        // if the property was set, to get all available properties we have to also consider the root element
        // this is to ensure that we can unset a previously set property
        if (configuration && configuration[property]) {
            viableArticles.push(this._root);
        }
        try {
            for (var _d = __values(this.rootDescendants), _e = _d.next(); !_e.done; _e = _d.next()) {
                var rootDescendant = _e.value;
                if (this.multiArticles.matchesConfigExceptForOwnProperties(rootDescendant, configuration)) {
                    viableArticles.push(rootDescendant);
                }
            }
        }
        catch (e_1_1) { e_1 = { error: e_1_1 }; }
        finally {
            try {
                if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
            }
            finally { if (e_1) throw e_1.error; }
        }
        var uniquePropValues = new Array();
        try {
            for (var viableArticles_1 = __values(viableArticles), viableArticles_1_1 = viableArticles_1.next(); !viableArticles_1_1.done; viableArticles_1_1 = viableArticles_1.next()) {
                var article = viableArticles_1_1.value;
                var propValues = this.multiArticles.getPropertyValues(article, property);
                try {
                    for (var propValues_1 = (e_3 = void 0, __values(propValues)), propValues_1_1 = propValues_1.next(); !propValues_1_1.done; propValues_1_1 = propValues_1.next()) {
                        var propValue = propValues_1_1.value;
                        if (uniquePropValues.indexOf(propValue) === -1) {
                            uniquePropValues.push(propValue);
                        }
                    }
                }
                catch (e_3_1) { e_3 = { error: e_3_1 }; }
                finally {
                    try {
                        if (propValues_1_1 && !propValues_1_1.done && (_c = propValues_1.return)) _c.call(propValues_1);
                    }
                    finally { if (e_3) throw e_3.error; }
                }
            }
        }
        catch (e_2_1) { e_2 = { error: e_2_1 }; }
        finally {
            try {
                if (viableArticles_1_1 && !viableArticles_1_1.done && (_b = viableArticles_1.return)) _b.call(viableArticles_1);
            }
            finally { if (e_2) throw e_2.error; }
        }
        return uniquePropValues;
    };
    return CascadeMode;
}());
export default CascadeMode;
