import { __rest, __values } from "tslib";
import _ from "lodash";
/**
 * A class implementing the restricted cascade mode for multi article traversal.
 * A cascade starts with discrete articles and lists all its properties and available values.
 * After setting a value, properties of the descendants which fit the config are also shown.
 */
var RestrictedCascadeMode = /** @class */ (function () {
    /**
     * The constructor
     * @param multiArticles
     * @param root
     */
    function RestrictedCascadeMode(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(RestrictedCascadeMode.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}
     */
    RestrictedCascadeMode.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 discrete articles that match the configuration.
     * @param property
     * @param configuration
     * @returns possible property values
     */
    RestrictedCascadeMode.prototype.getPropertyValues = function (property, configuration) {
        var e_1, _a, e_2, _b, e_3, _c;
        // delete "property" entry by destructuring
        var _d = property, propertyValue = configuration[_d], copiedConfigWithoutPropertyFromParameter = __rest(configuration, [typeof _d === "symbol" ? _d : _d + ""]);
        if (this.rootConfiguration[property]) {
            return [this.rootConfiguration[property]];
        }
        var viableArticles = new Array();
        try {
            for (var _e = __values(this.rootDescendants), _f = _e.next(); !_f.done; _f = _e.next()) {
                var rootDescendant = _f.value;
                // explicitly ignore multi articles
                if (rootDescendant.startsWith("@")) {
                    continue;
                }
                if (this.multiArticles.matchesConfigExceptForOwnProperties(rootDescendant, copiedConfigWithoutPropertyFromParameter)) {
                    viableArticles.push(rootDescendant);
                }
            }
        }
        catch (e_1_1) { e_1 = { error: e_1_1 }; }
        finally {
            try {
                if (_f && !_f.done && (_a = _e.return)) _a.call(_e);
            }
            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 RestrictedCascadeMode;
}());
export default RestrictedCascadeMode;
