import * as i0 from '@angular/core';
import { Injectable, Component, ViewChild, EventEmitter, Input, Output, NgModule } from '@angular/core';
import { SubAssetsService, AssetTypeGridColumn, DeleteAssetsModalComponent } from '@c8y/ngx-components/sub-assets';
import { get, some, find, isUndefined } from 'lodash-es';
import * as i1 from '@ngx-translate/core';
import * as i2 from '@c8y/client';
import * as i3 from '@c8y/ngx-components';
import { TypeaheadComponent, gettext, FilteringActionType, DataGridComponent, Status, AlertService, CoreModule, HOOK_ROUTE, HOOK_SEARCH } from '@c8y/ngx-components';
import * as i4 from '@c8y/client';
import * as i5 from '@c8y/ngx-components/assets-navigator';
import * as i6 from '@c8y/client';
import * as i7 from '@c8y/client';
import { __awaiter } from 'tslib';
import { Router, ActivatedRoute } from '@angular/router';
import { InventoryService, SmartGroupsService } from '@c8y/client';
import { DeviceGridService, NameDeviceGridColumn, ModelDeviceGridColumn, SerialNumberDeviceGridColumn, RegistrationDateDeviceGridColumn, SystemIdDeviceGridColumn, ImeiDeviceGridColumn, AlarmsDeviceGridColumn, DeviceGridModule } from '@c8y/ngx-components/device-grid';
import { pipe, defer, merge, of, empty, Subject } from 'rxjs';
import { map, tap, switchMap, takeUntil } from 'rxjs/operators';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
import { BsModalService } from 'ngx-bootstrap/modal';

