import * as i0 from '@angular/core';
import { Injectable, ViewChild, Component, NgModule } from '@angular/core';
import { gettext } from '@c8y/ngx-components/gettext';
import * as i1$1 from '@c8y/ngx-components';
import { PX_ACTIONS, Status, ActionBarItemComponent, IconDirective, DataGridComponent, EmptyStateComponent, ColumnDirective, CellRendererDefDirective, C8yTranslatePipe, DatePipe, CoreModule, hookRoute, ViewContext } from '@c8y/ngx-components';
import { PopoverModule } from 'ngx-bootstrap/popover';
import { TooltipModule } from 'ngx-bootstrap/tooltip';
import { ButtonsModule } from 'ngx-bootstrap/buttons';
import { ReactiveFormsModule } from '@angular/forms';
import * as i1 from '@c8y/client';
import * as i4 from '@angular/router';
import { BehaviorSubject } from 'rxjs';
import { tap, map, switchMap, shareReplay, finalize } from 'rxjs/operators';
import * as i5 from '@ngx-translate/core';
import { NgClass, NgIf, NgTemplateOutlet, AsyncPipe } from '@angular/common';

class DeviceProvisionedCertificatesService {
    constructor(userService, client) {
        this.userService = userService;
        this.client = client;
    }
    async getDeviceProvisionedCertificates(device) {
        const deviceUserName = await this.getDeviceUserName(device);
        // Avoid additional requests if the device does not have a user.
        // This case does not really occur in real-life scenarios, but e.g. in cypress tests only
        if (!deviceUserName) {
            return undefined;
        }
        const { data } = await this.userService.detail(deviceUserName, { withCertificates: true });
        return data.provisionedCertificates;
    }
    async getDeviceUserName(device) {
        const method = 'GET';
        const url = `/inventory/managedObjects/${device.id}/user`;
        const res = await this.client.fetch(url, { method });
        const data = await res.json();
        if (res.status >= 400) {
            throw new Error(data.message);
        }
        return data.userName;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DeviceProvisionedCertificatesService, deps: [{ token: i1.UserService }, { token: i1.FetchClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DeviceProvisionedCertificatesService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DeviceProvisionedCertificatesService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i1.UserService }, { type: i1.FetchClient }] });

class DeviceProvisionedCertificatesGuard {
    constructor(deviceProvisionedCertificatesService) {
        this.deviceProvisionedCertificatesService = deviceProvisionedCertificatesService;
    }
    async canActivate(route) {
        const contextData = route.data.contextData || route.parent.data.contextData;
        if (!contextData) {
            return false;
        }
        try {
            const provisionedCertificates = await this.deviceProvisionedCertificatesService.getDeviceProvisionedCertificates(contextData);
            return provisionedCertificates?.length > 0;
        }
        catch (error) {
            return false;
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DeviceProvisionedCertificatesGuard, deps: [{ token: DeviceProvisionedCertificatesService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DeviceProvisionedCertificatesGuard }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DeviceProvisionedCertificatesGuard, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: DeviceProvisionedCertificatesService }] });

