import { __awaiter, __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]() {
        var _a;
        let x = 0;
        const initPromise = (_a = this.initPromise) !== null && _a !== void 0 ? _a : (this.initPromise = this.getInitPromise());
        const items = this.items;
        return {
            next() {
                return __awaiter(this, void 0, void 0, function* () {
                    yield 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
     */
    forEach(callback) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            yield ((_a = this.initPromise) !== null && _a !== void 0 ? _a : (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
     */
    getComponents() {
        return __awaiter(this, void 0, void 0, function* () {
            yield 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
     */
    getComponent(metadata, parent, levelIndex, level) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const iteratorItem = {
                metadata,
                parent,
                levelIndex,
                level
            };
            this.items.push(iteratorItem);
            const def = yield this.loader.loadItem(metadata);
            if (!def) {
                (_a = this.logger) === null || _a === void 0 ? void 0 : _a.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++) {
                yield this.getComponent(childrenMeta[x], iteratorItem, x, level + 1);
            }
        });
    }
    /**
     * Gets initialization promise
     */
    getInitPromise() {
        return __awaiter(this, void 0, void 0, function* () {
            if (!this.initialized) {
                this.initialized = true;
                yield this.getComponents();
            }
        });
    }
};
LayoutComponentsIterator = __decorate([
    __param(1, Inject(LAYOUT_COMPONENTS_LOADER)),
    __metadata("design:paramtypes", [Object, DynamicItemLoader, Object])
], LayoutComponentsIterator);
export { LayoutComponentsIterator };
//# sourceMappingURL=layoutComponents.iterator.js.map