class AssetSearchService extends SubAssetsService {
    constructor() {
        super(...arguments);
        this.GRID_CONFIG_STORAGE_KEY = 'search-grid-config';
        this.DEFAULT_PAGE_SIZE = 50;
        this.FRAGMENTS_FOR_NO_DEVICE = [
            'c8y_Dashboard',
            'c8y_Report',
            'c8y_Kpi',
            'c8y_ExportConfiguration',
            'c8y_IsBinary',
            'c8y_NoDevice',
            'c8y_IsDeviceGroup',
            'c8y_Group',
            'com_cumulocity_model_smartrest_SmartRestTemplate',
            'com_cumulocity_model_devicesimulator_SensorTemplate',
            '_attachments',
            'c8y_IsDeviceType',
            'c8y_objectmapping_ObjectMapping'
        ];
        this.TYPES_FOR_NO_DEVICE = [
            'c8y_ConfigurationDump',
            'c8y_Firmware',
            'c8y_SmartRule',
            'c8y_Software',
            'impact_object_mapping',
            'c8y_UserPreference',
            'c8y_TenantPolicy',
            'c8y_PrivateSmartRule',
            'c8y_SmartRest2Template',
            'c8y_JsonSchema',
            'c8y_DeviceShellTemplate',
            'c8y_DemoStatus',
            'c8y_DataBroker',
            'c8y_Application_',
            'brandingVariables',
            'c8y_DeviceSimulator',
            'c8y_CertificateMetadata',
            'lwm2m_post_registration',
            'c8y_microservice_manifest_',
            'c8y_CepAgent'
        ];
        this.DEVICE_FRAGMENT_TYPE = 'c8y_IsDevice';
    }
    /**
     * Will return only valid assets (groups and devices) and filter out
     * none useful inventories (e.g. c8y_JsonSchema).
     * @param data All managed objects that should be filtered.
     */
    filterOnlyAssets(data) {
        return data.filter(mo => mo.c8y_IsDeviceGroup || this.isAnyDevice(mo));
    }
    buildCombinedRootQueryFilter(columns, pagination) {
        const rootQuery = {
            __filter: {
                __and: { __not: { __has: `c8y_IsBinary` } }
            }
        };
        const userQuery = this.getQueryObj(columns, pagination);
        const queryPart = this.queriesUtil.addOrderbys(rootQuery, userQuery.__orderby, 'append');
        const fullQuery = this.queriesUtil.addAndFilter(queryPart, userQuery.__filter);
        return this.queriesUtil.buildQuery(fullQuery);
    }
    /**
     * Returns the full-text search results.
     *
     * @param term The search term.
     * @param pagination The currently used pagination.
     */
    search(term, pagination = { currentPage: 1, pageSize: this.DEFAULT_PAGE_SIZE }) {
        return this.inventoryService.list({
            text: term,
            withTotalPages: true,
            pageSize: pagination.pageSize,
            withChildren: false,
            currentPage: pagination.currentPage || 1
        });
    }
    isRootDevice(mo) {
        return !!mo[this.DEVICE_FRAGMENT_TYPE];
    }
    isAnyDevice(mo) {
        const isDevice = this.isRootDevice(mo) || !this.hasFragmentOrTypeFromBlacklist(mo);
        return isDevice;
    }
    hasFragmentOrTypeFromBlacklist(mo) {
        return this.hasTypeFromBlacklist(mo) || this.hasFragmentFromBlacklist(mo);
    }
    hasTypeFromBlacklist(mo) {
        const moType = get(mo, 'type', '');
        return some(this.TYPES_FOR_NO_DEVICE, type => moType.includes(type));
    }
    hasFragmentFromBlacklist(mo) {
        return find(this.FRAGMENTS_FOR_NO_DEVICE, f => !isUndefined(mo[f]));
    }
}
AssetSearchService.ɵprov = i0.ɵɵdefineInjectable({ factory: function AssetSearchService_Factory() { return new AssetSearchService(i0.ɵɵinject(i1.TranslateService), i0.ɵɵinject(i2.InventoryService), i0.ɵɵinject(i3.AppStateService), i0.ɵɵinject(i4.UserService), i0.ɵɵinject(i5.AssetNodeService), i0.ɵɵinject(i5.DeviceGroupService), i0.ɵɵinject(i6.SmartGroupsService), i0.ɵɵinject(i7.SmartRulesService), i0.ɵɵinject(i3.AlertService), i0.ɵɵinject(i3.Permissions), i0.ɵɵinject(i3.ModalService)); }, token: AssetSearchService, providedIn: "root" });
AssetSearchService.decorators = [
    { type: Injectable, args: [{
                providedIn: 'root'
            },] }
];

