"use strict";
/* TODO auto-generated eslint ignore, please fix! */
/* eslint @typescript-eslint/no-inferrable-types: "off", prefer-const: "off" */
/**
 * Liza Group Context
 *
 *  Copyright (C) 2010-2019 R-T Specialty, LLC.
 *
 *  This file is part of the Liza Data Collection Framework
 *
 *  Liza is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.GroupContext = void 0;
/**
 * Context responsible for a group and its fields
 */
var GroupContext = /** @class */ (function () {
    /**
     * Initialize GroupContext
     *
     * @param _parser - ContextParser
     * @param _field_context_factory - field context factory
     */
    function GroupContext(_parser, _field_context_factory) {
        this._parser = _parser;
        this._field_context_factory = _field_context_factory;
        /**
         * Cache of FieldContexts
         */
        this._field_context_cache = {};
        /**
         * Object containing FieldContextStore for each field
         */
        this._field_context_stores = {};
        /**
         * Position of all cached fields
         */
        this._field_positions = [];
        /**
         * Non-cmatch field names
         */
        this._non_cmatch_fields = [];
    }
    /**
     * Create cache of field context stores
     * and initialize field arrays
     *
     * @param fields - exclusive field names of group
     * @param cmatch_fields - exclusive cmatch field names of group
     * @param content - group content
     * @param is_internal if user is internal
     */
    GroupContext.prototype.init = function (fields, cmatch_fields, content, is_internal) {
        if (is_internal === void 0) { is_internal = false; }
        var cmatch_fields_set = new Set(cmatch_fields);
        this._non_cmatch_fields = fields.filter(function (field) { return !cmatch_fields_set.has(field); });
        for (var i = 0; i < fields.length; i++) {
            var field = fields[i];
            var field_content = this._parser.parse(field, content);
            if (field_content !== null) {
                var sibling_content = this._parser.findSiblingContent(field_content);
                // Create the FieldContextStore
                var field_store = this._field_context_factory.createStore(field, field_content, sibling_content, is_internal);
                // Only non-subfields should store the position in GroupContext
                if (field_store.isSubField() === false) {
                    var position = field_store.position;
                    this._field_positions[position] = field;
                }
                this._field_context_stores[field] = field_store;
            }
        }
    };
    /**
     * Create cache of field contexts
     *
     * This should only be called by Groups that do not
     * support multiple indexes
     */
    GroupContext.prototype.createFieldCache = function () {
        for (var field in this._field_context_stores) {
            var store = this._field_context_stores[field];
            // Index is 0 for the initial fields
            var index = 0;
            var is_subfield = store.isSubField();
            var field_context = this._field_context_factory.create(field, index, store.content, is_subfield, store.siblingContent);
            this._field_context_cache[field] = [];
            this._field_context_cache[field][index] = field_context;
        }
    };
    /**
     * Shows default fields for a new index
     *
     * Only non-cmatch fields should be attached initially
     *
     * @param index - field index
     * @param to - parent content
     */
    GroupContext.prototype.addIndex = function (index, to) {
        for (var i = 0; i < this._non_cmatch_fields.length; i++) {
            var field_name = this._non_cmatch_fields[i];
            this.show(field_name, index, to);
        }
    };
    /**
     * Detaches content from the FieldContextStores
     * for specific fields that have cmatches
     *
     * The purpose of this is to reduce the number of
     * DOM elements in the parent of the content
     * in the FieldContextStore before the parent
     * is cloned for each index
     *
     * This method can be optionally called by
     * GroupUi and its subtypes to improve performance
     *
     * @param fields - cmatch field names of group
     */
    GroupContext.prototype.detachStoreContent = function (fields) {
        for (var i = 0; i < fields.length; i++) {
            var field = fields[i];
            var store = this._field_context_stores[field];
            if (store !== undefined) {
                store.detach();
            }
        }
    };
    /**
     * Remove the last index from the field context cache
     *
     * Or clear cache for fields at certain indexes
     * if it does not appear on all indexes
     *
     * @param fields      - exclusive field names of group
     * @param index       - index being removed
     * @param index_count - count of indexes in group
     */
    GroupContext.prototype.removeIndex = function (fields, index, index_count) {
        for (var i = 0; i < fields.length; i++) {
            var field = fields[i];
            var field_cache = this._field_context_cache[field];
            if (field_cache === undefined) {
                continue;
            }
            var field_cache_non_null = field_cache.filter(function (field) { return field !== null; });
            if (field_cache_non_null.length === index_count) {
                field_cache.pop();
            }
            else {
                // Some cmatch fields might not appear on all indexes
                // They need to be recreated when show is called
                // for the index being removed and above
                for (var k = index; k < field_cache.length; k++) {
                    if (field_cache[k] !== undefined) {
                        field_cache[k].hide();
                        delete field_cache[k];
                    }
                }
            }
        }
    };
    /**
     * Set the value if attached to the DOM
     * or store the value so it can be used later
     *
     * @param field_name - field name
     * @param index - field index
     * @param value - field value
     */
    GroupContext.prototype.setValueByName = function (field_name, index, value) {
        if (this.isFieldAttached(field_name, index)) {
            var field_context = this._fromCache(field_name, index);
            field_context.setValue(value);
        }
        else {
            var store = this._field_context_stores[field_name];
            if (store !== undefined) {
                store.setValueByIndex(index, value);
            }
        }
    };
    /**
     * Return if the field is attached to the DOM
     *
     * @param field_name - field name
     * @param index - field index
     */
    GroupContext.prototype.isFieldAttached = function (field_name, index) {
        if (this._field_context_cache[field_name] === undefined ||
            this._field_context_cache[field_name][index] === undefined) {
            return false;
        }
        var field_context = this._fromCache(field_name, index);
        return field_context.isAttached();
    };
    /**
     * Set Options on Select elements
     *
     * If the field is not attached, store the options and value
     * in the FieldContextStore to be retrieved when shown
     *
     * @param field_name - to attach options to
     * @param index - field index
     * @param options - list of options to set
     * @param value - value to set once options exist
     */
    GroupContext.prototype.setOptions = function (field_name, index, options, val) {
        if (this.isFieldAttached(field_name, index)) {
            var field_context = this._fromCache(field_name, index);
            field_context.setOptions(options, val);
        }
        else {
            var store = this._field_context_stores[field_name];
            if (store !== undefined) {
                store.setOptionsByIndex(index, options);
                store.setValueByIndex(index, val);
            }
        }
    };
    /**
     * Show field on the DOM
     *
     * Set the value and options of the field if stored
     *
     * @param field_name - to attach to DOM
     * @param index - field index
     * @param to - parent content
     */
    GroupContext.prototype.show = function (field_name, index, to) {
        // If field name was never added to a store, do nothing
        if (this._field_context_stores[field_name] === undefined) {
            return;
        }
        var field_context = this._fromCache(field_name, index);
        if (field_context.isVisible() === false) {
            field_context.show(to, this._getNextElement(field_name, index));
            var store = this._field_context_stores[field_name];
            if (store.hasOptionsByIndex(index)) {
                field_context.setOptions(store.getOptionsByIndex(index), store.getValueByIndex(index));
            }
            if (store.hasValueByIndex(index)) {
                field_context.setValue(store.getValueByIndex(index));
            }
        }
    };
    /**
     * Hide field from DOM
     *
     * @param field_name - to detach from DOM
     * @param index - field index
     */
    GroupContext.prototype.hide = function (field_name, index) {
        // If field name was never added to a store, do nothing
        if (this._field_context_stores[field_name] === undefined) {
            return;
        }
        var store = this._field_context_stores[field_name];
        // If the field is a subfield, we need its parent
        // context to be created and then the subfield,
        // so it can be detached
        if (store.isSubField() === true) {
            // Get the parent field context
            var parent_name = store.subFieldParentName;
            // create the parent field context if not defined
            this._fromCache(parent_name, index);
            var subfield_context = this._fromCache(field_name, index);
            subfield_context.hide();
        }
        // If FieldContext was never added to cache, do nothing
        if (this._field_context_cache[field_name] === undefined ||
            this._field_context_cache[field_name][index] === undefined) {
            return;
        }
        this._field_context_cache[field_name][index].hide();
    };
    /**
     * Return FieldContext from cache, or create a new one
     * and save it to the cache
     *
     * @param field_name - field name
     * @param index - field index
     *
     * @returns cached FieldContext
     */
    GroupContext.prototype._fromCache = function (field_name, index) {
        if (this._field_context_cache[field_name] !== undefined &&
            this._field_context_cache[field_name][index] !== undefined) {
            return this._field_context_cache[field_name][index];
        }
        // Retrieve cloned nodes from the FieldContextStore
        var store = this._field_context_stores[field_name];
        var field_content = store.getContentClone(index);
        var sibling_content = store.getSiblingContentClone(index);
        var is_subfield = store.isSubField();
        // If it's a subfield, grab the content from its parent
        // We don't want a new clone in this scenario
        if (is_subfield === true) {
            var parent_name = store.subFieldParentName;
            var parent_context = this._fromCache(parent_name, index);
            field_content = parent_context.getContent();
        }
        var field_context = this._field_context_factory.create(field_name, index, field_content, is_subfield, sibling_content);
        if (this._field_context_cache[field_name] === undefined) {
            this._field_context_cache[field_name] = [];
        }
        this._field_context_cache[field_name][index] = field_context;
        return field_context;
    };
    /**
     * Determine the next attached element to attach before
     *
     * @param field_name - of element to find next element
     * @param index - field index
     *
     * @returns the Context of the next visible element
     */
    GroupContext.prototype._getNextElement = function (field_name, index) {
        var store = this._field_context_stores[field_name];
        var position = store.position;
        position++;
        for (var i = position; i < this._field_positions.length; i++) {
            if (this._field_positions[i] !== undefined) {
                var next_element_name = this._field_positions[i];
                var next_context = this._field_context_cache[next_element_name];
                if (next_context !== undefined &&
                    next_context[index] !== undefined &&
                    next_context[index].isAttached()) {
                    return next_context[index].getFirstOfContentSet();
                }
            }
        }
        return null;
    };
    return GroupContext;
}());
exports.GroupContext = GroupContext;
//# sourceMappingURL=data:application/json;base64, 