import { __awaiter, __decorate, __metadata } from "tslib";
import { Component, ChangeDetectionStrategy, ChangeDetectorRef, Inject, Optional, Input } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CdkDropList, DragDropModule } from '@angular/cdk/drag-drop';
import { DynamicItemLoader, PackageManager } from '@anglr/dynamic';
import { FirstUppercaseLocalizeSAPipe, LOGGER } from '@anglr/common';
import { DebounceCall, generateId, nameof, WithSync } from '@jscrpt/common';
import { Subscription } from 'rxjs';
import { REFRESH_PALETTE_OBSERVABLES, RELATIONS_MODULE_TYPES_LOADER, RELATIONS_NODES_LOADER } from '../../misc/tokens';
import { RelationsNodeManager } from '../../services';
import { ToRelationsDragDataSAPipe } from '../../pipes';
import { NodesPaletteItemSAComponent } from './item/nodesPaletteItem.component';
import * as i0 from "@angular/core";
import * as i1 from "@anglr/dynamic";
import * as i2 from "../../services";
import * as i3 from "@angular/common";
import * as i4 from "@angular/cdk/drag-drop";
/**
 * Component displaying available nodes palette
 */
export class NodesPaletteSAComponent {
    /**
     * Gets array of used packages
     */
    get usedPackages() {
        var _a;
        return (_a = this.packages) !== null && _a !== void 0 ? _a : this.packageManager.usedPackages;
    }
    //######################### constructor #########################
    constructor(_moduleTypesLoader, _nodesLoader, _changeDetector, packageManager, _metadataManager, _refreshObservables, _logger) {
        this._moduleTypesLoader = _moduleTypesLoader;
        this._nodesLoader = _nodesLoader;
        this._changeDetector = _changeDetector;
        this.packageManager = packageManager;
        this._metadataManager = _metadataManager;
        this._refreshObservables = _refreshObservables;
        this._logger = _logger;
        //######################### protected properties #########################
        /**
         * Subscriptions created during initialization
         */
        this.initSubscriptions = new Subscription();
        /**
         * Array of all available items in palette
         */
        this.allItems = [];
        //######################### protected properties - template bindings #########################
        /**
         * Available items grouped by group name
         */
        this.groupedItems = {};
        /**
         * Generated component id, that is used for new component
         */
        this.newCompnentId = generateId(16);
        /**
         * Indication whether drag element is over palette
         */
        this.isDragOverPalette = false;
        /**
         * Array of whitelisted packages
         */
        this.whiteListedPackages = [];
    }
    //######################### public methods - implementation of OnInit #########################
    /**
     * Initialize component
     */
    ngOnInit() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this._refreshObservables && Array.isArray(this._refreshObservables)) {
                for (const obs of this._refreshObservables) {
                    this.initSubscriptions.add(obs.subscribe(() => this.loadNodes()));
                }
            }
            this.initSubscriptions.add(this.packageManager.usedPackagesChange.subscribe(() => this.loadNodes()));
            yield this.loadNodes();
        });
    }
    //######################### public methods - implementation of OnChanges #########################
    /**
     * Called when input value changes
     */
    ngOnChanges(changes) {
        return __awaiter(this, void 0, void 0, function* () {
            if (nameof('whiteList') in changes) {
                this.whiteListedPackages = [];
                if (Array.isArray(this.whiteList)) {
                    for (const source of this.whiteList) {
                        //package already whitelisted
                        if (this.whiteListedPackages.find(itm => itm == source.package)) {
                            continue;
                        }
                        this.whiteListedPackages.push(source.package);
                    }
                }
            }
            if (nameof('whiteList') in changes ||
                nameof('blackList') in changes ||
                nameof('packages') in changes) {
                yield this.loadNodes();
            }
        });
    }
    //######################### public methods - implementation of OnDestroy #########################
    /**
     * Called when component is destroyed
     */
    ngOnDestroy() {
        this.initSubscriptions.unsubscribe();
    }
    /**
     * Loads available relations nodes into palette
     */
    loadNodes() {
        var _a, _b, _c, _d, _e, _f, _g, _h;
        var _j;
        return __awaiter(this, void 0, void 0, function* () {
            this.allItems = [];
            this.groupedItems = {};
            for (const packageName of this.usedPackages) {
                const types = (_b = (_a = (yield this._moduleTypesLoader.loadItem({ package: packageName, name: 'types' }))) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : [];
                for (const type of types) {
                    //package is whitelisted
                    if (this.whiteListedPackages.find(itm => packageName == itm)) {
                        //item is not whitelisted
                        if (!((_c = this.whiteList) === null || _c === void 0 ? void 0 : _c.find(itm => itm.package == packageName && itm.name == type))) {
                            continue;
                        }
                    }
                    //item is blacklisted
                    else if ((_d = this.blackList) === null || _d === void 0 ? void 0 : _d.find(itm => itm.package == packageName && itm.name == type)) {
                        continue;
                    }
                    const itemSource = { package: packageName, name: type };
                    const metadata = yield this._nodesLoader.loadItem(itemSource);
                    if (!metadata) {
                        (_e = this._logger) === null || _e === void 0 ? void 0 : _e.warn('NodesPaletteSAComponent: Failed to obtain layout editor metadata {{@source}}', { source: itemSource });
                    }
                    else {
                        this.allItems.push({
                            itemSource,
                            metadata
                        });
                    }
                }
            }
            this.groupedItems[''] = [];
            //group items
            for (const item of this.allItems) {
                const group = (_g = (_f = item.metadata.metaInfo) === null || _f === void 0 ? void 0 : _f.group) !== null && _g !== void 0 ? _g : '';
                (_h = (_j = this.groupedItems)[group]) !== null && _h !== void 0 ? _h : (_j[group] = []);
                this.groupedItems[group].push(item);
            }
            this._changeDetector.detectChanges();
        });
    }
    //######################### protected methods - template bindings #########################
    /**
     * Generates new component id
     */
    generateNewId() {
        this.newCompnentId = generateId(16);
    }
}
NodesPaletteSAComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.4", ngImport: i0, type: NodesPaletteSAComponent, deps: [{ token: RELATIONS_MODULE_TYPES_LOADER }, { token: RELATIONS_NODES_LOADER }, { token: i0.ChangeDetectorRef }, { token: i1.PackageManager }, { token: i2.RelationsNodeManager }, { token: REFRESH_PALETTE_OBSERVABLES, optional: true }, { token: LOGGER, optional: true }], target: i0.ɵɵFactoryTarget.Component });
NodesPaletteSAComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.4", type: NodesPaletteSAComponent, isStandalone: true, selector: "nodes-palette", inputs: { canvasDropList: "canvasDropList", packages: "packages", whiteList: "whiteList", blackList: "blackList" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"dynamic-flex-column\">\n    <ng-container *ngFor=\"let groupKeyValue of groupedItems | keyvalue\">\n        <div class=\"dynamic-text-spread dynamic-text-small-caps dynamic-margin-left-extra-small dynamic-margin-horizontal-small dynamic-bold\">{{groupKeyValue.key|firstUppercaseLocalize}}&nbsp;</div>\n\n        <div *ngFor=\"let item of groupKeyValue.value\"\n             cdkDropList\n             cdkDropListSortingDisabled\n             [cdkDropListConnectedTo]=\"canvasDropList\"\n             class=\"palette-droplist\">\n            <nodes-palette-item [data]=\"item\"\n                                class=\"editor-component mat-elevation-z2\"\n                                cdkDrag\n                                [cdkDragData]=\"item | toRelationsDragData: newCompnentId: item.metadata.singleton: item.metadata.scope\"\n                                (cdkDragDropped)=\"generateNewId()\"></nodes-palette-item>\n        </div>\n    </ng-container>\n</div>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "pipe", type: i3.KeyValuePipe, name: "keyvalue" }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i4.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "pipe", type: 
            // LayoutEditorDragPreviewSAComponent,
            // LayoutEditorDragPlaceholderSAComponent,
            ToRelationsDragDataSAPipe, name: "toRelationsDragData" }, { kind: "component", type: NodesPaletteItemSAComponent, selector: "nodes-palette-item", inputs: ["data"] }, { kind: "pipe", type: FirstUppercaseLocalizeSAPipe, name: "firstUppercaseLocalize" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
__decorate([
    DebounceCall(10),
    WithSync(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], NodesPaletteSAComponent.prototype, "loadNodes", null);
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.4", ngImport: i0, type: NodesPaletteSAComponent, decorators: [{
            type: Component,
            args: [{ selector: 'nodes-palette', standalone: true, imports: [
                        CommonModule,
                        DragDropModule,
                        // LayoutEditorDragPreviewSAComponent,
                        // LayoutEditorDragPlaceholderSAComponent,
                        ToRelationsDragDataSAPipe,
                        NodesPaletteItemSAComponent,
                        FirstUppercaseLocalizeSAPipe,
                    ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"dynamic-flex-column\">\n    <ng-container *ngFor=\"let groupKeyValue of groupedItems | keyvalue\">\n        <div class=\"dynamic-text-spread dynamic-text-small-caps dynamic-margin-left-extra-small dynamic-margin-horizontal-small dynamic-bold\">{{groupKeyValue.key|firstUppercaseLocalize}}&nbsp;</div>\n\n        <div *ngFor=\"let item of groupKeyValue.value\"\n             cdkDropList\n             cdkDropListSortingDisabled\n             [cdkDropListConnectedTo]=\"canvasDropList\"\n             class=\"palette-droplist\">\n            <nodes-palette-item [data]=\"item\"\n                                class=\"editor-component mat-elevation-z2\"\n                                cdkDrag\n                                [cdkDragData]=\"item | toRelationsDragData: newCompnentId: item.metadata.singleton: item.metadata.scope\"\n                                (cdkDragDropped)=\"generateNewId()\"></nodes-palette-item>\n        </div>\n    </ng-container>\n</div>" }]
        }], ctorParameters: () => [{ type: i1.DynamicItemLoader, decorators: [{
                    type: Inject,
                    args: [RELATIONS_MODULE_TYPES_LOADER]
                }] }, { type: i1.DynamicItemLoader, decorators: [{
                    type: Inject,
                    args: [RELATIONS_NODES_LOADER]
                }] }, { type: i0.ChangeDetectorRef }, { type: i1.PackageManager }, { type: i2.RelationsNodeManager }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [REFRESH_PALETTE_OBSERVABLES]
                }, {
                    type: Optional
                }] }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [LOGGER]
                }, {
                    type: Optional
                }] }], propDecorators: { canvasDropList: [{
                type: Input
            }], packages: [{
                type: Input
            }], whiteList: [{
                type: Input
            }], blackList: [{
                type: Input
            }], loadNodes: [] } });
//# sourceMappingURL=nodesPalette.component.js.map