class SearchBoxComponent {
    constructor(router, inventory, deviceGridService, searchService) {
        this.router = router;
        this.inventory = inventory;
        this.deviceGridService = deviceGridService;
        this.searchService = searchService;
        this.term = '';
        this.filterPipe = pipe(map((data) => {
            return this.searchService.filterOnlyAssets(data);
        }));
        this.recentSearchResults = [];
        this.isLoading = false;
        this.noMatch = false;
        this.RECENT_SEARCH_STORAGE_KEY = 'recent_search_view';
        this.MAX_RECENT_SEARCH_RESULTS = 5;
        this.DEFAULT_FILTER = {
            withTotalPages: true,
            pageSize: 5,
            withChildren: false
        };
        this.KEYCODE_ENTER = 13;
        this.KEYCODE_ESC = 27;
    }
    ngOnInit() {
        return __awaiter(this, void 0, void 0, function* () {
            const recentSearchIds = JSON.parse(localStorage.getItem(this.RECENT_SEARCH_STORAGE_KEY));
            if (recentSearchIds && recentSearchIds.length > 0) {
                const { data } = yield this.inventory.list({ ids: recentSearchIds.join(',') });
                this.recentSearchResults = data;
                this.recentlyRegisteredResults$ = defer(() => this.inventory.list(Object.assign({ q: '$orderby=creationTime desc' }, this.DEFAULT_FILTER)));
            }
        });
    }
    onOpenChange(isOpen) {
        if (isOpen) {
            // needs to request an animation frame as
            // otherwise the typeahead is undefined
            requestAnimationFrame(() => {
                this.subscribeOnSearch();
                this.typeahead.dropdown.show();
                this.typeahead.searchControl.nativeElement.focus();
            });
        }
    }
    open(event, mo) {
        event.stopPropagation();
        const isAlreadyRecent = this.recentSearchResults.find(({ id }) => id === mo.id);
        if (!isAlreadyRecent) {
            this.recentSearchResults.unshift(mo);
            this.recentSearchResults = this.recentSearchResults.slice(0, this.MAX_RECENT_SEARCH_RESULTS);
        }
        const recentSearchIds = this.recentSearchResults.map(({ id }) => id);
        localStorage.setItem(this.RECENT_SEARCH_STORAGE_KEY, JSON.stringify(recentSearchIds));
        this.router.navigateByUrl(this.deviceGridService.getHref(mo, '/'));
        this.dropdown.hide();
    }
    reset() {
        this.typeahead.onSearch.emit('');
        this.selected = undefined;
        this.typeahead.searchControl.nativeElement.focus();
    }
    keyDown(event) {
        const keyCode = event.keyCode;
        if (keyCode === this.KEYCODE_ENTER) {
            // enter hit can be faster then typeahead debounce,
            // therefore we take the term from the DOM element
            // itself:
            const searchTerm = event.target.value;
            this.navigate(['/assetsearch'], { queryParams: { search: searchTerm } });
            this.dropdown.hide();
        }
        else if (keyCode === this.KEYCODE_ESC) {
            if (this.term === '') {
                this.dropdown.hide();
            }
            this.reset();
        }
    }
    filter(on) {
        this.navigate(['/assetsearch'], { queryParams: { filter: on } });
        this.dropdown.hide();
    }
    openSearch() {
        this.router.navigateByUrl('/assetsearch');
        this.dropdown.hide();
    }
    subscribeOnSearch() {
        if (!this.results$) {
            this.results$ = this.typeahead.onSearch.pipe(tap(term => this.onTypingStarted(term)), switchMap(term => this.mergeRequest(term)));
        }
    }
    navigate(commands, extras) {
        this.router
            .navigateByUrl('/', { skipLocationChange: true })
            .then(() => this.router.navigate(commands, extras));
    }
    mergeRequest(term) {
        return merge(of({ data: [] }), this.queryInventoryService(term).pipe(tap(({ data, paging }) => this.onLoadingDone(data, paging))));
    }
    queryInventoryService(term) {
        if (term) {
            return defer(() => this.searchService.search(term));
        }
        return empty();
    }
    onLoadingDone(data, paging) {
        this.isLoading = false;
        this.noMatch =
            paging && paging.nextPage === null && this.searchService.filterOnlyAssets(data).length === 0;
    }
    onTypingStarted(term) {
        this.noMatch = false;
        this.term = term;
        this.isLoading = term.length > 0;
    }
}
SearchBoxComponent.decorators = [
    { type: Component, args: [{
                selector: 'c8y-search-box',
                template: "<div\n  class=\"dropdown\"\n  dropdown\n  #dropdown=\"bs-dropdown\"\n  [insideClick]=\"true\"\n  (isOpenChange)=\"onOpenChange($event)\"\n>\n  <button\n    class=\"main-header-button dropdown-toggle c8y-dropdown\"\n    dropdownToggle\n    type=\"button\"\n    title=\"Search\"\n    aria-controls=\"searchDropdown\"\n  >\n    <i c8yIcon=\"search\" class=\"icon-2x\"></i>\n  </button>\n\n  <div\n    id=\"searchDropdown\"\n    *dropdownMenu\n    class=\"search-header-menu dropdown-menu dropdown-menu-center\"\n  >\n    <form novalidate #searchForm=\"ngForm\" class=\"c8y-search-form\">\n      <c8y-typeahead\n        [(ngModel)]=\"selected\"\n        placeholder=\"{{ 'Search for groups or assets\u2026' | translate }}\"\n        (keydown)=\"keyDown($event)\"\n        (onIconClick)=\"reset()\"\n        [icon]=\"term ? 'times' : 'search'\"\n        [allowFreeEntries]=\"false\"\n        name=\"selected\"\n      >\n        <!-- filter buttons -->\n        <c8y-li *ngIf=\"term.length !== 0\" class=\"p-l-16 p-r-16\">\n          <div class=\"flex-row\">\n            <p class=\"m-r-4 text-muted\">\n              <em translate>Searching by exact match. Click for other search options:</em>\n            </p>\n            <div class=\"btn-group btn-group-sm\">\n              <button\n                class=\"btn btn-default\"\n                title=\"{{ 'Starts with' | translate }}\"\n                (click)=\"filter(term + '*')\"\n              >\n                {{ 'Starts with' | translate }}\n              </button>\n              <button\n                class=\"btn btn-default\"\n                title=\"{{ 'Contains' | translate }}\"\n                (click)=\"filter('*' + term + '*')\"\n              >\n                {{ 'Contains' | translate }}\n              </button>\n              <button\n                class=\"btn btn-default\"\n                title=\"{{ 'Ends with' | translate }}\"\n                (click)=\"filter('*' + term)\"\n              >\n                {{ 'Ends with' | translate }}\n              </button>\n            </div>\n          </div>\n        </c8y-li>\n\n        <!-- Recent search -->\n        <c8y-li\n          *ngIf=\"term.length === 0 && recentSearchResults.length > 0\"\n          [selectable]=\"false\"\n          class=\"p-l-24 p-r-24\"\n        >\n          <div class=\"legend form-block\">\n            <span translate>Recent search results</span>\n          </div>\n        </c8y-li>\n        <c8y-li\n          *ngFor=\"let result of term.length === 0 ? recentSearchResults : []\"\n          class=\"c8y-list__item--link m-l-16 m-r-16\"\n          (click)=\"open($event, result)\"\n        >\n          <c8y-li-icon>\n            <device-status [mo]=\"result\" *ngIf=\"!result.c8y_IsDeviceGroup\"></device-status>\n            <i\n              [c8yIcon]=\"'c8y-group-open'\"\n              class=\"c8y-icon-duocolor\"\n              *ngIf=\"result.c8y_IsDeviceGroup\"\n            ></i>\n          </c8y-li-icon>\n          {{ result.name || '--' }}\n        </c8y-li>\n\n        <!-- Recently registered devices -->\n        <c8y-li\n          *ngIf=\"term.length === 0 && (recentlyRegisteredResults$ | async)?.data?.length > 0\"\n          class=\"p-l-24 p-r-24\"\n          [selectable]=\"false\"\n        >\n          <div class=\"legend form-block\">\n            <span translate>Recently registered devices</span>\n          </div>\n        </c8y-li>\n        <c8y-li\n          *c8yFor=\"\n            let result of term.length === 0 ? recentlyRegisteredResults$ : { data: [] };\n            loadMore: 'none';\n            pipe: filterPipe\n          \"\n          class=\"c8y-list__item--link m-l-16 m-r-16\"\n          (click)=\"open($event, result)\"\n        >\n          <c8y-li-icon>\n            <device-status [mo]=\"result\" *ngIf=\"!result.c8y_IsDeviceGroup\"></device-status>\n            <i\n              [c8yIcon]=\"'c8y-group-open'\"\n              class=\"c8y-icon-duocolor\"\n              *ngIf=\"result.c8y_IsDeviceGroup\"\n            ></i>\n          </c8y-li-icon>\n          {{ result.name || '--' }}\n        </c8y-li>\n\n        <!-- Search results -->\n        <c8y-li *ngIf=\"term.length !== 0\" class=\"p-l-24 p-r-24\" [selectable]=\"false\">\n          <div class=\"legend form-block\">\n            <span translate>Search results</span>\n          </div>\n        </c8y-li>\n        <c8y-li\n          *c8yFor=\"\n            let result of results$;\n            loadMore: 'auto';\n            pipe: filterPipe;\n            notFound: notFoundTemplate;\n            loadingTemplate: loading;\n            loadNextLabel: 'Find more\u2026'\n          \"\n          class=\"c8y-list__item--link  m-l-16 m-r-16\"\n          (click)=\"open($event, result)\"\n        >\n          <c8y-li-icon>\n            <device-status [mo]=\"result\" *ngIf=\"!result.c8y_IsDeviceGroup\"></device-status>\n            <i\n              [c8yIcon]=\"'c8y-group-open'\"\n              class=\"c8y-icon-duocolor\"\n              *ngIf=\"result.c8y_IsDeviceGroup\"\n            ></i>\n          </c8y-li-icon>\n          {{ result.name || '--' }}\n        </c8y-li>\n\n        <!-- No search results found entry -->\n        <ng-template #notFoundTemplate>\n          <c8y-li *ngIf=\"noMatch\" class=\"p-16 c8y-empty-state\" [selectable]=\"false\">\n            <c8y-li-icon [icon]=\"'search'\"></c8y-li-icon>\n            <p><strong translate>No match found.</strong></p>\n            <small translate>\n              Use a filter or go to the asset data table to show all devices and groups.\n            </small>\n          </c8y-li>\n        </ng-template>\n\n        <!-- loading bar first entries -->\n        <c8y-li *ngIf=\"isLoading\" class=\"p-t-32 p-b-0 p-relative\">\n          <div class=\"spinner\" style=\"right:0;\">\n            <div class=\"rect1\"></div>\n            <div class=\"rect2\"></div>\n            <div class=\"rect3\"></div>\n            <div class=\"rect4\"></div>\n            <div class=\"rect5\"></div>\n          </div>\n        </c8y-li>\n\n        <!-- loading bar for loading more entries (inventory roles) -->\n        <ng-template #loading>\n          <c8y-li class=\"text-center p-t-32 p-b-0 p-relative\">\n            <div class=\"spinner\" style=\"right:0;\">\n              <div class=\"rect1\"></div>\n              <div class=\"rect2\"></div>\n              <div class=\"rect3\"></div>\n              <div class=\"rect4\"></div>\n              <div class=\"rect5\"></div>\n            </div>\n          </c8y-li>\n        </ng-template>\n\n        <!-- more filter possibilities -->\n        <c8y-li class=\"m-t-24 bg-gray-lighter p-t-16 p-b-16 p-l-24 p-r-24\" [selectable]=\"false\">\n          <div class=\"flex-row\">\n            <i c8yIcon=\"info-circle\" class=\"text-info m-r-4\"></i>\n            <p translate class=\"m-r-8\">Need more filter possibilities?</p>\n            <button\n              type=\"button\"\n              class=\"m-l-auto btn btn-default btn-sm\"\n              translate\n              (mousedown)=\"openSearch()\"\n            >\n              Go to the asset data table\n            </button>\n          </div>\n        </c8y-li>\n      </c8y-typeahead>\n    </form>\n  </div>\n</div>\n"
            },] }
];
SearchBoxComponent.ctorParameters = () => [
    { type: Router },
    { type: InventoryService },
    { type: DeviceGridService },
    { type: AssetSearchService }
];
SearchBoxComponent.propDecorators = {
    typeahead: [{ type: ViewChild, args: [TypeaheadComponent, { static: false },] }],
    dropdown: [{ type: ViewChild, args: ['dropdown', { static: false },] }]
};

