"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var React = require("react");
var MultiArticle = require("@intelligentgraphics/ig.gfx.multiarticle");
var ig_utilities_1 = require("@intelligentgraphics/ig.utilities");
var Context_1 = require("./Context");
var FilterContext_1 = require("./FilterContext");
var Filter = /** @class */ (function (_super) {
    tslib_1.__extends(Filter, _super);
    function Filter() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.state = {
            configuration: {},
            ready: false,
            availableProperties: [],
        };
        _this.buildFilterContext = function () { return ({
            getValues: _this.getValues,
            getCurrentValue: _this.getCurrentValue,
            setValue: _this.setValue,
            hasProperty: _this.hasProperty,
            getArticles: _this.getViableArticles,
            getAllValues: _this.getAllValues,
            configuration: _this.state.configuration,
            getAllProperties: _this.getAllProperties,
        }); };
        _this.getViableArticles = function () { return _this.filter.getViableArticles(); };
        _this.getValues = function (key) { return _this.filter.getValues(key); };
        _this.getCurrentValue = function (key) { return _this.filter.getCurrentValue(key); };
        _this.hasProperty = function (key) {
            return !!_this.state.availableProperties.find(function (prop) { return prop === key; });
        };
        _this.getAllProperties = function () {
            return _this.getPackage().getProperties(_this.props.root);
        };
        _this.getAllValues = function (key, filterWith) {
            var multiPackage = _this.getPackage();
            if (!filterWith) {
                return ig_utilities_1.Arr.unique(multiPackage.getPropertyValues(_this.props.root, key));
            }
            var instances = multiPackage.Instances[_this.props.root];
            var configurationSubset = filterWith.reduce(function (acc, prop) { return ((acc[prop] = _this.filter.getCurrentValue(prop)), acc); }, {});
            var values = new Set();
            for (var entry in instances) {
                if (multiPackage.matchesConfigExceptForOwnProperties(entry, configurationSubset)) {
                    values.add(instances[entry][key]);
                }
            }
            return Array.from(values);
        };
        _this.reset = function () {
            _this.filter["configuration"] = {};
            _this.setState({ configuration: {} });
        };
        _this.setValue = function (key, value) {
            var newValue = ig_utilities_1.isNullOrUndefined(value) || _this.state.configuration[key] === value
                ? undefined
                : value;
            _this.filter["configuration"] = tslib_1.__assign({}, _this.filter["configuration"]);
            if (newValue === undefined) {
                delete _this.filter["configuration"][key];
            }
            else {
                _this.filter["configuration"][key] = newValue;
            }
            _this.setState({
                configuration: tslib_1.__assign({}, _this.filter["configuration"]),
            }, function () {
                if (_this.props.updateConfiguration) {
                    _this.props.updateConfiguration(key, value);
                }
            });
        };
        return _this;
    }
    Filter.getDerivedStateFromProps = function (nextProps, nextState) {
        if (!nextProps.configuration) {
            return null;
        }
        return {
            configuration: nextProps.configuration,
        };
    };
    Filter.prototype.render = function () {
        if (!this.state.ready) {
            return null;
        }
        return (React.createElement(FilterContext_1.FilterContext.Provider, { value: this.buildFilterContext() }, this.props.children({
            properties: this.state.availableProperties,
        })));
    };
    Filter.prototype.componentDidMount = function () {
        this.setState(this.buildInitialState());
    };
    Filter.prototype.componentDidUpdate = function (prevProps, prevState) {
        if (prevProps.configuration !== this.props.configuration) {
            this.filter["configuration"] = this.props.configuration;
        }
        if (this.state.configuration !== prevState.configuration) {
            if (this.props.onViableArticlesChange) {
                this.props.onViableArticlesChange(this.filter.getViableArticles());
            }
        }
    };
    Filter.prototype.buildInitialState = function () {
        var multiPackage = this.getPackage();
        if (this.props.filter instanceof MultiArticle.MultiArticleFilter) {
            this.filter = this.props.filter;
        }
        else {
            this.filter = new MultiArticle.MultiArticleFilter(multiPackage);
        }
        if (typeof this.props.filterMode === "string") {
            var FilterConstructor = MultiArticle[this.props.filterMode + "Mode"];
            this.filterMode = new FilterConstructor(multiPackage, this.props.root);
        }
        else {
            this.filterMode = new this.props.filterMode(multiPackage, this.props.root);
        }
        this.filter.startMode(this.filterMode);
        this.filter.setProperty = this.setValue;
        this.filter.reset = this.reset;
        if (this.props.initialConfiguration !== undefined) {
            this.filter["configuration"] = tslib_1.__assign({}, this.props.initialConfiguration);
        }
        else if (this.props.configuration !== undefined) {
            this.filter["configuration"] = tslib_1.__assign({}, this.props.configuration);
        }
        var availableProperties = multiPackage.getProperties(this.props.root);
        return {
            availableProperties: availableProperties,
            ready: true,
            configuration: this.filter["configuration"],
        };
    };
    Filter.prototype.getPackage = function () {
        if (this.props.package !== undefined) {
            return this.props.package;
        }
        if (this.context === undefined) {
            throw new Error("The Filter component requires a MultiArticle Package to be supplied either through the package prop or through context");
        }
        return this.context;
    };
    Filter.contextType = Context_1.Context;
    return Filter;
}(React.PureComponent));
exports.default = Filter;