class DeviceTabProvisionedCertificatesComponent {
    constructor(alertService, modalService, deviceSerialsService, crlService, route, translateService) {
        this.alertService = alertService;
        this.modalService = modalService;
        this.deviceSerialsService = deviceSerialsService;
        this.crlService = crlService;
        this.route = route;
        this.translateService = translateService;
        this.reloading = false;
        this.reload$ = new BehaviorSubject(null);
        this.tableTitle = gettext('Provisioned certificates');
        this.columns = [
            {
                name: 'serialNumber',
                path: 'serialNumber',
                header: gettext('Serial number')
            },
            {
                name: 'notBefore',
                path: 'notBefore',
                header: gettext('Valid from')
            },
            {
                name: 'notAfter',
                path: 'notAfter',
                header: gettext('Expiration date')
            }
        ];
        this.rows$ = this.reload$.pipe(tap(() => {
            this.reloading = true;
        }), map(() => this.route.snapshot.parent.data.contextData), switchMap(device => this.deviceSerialsService.getDeviceProvisionedCertificates(device)), map(provisionedCertificates => provisionedCertificates.map(cert => ({
            ...cert,
            id: cert.serialNumber
        }))), tap(() => {
            this.reloading = false;
        }), shareReplay(1), finalize(() => {
            this.reloading = false;
        }));
        this.pagination = {
            pageSize: 20,
            currentPage: 1
        };
        this.actionControls = [
            {
                type: 'REVOKE',
                text: gettext('Revoke'),
                icon: 'trash',
                iconClasses: 'text-danger',
                showOnHover: false,
                callback: (item) => this.revokeProvisionedCertificates([item.serialNumber])
            }
        ];
        this.bulkActionControls = [
            {
                type: 'REVOKE',
                text: gettext('Revoke'),
                icon: 'trash',
                callback: (selectedItemsIds) => this.revokeProvisionedCertificates(selectedItemsIds)
            }
        ];
        this.displayOptions = {
            filter: false,
            striped: true,
            hover: true,
            bordered: false,
            gridHeader: true
        };
        this.PX_ACTIONS = PX_ACTIONS;
    }
    ngOnInit() {
        this.reload();
    }
    reload() {
        this.reload$.next();
    }
    getExpirationHighlight(item) {
        const now = Date.now();
        const notAfter = new Date(item.notAfter).getTime();
        const ninetyDays = 90 * 24 * 60 * 60 * 1000;
        const result = {
            expired: false,
            icon: 'calendar',
            textClass: '',
            tooltipText: ''
        };
        if (notAfter < now) {
            result.expired = true;
            result.icon = 'warning';
            result.textClass = 'text-muted';
            result.tooltipText = gettext('Certificate expired');
        }
        else if (notAfter < now + ninetyDays) {
            result.icon = 'warning';
            result.textClass = 'text-danger';
            result.tooltipText = gettext('Certificate expires in less than 90 days');
        }
        return result;
    }
    async revokeProvisionedCertificates(serialNumbersInHex) {
        if (serialNumbersInHex && serialNumbersInHex.length > 0) {
            try {
                await this.confirmRevocation(serialNumbersInHex);
                await this.crlService.uploadCrls(serialNumbersInHex.map(serialNumber => ({ serialNumberInHex: serialNumber })));
                if (serialNumbersInHex.length === 1) {
                    this.alertService.success(gettext('Selected provisioned certificate was revoked.'));
                }
                else {
                    this.alertService.success(gettext('Selected provisioned certificates were revoked.'));
                }
                this.dataGrid.setAllItemsSelected(false);
            }
            catch (error) {
                this.alertService.addServerFailure(error);
            }
            finally {
                this.reload();
            }
        }
    }
    async confirmRevocation(serialNumbers) {
        const hasMany = serialNumbers.length > 1;
        const serialsDisplay = serialNumbers.join(', ');
        const title = hasMany
            ? gettext('Revoke provisioned certificates?')
            : gettext('Revoke provisioned certificate?');
        const messageTpl = hasMany
            ? gettext(`You are about to revoke provisioned certificates: {{ serialNumbers }}. Do you want to proceed?`)
            : gettext(`You are about to revoke provisioned certificate {{ serialNumber }}. Do you want to proceed?`);
        const message = this.translateService.instant(messageTpl, {
            serialNumbers: serialsDisplay,
            serialNumber: serialsDisplay
        });
        return await this.modalService.confirm(title, message, Status.DANGER, {
            ok: gettext('Revoke'),
            cancel: gettext('Cancel')
        });
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DeviceTabProvisionedCertificatesComponent, deps: [{ token: i1$1.AlertService }, { token: i1$1.ModalService }, { token: DeviceProvisionedCertificatesService }, { token: i1.CrlService }, { token: i4.ActivatedRoute }, { token: i5.TranslateService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: DeviceTabProvisionedCertificatesComponent, isStandalone: true, selector: "device-tab-serials-component", viewQueries: [{ propertyName: "dataGrid", first: true, predicate: ["dataGrid"], descendants: true }], ngImport: i0, template: "<c8y-action-bar-item [placement]=\"'right'\">\n  <button\n    class=\"btn btn-link\"\n    title=\"{{ 'Reload' | translate }}\"\n    type=\"button\"\n    (click)=\"reload()\"\n  >\n    <i\n      c8yIcon=\"refresh\"\n      [ngClass]=\"{ 'icon-spin': reloading }\"\n    ></i>\n    {{ 'Reload' | translate }}\n  </button>\n</c8y-action-bar-item>\n\n<c8y-data-grid\n  [title]=\"tableTitle | translate\"\n  #dataGrid\n  [columns]=\"columns\"\n  [rows]=\"rows$ | async\"\n  [pagination]=\"pagination\"\n  [actionControls]=\"actionControls\"\n  [bulkActionControls]=\"bulkActionControls\"\n  [displayOptions]=\"displayOptions\"\n  [hideReload]=\"true\"\n  [selectable]=\"true\"\n>\n  <c8y-ui-empty-state\n    [icon]=\"'certificate'\"\n    [title]=\"'No provisioned certificates to display.' | translate\"\n    *ngIf=\"(rows$ | async)?.length === 0\"\n  ></c8y-ui-empty-state>\n\n  <c8y-column name=\"serialNumber\">\n    <ng-container *c8yCellRendererDef=\"let context\">\n      <span\n        class=\"text-truncate\"\n        title=\"{{ context.property.header | translate }}: {{ context.value }}\"\n      >\n        {{ context.value }}\n      </span>\n    </ng-container>\n  </c8y-column>\n\n  <c8y-column name=\"notBefore\">\n    <ng-container *c8yCellRendererDef=\"let context\">\n      <span\n        class=\"text-truncate\"\n        title=\"{{ context.property.header | translate }}: {{ context.value | c8yDate }}\"\n      >\n        <span *ngIf=\"context.value\">\n          <i\n            class=\"m-r-4\"\n            c8yIcon=\"calendar\"\n          ></i>\n          <span>{{ context.value | c8yDate }}</span>\n        </span>\n      </span>\n    </ng-container>\n  </c8y-column>\n\n  <c8y-column name=\"notAfter\">\n    <ng-container *c8yCellRendererDef=\"let context\">\n      @let expirationHighlight = getExpirationHighlight(context.item);\n      <span\n        [title]=\"\n          (context.property.header | translate) +\n          ': ' +\n          (context.value | c8yDate) +\n          (expirationHighlight?.tooltipText\n            ? ' - ' + (expirationHighlight?.tooltipText | translate)\n            : '')\n        \"\n        [ngClass]=\"expirationHighlight?.textClass\"\n      >\n        <ng-container *ngIf=\"expirationHighlight?.expired; else notExpiredYet\">\n          <del>\n            <ng-container *ngTemplateOutlet=\"expirationDateTpl\"></ng-container>\n          </del>\n        </ng-container>\n        <ng-template #notExpiredYet>\n          <ng-container *ngTemplateOutlet=\"expirationDateTpl\"></ng-container>\n        </ng-template>\n        <ng-template #expirationDateTpl>\n          <i\n            class=\"m-r-4\"\n            c8yIcon=\"{{ expirationHighlight?.icon }}\"\n            *ngIf=\"expirationHighlight?.icon\"\n          ></i>\n          <span>{{ context.value | c8yDate }}</span>\n        </ng-template>\n      </span>\n    </ng-container>\n  </c8y-column>\n</c8y-data-grid>\n", dependencies: [{ kind: "component", type: ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: DataGridComponent, selector: "c8y-data-grid", inputs: ["title", "loadMoreItemsLabel", "loadingItemsLabel", "showSearch", "refresh", "columns", "rows", "pagination", "childNodePagination", "infiniteScroll", "serverSideDataCallback", "selectable", "singleSelection", "selectionPrimaryKey", "displayOptions", "actionControls", "bulkActionControls", "headerActionControls", "searchText", "configureColumnsEnabled", "showCounterWarning", "activeClassName", "expandableRows", "treeGrid", "hideReload", "childNodesProperty", "parentNodeLabelProperty"], outputs: ["rowMouseOver", "rowMouseLeave", "rowClick", "onConfigChange", "onBeforeFilter", "onBeforeSearch", "onFilter", "itemsSelect", "onReload", "onAddCustomColumn", "onRemoveCustomColumn", "onColumnFilterReset", "onSort", "onPageSizeChange", "onColumnReordered", "onColumnVisibilityChange"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: ColumnDirective, selector: "c8y-column", inputs: ["name"] }, { kind: "directive", type: CellRendererDefDirective, selector: "[c8yCellRendererDef]" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DeviceTabProvisionedCertificatesComponent, decorators: [{
            type: Component,
            args: [{ selector: 'device-tab-serials-component', imports: [
                        ActionBarItemComponent,
                        IconDirective,
                        NgClass,
                        DataGridComponent,
                        NgIf,
                        EmptyStateComponent,
                        ColumnDirective,
                        CellRendererDefDirective,
                        C8yTranslatePipe,
                        AsyncPipe,
                        DatePipe,
                        NgTemplateOutlet
                    ], template: "<c8y-action-bar-item [placement]=\"'right'\">\n  <button\n    class=\"btn btn-link\"\n    title=\"{{ 'Reload' | translate }}\"\n    type=\"button\"\n    (click)=\"reload()\"\n  >\n    <i\n      c8yIcon=\"refresh\"\n      [ngClass]=\"{ 'icon-spin': reloading }\"\n    ></i>\n    {{ 'Reload' | translate }}\n  </button>\n</c8y-action-bar-item>\n\n<c8y-data-grid\n  [title]=\"tableTitle | translate\"\n  #dataGrid\n  [columns]=\"columns\"\n  [rows]=\"rows$ | async\"\n  [pagination]=\"pagination\"\n  [actionControls]=\"actionControls\"\n  [bulkActionControls]=\"bulkActionControls\"\n  [displayOptions]=\"displayOptions\"\n  [hideReload]=\"true\"\n  [selectable]=\"true\"\n>\n  <c8y-ui-empty-state\n    [icon]=\"'certificate'\"\n    [title]=\"'No provisioned certificates to display.' | translate\"\n    *ngIf=\"(rows$ | async)?.length === 0\"\n  ></c8y-ui-empty-state>\n\n  <c8y-column name=\"serialNumber\">\n    <ng-container *c8yCellRendererDef=\"let context\">\n      <span\n        class=\"text-truncate\"\n        title=\"{{ context.property.header | translate }}: {{ context.value }}\"\n      >\n        {{ context.value }}\n      </span>\n    </ng-container>\n  </c8y-column>\n\n  <c8y-column name=\"notBefore\">\n    <ng-container *c8yCellRendererDef=\"let context\">\n      <span\n        class=\"text-truncate\"\n        title=\"{{ context.property.header | translate }}: {{ context.value | c8yDate }}\"\n      >\n        <span *ngIf=\"context.value\">\n          <i\n            class=\"m-r-4\"\n            c8yIcon=\"calendar\"\n          ></i>\n          <span>{{ context.value | c8yDate }}</span>\n        </span>\n      </span>\n    </ng-container>\n  </c8y-column>\n\n  <c8y-column name=\"notAfter\">\n    <ng-container *c8yCellRendererDef=\"let context\">\n      @let expirationHighlight = getExpirationHighlight(context.item);\n      <span\n        [title]=\"\n          (context.property.header | translate) +\n          ': ' +\n          (context.value | c8yDate) +\n          (expirationHighlight?.tooltipText\n            ? ' - ' + (expirationHighlight?.tooltipText | translate)\n            : '')\n        \"\n        [ngClass]=\"expirationHighlight?.textClass\"\n      >\n        <ng-container *ngIf=\"expirationHighlight?.expired; else notExpiredYet\">\n          <del>\n            <ng-container *ngTemplateOutlet=\"expirationDateTpl\"></ng-container>\n          </del>\n        </ng-container>\n        <ng-template #notExpiredYet>\n          <ng-container *ngTemplateOutlet=\"expirationDateTpl\"></ng-container>\n        </ng-template>\n        <ng-template #expirationDateTpl>\n          <i\n            class=\"m-r-4\"\n            c8yIcon=\"{{ expirationHighlight?.icon }}\"\n            *ngIf=\"expirationHighlight?.icon\"\n          ></i>\n          <span>{{ context.value | c8yDate }}</span>\n        </ng-template>\n      </span>\n    </ng-container>\n  </c8y-column>\n</c8y-data-grid>\n" }]
        }], ctorParameters: () => [{ type: i1$1.AlertService }, { type: i1$1.ModalService }, { type: DeviceProvisionedCertificatesService }, { type: i1.CrlService }, { type: i4.ActivatedRoute }, { type: i5.TranslateService }], propDecorators: { dataGrid: [{
                type: ViewChild,
                args: ['dataGrid']
            }] } });

class DeviceProvisionedCertificatesModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DeviceProvisionedCertificatesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: DeviceProvisionedCertificatesModule, imports: [CoreModule,
            TooltipModule,
            ReactiveFormsModule,
            ButtonsModule,
            PopoverModule,
            DeviceTabProvisionedCertificatesComponent] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DeviceProvisionedCertificatesModule, providers: [
            hookRoute([
                {
                    context: ViewContext.Device,
                    path: 'device-provisioned-certificates',
                    component: DeviceTabProvisionedCertificatesComponent,
                    label: gettext('x509'),
                    icon: 'c8y-device-profile',
                    canActivate: [DeviceProvisionedCertificatesGuard]
                }
            ]),
            DeviceProvisionedCertificatesService,
            DeviceProvisionedCertificatesGuard
        ], imports: [CoreModule,
            TooltipModule,
            ReactiveFormsModule,
            ButtonsModule,
            PopoverModule,
            DeviceTabProvisionedCertificatesComponent] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DeviceProvisionedCertificatesModule, decorators: [{
            type: NgModule,
            args: [{
                    exports: [],
                    imports: [
                        CoreModule,
                        TooltipModule,
                        ReactiveFormsModule,
                        ButtonsModule,
                        PopoverModule,
                        DeviceTabProvisionedCertificatesComponent
                    ],
                    providers: [
                        hookRoute([
                            {
                                context: ViewContext.Device,
                                path: 'device-provisioned-certificates',
                                component: DeviceTabProvisionedCertificatesComponent,
                                label: gettext('x509'),
                                icon: 'c8y-device-profile',
                                canActivate: [DeviceProvisionedCertificatesGuard]
                            }
                        ]),
                        DeviceProvisionedCertificatesService,
                        DeviceProvisionedCertificatesGuard
                    ]
                }]
        }] });

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

export { DeviceProvisionedCertificatesModule };
//# sourceMappingURL=c8y-ngx-components-device-provisioned-certificates.mjs.map