class SearchGridComponent {
    constructor(searchService, bsModalService, smartGroupsService, subAssetsGridService) {
        this.searchService = searchService;
        this.bsModalService = bsModalService;
        this.smartGroupsService = smartGroupsService;
        this.subAssetsGridService = subAssetsGridService;
        this.title = '';
        this.loadingItemsLabel = gettext('Loading results…');
        this.selectable = false;
        this.onColumnsChange = new EventEmitter();
        this.searchText = '';
        this.pagination = this.searchService.getDefaultPagination();
        this.bulkActionControls = this.searchService.getDefaultBulkActionControls();
        this.refresh = new EventEmitter();
        this.sizeCount = 0;
    }
    set _columns(value) {
        if (value) {
            this.columns = value;
        }
        else {
            this.columns = this.searchService.getDefaultColumns();
        }
    }
    set _pagination(value) {
        if (value) {
            this.pagination = value;
        }
        else {
            this.pagination = this.searchService.getDefaultPagination();
        }
    }
    set _actionControls(value) {
        if (value) {
            this.actionControls = value;
        }
        else {
            this.actionControls = this.searchService.getDefaultActionControls();
        }
    }
    set _bulkActionControls(value) {
        if (value) {
            this.bulkActionControls = value;
        }
        else {
            this.bulkActionControls = this.searchService.getDefaultBulkActionControls();
        }
    }
    ngOnInit() {
        if (!this.filteringName) {
            this.columns = this.searchService.getDefaultColumns();
        }
        else {
            this.columns = [
                new AssetTypeGridColumn({ sortOrder: 'desc' }),
                new NameDeviceGridColumn({
                    sortOrder: 'asc',
                    filter: { externalFilterQuery: { names: [this.filteringName] } }
                }),
                new ModelDeviceGridColumn(),
                new SerialNumberDeviceGridColumn({ visible: false }),
                new RegistrationDateDeviceGridColumn({ visible: false }),
                new SystemIdDeviceGridColumn({ visible: false }),
                new ImeiDeviceGridColumn({ visible: false }),
                new AlarmsDeviceGridColumn()
            ];
        }
        this.serverSideDataCallback = this.onDataSourceModifier.bind(this);
        this.setActionControls();
    }
    trackByName(_index, column) {
        return column.name;
    }
    onDataSourceModifier(dataSourceModifier) {
        return __awaiter(this, void 0, void 0, function* () {
            let response;
            if (dataSourceModifier.searchText) {
                response = yield this.searchService.search(dataSourceModifier.searchText, dataSourceModifier.pagination);
            }
            else {
                response = yield this.searchService.getData(dataSourceModifier.columns, dataSourceModifier.pagination, undefined);
            }
            const { res, data, paging } = response;
            const filteredData = this.searchService.filterOnlyAssets(data);
            if (paging.currentPage === 1) {
                this.sizeCount = 0;
            }
            this.sizeCount += filteredData.length;
            this.onColumnsChange.emit(dataSourceModifier.columns);
            return {
                res,
                data: filteredData,
                paging,
                filteredSize: this.sizeCount,
                size: undefined
            };
        });
    }
    setActionControls() {
        const actionControls = [];
        const deleteAction = {
            type: "DELETE" /* Delete */,
            callback: (asset) => this.onDeleteAsset(asset, this.parentGroup)
        };
        actionControls.push(deleteAction);
        if (!this.actionControls) {
            this.actionControls = actionControls;
        }
    }
    updateFiltering(columnNames, action) {
        const { type } = action;
        if (type === FilteringActionType.ResetFilter) {
            this.dataGrid.clearFilters();
        }
        else {
            this.dataGrid.updateFiltering(columnNames, action, false);
        }
    }
    configChange(config) {
        this.searchService.saveConfig(config);
    }
    onDeleteAsset(asset, parentRef) {
        const initialState = {
            showWithDeviceUserCheckbox: this.subAssetsGridService.shouldShowWithDeviceUserCheckbox(asset),
            asset,
            showWithCascadeCheckbox: !this.smartGroupsService.isSmartGroup(asset) &&
                !this.smartGroupsService.isSmartGroupV2(asset)
        };
        const modalRef = this.bsModalService.show(DeleteAssetsModalComponent, { initialState });
        modalRef.content.closeSubject.subscribe((result) => __awaiter(this, void 0, void 0, function* () {
            if (result) {
                yield this.subAssetsGridService.deleteAsset(asset, parentRef, result);
                this.refresh.emit();
            }
        }));
    }
}
SearchGridComponent.decorators = [
    { type: Component, args: [{
                selector: 'c8y-search-grid',
                template: "<div class=\"card--grid--fullpage\">\n  <c8y-data-grid\n    [title]=\"'Search results' | translate\"\n    [loadingItemsLabel]=\"loadingItemsLabel\"\n    [columns]=\"columns\"\n    [pagination]=\"pagination\"\n    [actionControls]=\"actionControls\"\n    [selectable]=\"selectable\"\n    [bulkActionControls]=\"bulkActionControls\"\n    [serverSideDataCallback]=\"serverSideDataCallback\"\n    [infiniteScroll]=\"'auto'\"\n    [showSearch]=\"true\"\n    [searchText]=\"searchText\"\n    [refresh]=\"refresh\"\n    (onConfigChange)=\"configChange($event)\"\n    class=\"d-contents\"\n  >\n    <ng-container *ngFor=\"let column of columns; trackBy: trackByName\">\n      <c8y-column [name]=\"column.name\"></c8y-column>\n    </ng-container>\n    <div class=\"c8y-empty-state\">\n      <h1 c8yIcon=\"search\"></h1>\n      <div>\n        <p>\n          <strong>{{ 'No items found.' | translate }}</strong>\n        </p>\n        <small>{{ 'Change your search or filter criteria.' | translate }}</small>\n      </div>\n    </div>\n  </c8y-data-grid>\n</div>\n"
            },] }
];
SearchGridComponent.ctorParameters = () => [
    { type: AssetSearchService },
    { type: BsModalService },
    { type: SmartGroupsService },
    { type: SubAssetsService }
];
SearchGridComponent.propDecorators = {
    parentGroup: [{ type: Input, args: ['parent-group',] }],
    title: [{ type: Input }],
    loadingItemsLabel: [{ type: Input }],
    _columns: [{ type: Input, args: ['columns',] }],
    _pagination: [{ type: Input, args: ['pagination',] }],
    _actionControls: [{ type: Input, args: ['actionControls',] }],
    selectable: [{ type: Input }],
    _bulkActionControls: [{ type: Input, args: ['bulkActionControls',] }],
    onColumnsChange: [{ type: Output }],
    searchText: [{ type: Input }],
    filteringName: [{ type: Input }],
    dataGrid: [{ type: ViewChild, args: [DataGridComponent, { static: true },] }]
};

