"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GridCollection = void 0;
var GridGroupUi_1 = require("../group/GridGroupUi");
/**
 * The only type of group this collection may contain
 */
var REQUIRED_GROUP_TYPE = GridGroupUi_1.GridGroupUi;
/**
 * HTML section tag
 */
var SECTION_TAG = 'SECTION';
/**
 * HTML fieldset tag
 */
var FIELDSET_TAG = 'FIELDSET';
/**
 * A mediator of grid groups
 */
var GridCollection = /** @class */ (function () {
    /**
     * Create a new GridCollection instance
     *
     * @param _content  - target collection element
     * @param groups    - list of groups
     * @param _stylers  - ancestor-aware styler
     * @param document  - DOM
     */
    function GridCollection(_content, groups, _stylers, document) {
        var _this = this;
        var _a;
        this._content = _content;
        this._stylers = _stylers;
        /**
         * Groups inside of this collection
         */
        this._groups = [];
        /**
         * Whether the collection is locked (all elements disabled)
         */
        this._locked = false;
        this._setGroups(groups);
        this._content.addEventListener('click', function (e) {
            if (e.target) {
                _this._handleClick(e.target);
            }
        });
        (_a = document.defaultView) === null || _a === void 0 ? void 0 : _a.addEventListener('resize', function () {
            return _this._resizeDetails();
        });
    }
    /**
     * Trigger visitation of the collection
     *
     * It's assumed that the groups will have been visited before the
     * collection's visit method is called. If not, the children may not have
     * properly updated data.
     */
    GridCollection.prototype.visit = function () {
        var _this = this;
        var column_count = this._getColumnCount();
        this._setColumnClass(column_count);
        // Ensure all detail panes are closed
        this._groups.forEach(function (g) { return g.closeDetails(_this._stylers); });
    };
    /**
     * Lock/unlock a collection (preventing modifications)
     *
     * If the lock status has changed, the click handlers
     * will be disabled/enabled respectively.
     *
     * @param lock - whether collection should be locked
     */
    GridCollection.prototype.lock = function (lock) {
        this._locked = lock;
    };
    /**
     * Get the count of columns in the grid
     *
     * @return the number of columns
     */
    GridCollection.prototype._getColumnCount = function () {
        var unique = function (type, i, children) {
            if (type === null) {
                type = '';
            }
            return children.indexOf(type) === i;
        };
        return this._groups
            .filter(function (group) { return group.isVisible(); })
            .map(function (child) { return child.getXType(); })
            .filter(unique).length;
    };
    /**
     * Set a column class on the group
     *
     * Remove existing column classes.
     *
     * @param number - the number of columns
     */
    GridCollection.prototype._setColumnClass = function (number) {
        var class_class = /col-\d+/;
        var classes = this._content.classList;
        for (var index = 0; index < classes.length; index++) {
            var value = classes[index];
            if (class_class.test(value)) {
                this._content.classList.remove(value);
            }
        }
        this._content.classList.add('col-' + number);
    };
    /**
     * Handle the click event for the collection
     *
     * @param target - click target
     */
    GridCollection.prototype._handleClick = function (target) {
        if (this._locked) {
            return;
        }
        var element = target;
        if (element.classList.contains('close')) {
            return this._closeDetails();
        }
        var section = this._getGridSection(element);
        var group = this._getGridGroup(element);
        if (!section || !group) {
            return;
        }
        this._handleSelection(section, group);
    };
    /**
     * Handle selection of a group
     *
     * @param section       - section of the group that was clicked
     * @param group_element - group that was clicked
     */
    GridCollection.prototype._handleSelection = function (section, group_element) {
        var _this = this;
        var is_invalid = group_element.classList.contains('invalid');
        var is_disabled = group_element.classList.contains('disabled');
        var is_content = section.classList.contains('content');
        var is_actions = section.classList.contains('actions');
        var group = this._getGroupFromElement(group_element);
        // If the group is disabled we don't take any action on selection
        if (is_invalid || !group || (is_disabled && !group.group.isInternal())) {
            return;
        }
        if (is_content) {
            // Cycle through all other groups first
            this._groups
                .filter(function (g) { return g !== group && _this._groupsConflict(g, group); })
                .forEach(function (g) { return g.deselect(); });
            var selected_siblings = this._groups
                .filter(function (g) { return g !== group && g.isSelected(); })
                .map(function (g) { return g.getSelectedValue(); });
            group.isSelected()
                ? group.deselect(selected_siblings)
                : group.select(selected_siblings);
        }
        if (is_actions) {
            // Cycle through all other groups first to avoid conflicting CSS
            this._groups
                .filter(function (g) { return g !== group; })
                .forEach(function (g) { return g.closeDetails(_this._stylers); });
            group.areDetailsOpen()
                ? group.closeDetails(this._stylers)
                : group.openDetails(this._stylers);
        }
    };
    /**
     * Close details of all groups
     */
    GridCollection.prototype._closeDetails = function () {
        var _this = this;
        this._groups.forEach(function (g) { return g.closeDetails(_this._stylers); });
    };
    /**
     * Get the grid group's section element from an HTML element
     *
     * @param element - target element
     *
     * @return grid's section element
     */
    GridCollection.prototype._getGridSection = function (element) {
        var isGridSection = function (elem) {
            return (elem.tagName === SECTION_TAG &&
                (elem.classList.contains('content') ||
                    elem.classList.contains('actions')));
        };
        return this._getClosestElement(element, this._content, isGridSection);
    };
    /**
     * Get the grid group root from an HTML element
     *
     * @param element - target element
     *
     * @return grid group's root fieldset element
     */
    GridCollection.prototype._getGridGroup = function (element) {
        var isGridGroup = function (elem) {
            return elem.tagName === FIELDSET_TAG && elem.classList.contains('grid');
        };
        return this._getClosestElement(element, this._content, isGridGroup);
    };
    /**
     * Get the GridGroup that corresponds to a group element
     *
     * @param element - target element
     *
     * @return group
     */
    GridCollection.prototype._getGroupFromElement = function (element) {
        var id = element.getAttribute('id');
        return this._groups.filter(function (group) { return group.getGroupId() === id; })[0];
    };
    /**
     * Get the closest element that matches a test
     *
     * @param elem   - starting element
     * @param stopAt - element to stop looking at
     * @param test   - test to conduct
     *
     * @return closest found element
     */
    GridCollection.prototype._getClosestElement = function (elem, stopAt, test) {
        while (elem) {
            if (elem === stopAt) {
                return null;
            }
            if (test(elem)) {
                return elem;
            }
            elem = elem.parentElement;
        }
        return null;
    };
    /**
     * Set groups for the collection
     *
     * @param groups    - child groups
     */
    GridCollection.prototype._setGroups = function (groups) {
        var group_elems = this._getGroupFieldsets();
        if (group_elems.length === 0) {
            return;
        }
        var group_ids = group_elems
            .map(function (element) { return element.getAttribute('id'); })
            .filter(function (id) { return !!id; });
        for (var id in groups) {
            var group = groups[id];
            var is_child_id = group_ids.indexOf(id) > -1;
            if (is_child_id && group instanceof REQUIRED_GROUP_TYPE) {
                this._groups.push(group);
            }
        }
    };
    /**
     * Get group fieldsets
     *
     * @return group fieldsets
     */
    GridCollection.prototype._getGroupFieldsets = function () {
        return Array.prototype.slice.call(this._content.querySelectorAll('fieldset'));
    };
    /**
     * Determine if the groups conflict
     *
     * Groups conflict when they share a category.
     *
     * @param g1 - first group
     * @param g2 - second group
     *
     * @return if the groups conflict
     */
    GridCollection.prototype._groupsConflict = function (g1, g2) {
        return (g1.getCategories().filter(function (category) {
            return g2.getCategories().indexOf(category) > -1;
        }).length > 0);
    };
    /**
     * Force re-open any open detail panes to apply resize
     */
    GridCollection.prototype._resizeDetails = function () {
        var _this = this;
        this._groups
            .filter(function (g) { return g.areDetailsOpen(); })
            .forEach(function (g) { return g.openDetails(_this._stylers); });
    };
    return GridCollection;
}());
exports.GridCollection = GridCollection;
//# sourceMappingURL=data:application/json;base64, 