import { __awaiter } from "tslib";
import { ChangeDetectorRef, Directive, ElementRef, Inject, Injector, Optional } from '@angular/core';
import { LOGGER } from '@anglr/common';
import { isEmptyObject, nameof } from '@jscrpt/common';
import * as i0 from "@angular/core";
/**
 * Base component for layout component
 */
export class LayoutComponentBase {
    //######################### protected properties #########################
    /**
     * Gets element that is used within extension
     */
    get element() {
        return this.componentElement;
    }
    /**
     * Gets options that are used within extension
     */
    get extensionsOptions() {
        return this.options;
    }
    //######################### constructor #########################
    constructor(changeDetector, componentElement, injector, logger) {
        this.changeDetector = changeDetector;
        this.componentElement = componentElement;
        this.injector = injector;
        this.logger = logger;
        //######################### protected fields #########################
        /**
         * Array of extensions that are registered for component
         */
        this.extensions = [];
        /**
         * Indication whether initialization was already done
         */
        this.initialized = false;
        /**
         * Indication whether was component destroyed
         */
        this.destroyed = false;
    }
    //######################### public methods - implementation of OnDestroy #########################
    /**
     * Called when component is destroyed
     */
    ngOnDestroy() {
        if (this.destroyed) {
            return;
        }
        this.destroyed = true;
        for (const ext of this.extensions) {
            ext.destroy();
        }
        this.onDestroy();
    }
    //######################### public methods - implementation of LayoutComponent #########################
    /**
     * @inheritdoc
     */
    ngOnInit() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.initialized) {
                return;
            }
            this.initialized = true;
            const extensionsOptions = this.extensionsOptions;
            yield this.onInit();
            yield this.onOptionsSet();
            if (extensionsOptions) {
                for (const extension of this.extensions) {
                    yield extension.initialize(this.injector, this.element, this);
                }
            }
            yield this.afterInit();
        });
    }
    /**
     * @inheritdoc
     */
    ngOnChanges(changes) {
        return __awaiter(this, void 0, void 0, function* () {
            //options has changed
            if (nameof('options') in changes) {
                yield this.onOptionsSet();
                const extensionsOptions = this.extensionsOptions;
                //set options in extensions
                if (extensionsOptions) {
                    for (const extension of this.extensions) {
                        yield extension.optionsChange(extensionsOptions);
                    }
                }
                if (!this.initialized) {
                    return;
                }
                yield this.onOptionsChange();
            }
            delete changes[nameof('options')];
            if (!isEmptyObject(changes)) {
                this.onChanges(changes);
            }
        });
    }
    /**
     * @inheritdoc
     */
    registerExtensions(extensions) {
        this.extensions = extensions;
    }
    /**
     * @inheritdoc
     */
    invalidateVisuals() {
        this.changeDetector.detectChanges();
    }
    //######################### protected methods #########################
    /**
     * Called on initialzation of component, options are already set
     */
    onInit() {
    }
    /**
     * Called right after initialization finished, including extesions
     */
    afterInit() {
    }
    /**
     * Called on change of options, after initialization
     */
    onOptionsChange() {
    }
    /**
     * Occurs when some property changes on component
     * @param _changes - Changes that occured on component
     */
    onChanges(_changes) {
    }
    /**
     * Called everytime options are set, after initialization and later
     */
    onOptionsSet() {
    }
    /**
     * Called when component is being destroyed
     */
    onDestroy() {
    }
}
LayoutComponentBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.4", ngImport: i0, type: LayoutComponentBase, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: i0.Injector }, { token: LOGGER, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
LayoutComponentBase.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.4", type: LayoutComponentBase, usesOnChanges: true, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.4", ngImport: i0, type: LayoutComponentBase, decorators: [{
            type: Directive
        }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i0.Injector }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [LOGGER]
                }, {
                    type: Optional
                }] }] });
//# sourceMappingURL=layoutComponentBase.js.map