class SearchResultsComponent {
    constructor(route, alert) {
        this.route = route;
        this.alert = alert;
        this.filter = '';
        this.searchTerm = '';
        this.unsubscribe$ = new Subject();
    }
    ngOnInit() {
        this.route.queryParams.subscribe(params => {
            if (params.filter) {
                this.filteringName = params.filter;
            }
        });
    }
    ngAfterViewInit() {
        this.route.queryParams
            .pipe(takeUntil(this.unsubscribe$))
            .subscribe(({ filter, search }) => this.onQueryParamsChange(filter, search));
        this.searchGrid.dataGrid.searchText$.pipe(takeUntil(this.unsubscribe$)).subscribe(text => {
            if (text) {
                this.resetFilter();
            }
            this.searchTerm = text;
        });
        this.searchGrid.dataGrid.onFilter
            .pipe(takeUntil(this.unsubscribe$))
            .subscribe(() => this.resetSearch());
        // to prevent race condition (search empty):
        this.searchTerm = this.route.snapshot.queryParams.search || '';
    }
    resetSearch() {
        this.searchTerm = '';
        if (this.searchTerm) {
            this.alert.add({
                text: gettext('Search reset. Full text search does not support filtering.'),
                type: Status.WARNING,
                timeout: 5000
            });
        }
    }
    resetFilter() {
        this.filter = '';
        if (this.searchGrid.dataGrid.filteringApplied) {
            this.alert.add({
                text: gettext('Filter reset. Full text search does not support filtering.'),
                type: Status.WARNING,
                timeout: 5000
            });
            this.searchGrid.dataGrid.clearFilters();
        }
    }
    ngOnDestroy() {
        this.unsubscribe$.next();
        this.unsubscribe$.complete();
    }
    onQueryParamsChange(filter, searchTerm) {
        if (!this.shouldFilter(filter) && searchTerm) {
            this.search(searchTerm);
        }
        else if (this.shouldFilter(filter) && searchTerm) {
            this.search(searchTerm);
        }
    }
    shouldFilter(filter) {
        if (!filter) {
            return false;
        }
        this.resetSearch();
        this.filter = filter || '';
        this.searchGrid.updateFiltering(['name'], {
            type: FilteringActionType.ApplyFilter,
            payload: {
                filteringModifier: {
                    externalFilterQuery: {
                        names: [this.filter]
                    }
                }
            }
        });
        return true;
    }
    search(searchTerm) {
        this.searchTerm = searchTerm || '';
        this.searchGrid.dataGrid.searchText$.next(this.searchTerm);
    }
}
SearchResultsComponent.decorators = [
    { type: Component, args: [{
                selector: 'c8y-search-results',
                template: "<c8y-title>\n  <span translate class=\"p-r-4\">Search</span>\n  <small\n    ngNonBindable\n    translate\n    *ngIf=\"searchTerm\"\n    [translateParams]=\"{\n      searchHint: searchTerm\n    }\"\n    >searching \"{{ searchHint }}\"</small\n  >\n  <small\n    ngNonBindable\n    translate\n    *ngIf=\"filter\"\n    [translateParams]=\"{\n      filterHint: filter\n    }\"\n    >filtered by \"{{ filterHint }}\"</small\n  >\n</c8y-title>\n\n<c8y-search-grid [searchText]=\"searchTerm\" [filteringName]=\"filteringName\"></c8y-search-grid>\n"
            },] }
];
SearchResultsComponent.ctorParameters = () => [
    { type: ActivatedRoute },
    { type: AlertService }
];
SearchResultsComponent.propDecorators = {
    searchGrid: [{ type: ViewChild, args: [SearchGridComponent, { static: true },] }]
};

const ɵ0 = [
    {
        path: 'assetsearch',
        component: SearchResultsComponent
    }
], ɵ1 = [
    {
        template: SearchBoxComponent
    }
];
class SearchModule {
}
SearchModule.decorators = [
    { type: NgModule, args: [{
                declarations: [SearchResultsComponent, SearchBoxComponent, SearchGridComponent],
                imports: [CoreModule, DeviceGridModule, BsDropdownModule],
                entryComponents: [SearchResultsComponent, SearchBoxComponent],
                exports: [SearchResultsComponent, SearchBoxComponent, SearchGridComponent],
                providers: [
                    AssetSearchService,
                    {
                        provide: HOOK_ROUTE,
                        useValue: ɵ0,
                        multi: true
                    },
                    {
                        provide: HOOK_SEARCH,
                        useValue: ɵ1,
                        multi: true
                    }
                ]
            },] }
];

/**
 * Generated bundle index. Do not edit.
 */

export { AssetSearchService, SearchBoxComponent, SearchGridComponent, SearchModule, SearchResultsComponent, ɵ0, ɵ1 };
//# sourceMappingURL=c8y-ngx-components-search.js.map
