import { __decorate, __metadata, __param } from "tslib";
import { Inject } from '@angular/core';
import { DynamicItemLoader } from '@anglr/dynamic';
import { LAYOUT_COMPONENTS_LOADER } from '@anglr/dynamic/layout';
import { getDescendantsGetter } from '../../decorators';
//TODO: make action commented type
/**
 * Iterator for layout components metadata
 */
let LayoutComponentsIterator = class LayoutComponentsIterator {
    //######################### public properties #########################
    /**
     * Async iterator for layout components metadata
     */
    [Symbol.asyncIterator]() {
        let x = 0;
        const initPromise = this.initPromise ?? (this.initPromise = this.getInitPromise());
        const items = this.items;
        return {
            async next() {
                await initPromise;
                if (x < items.length) {
                    return {
                        value: items[x++],
                        done: false
                    };
                }
                return {
                    value: items[x - 1],
                    done: true
                };
            }
        };
    }
    //######################### constructor #########################
    constructor(layoutMetadata, loader, logger) {
        this.layoutMetadata = layoutMetadata;
        this.loader = loader;
        this.logger = logger;
        //######################### protected fields #########################
        /**
         * Array of layout component iterator items, flattened layout structure
         */
        this.items = [];
        /**
         * Indication whether was iterator initialized
         */
        this.initialized = false;
        /**
         * Initialization promise
         */
        this.initPromise = null;
    }
    //######################### public methods #########################
    /**
     * Calls callback for each component in tree
     * @param callback - Callback called for each layout component metadata
     */
    async forEach(callback) {
        await (this.initPromise ?? (this.initPromise = this.getInitPromise()));
        for (const item of this.items) {
            callback(item.metadata, item.parent, item.levelIndex, item.level);
        }
    }
    //######################### protected methods #########################
    /**
     * Gets components in layout components metadata hierarchy
     */
    async getComponents() {
        await this.getComponent(this.layoutMetadata, null, 0, 0);
    }
    /**
     * Gets metadata for single layout component metadata and its children
     * @param metadata - Metadata for layout component
     * @param parentMetadata - parent layout component iterator item
     * @param levelIndex - Index of layout component in current level
     * @param level - Current level of nexted components, 0 is root component
     */
    async getComponent(metadata, parent, levelIndex, level) {
        const iteratorItem = {
            metadata,
            parent,
            levelIndex,
            level
        };
        this.items.push(iteratorItem);
        const def = await this.loader.loadItem(metadata);
        if (!def) {
            this.logger?.debug('LayoutComponentsIterator: failed to get dynamic component type for iterator! {{@data}}', { data: { package: metadata.package, name: metadata.name } });
            return;
        }
        const getDescendants = getDescendantsGetter(def.data);
        //component does not have children
        if (!getDescendants) {
            return;
        }
        const childrenMeta = getDescendants(metadata.options);
        for (let x = 0; x < childrenMeta.length; x++) {
            await this.getComponent(childrenMeta[x], iteratorItem, x, level + 1);
        }
    }
    /**
     * Gets initialization promise
     */
    async getInitPromise() {
        if (!this.initialized) {
            this.initialized = true;
            await this.getComponents();
        }
    }
};
LayoutComponentsIterator = __decorate([
    __param(1, Inject(LAYOUT_COMPONENTS_LOADER)),
    __metadata("design:paramtypes", [Object, DynamicItemLoader, Object])
], LayoutComponentsIterator);
export { LayoutComponentsIterator };
//# sourceMappingURL=layoutComponents.iterator.js.map