import { __awaiter, __decorate } from "tslib";
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { InventoryService } from '@c8y/client';
import { AlertService, gettext, memoize, ModalService, Status } from '@c8y/ngx-components';
import { TranslateService } from '@ngx-translate/core';
import { property } from 'lodash-es';
import { BsModalService } from 'ngx-bootstrap/modal';
import { BehaviorSubject, combineLatest, defer, merge, Subject } from 'rxjs';
import { distinctUntilKeyChanged, map, shareReplay, switchMap, take, takeUntil, tap, withLatestFrom } from 'rxjs/operators';
import { RepositoryService } from './../repository.service';
import { AddFirmwareModalComponent } from './add-firmware-modal.component';
import { AddFirmwarePatchModalComponent } from './add-firmware-patch-modal.component';
export class FirmwareDetailsComponent {
    constructor(activatedRoute, inventoryService, repositoryService, alertService, translateService, modalService, bsModalService) {
        this.activatedRoute = activatedRoute;
        this.inventoryService = inventoryService;
        this.repositoryService = repositoryService;
        this.alertService = alertService;
        this.translateService = translateService;
        this.modalService = modalService;
        this.bsModalService = bsModalService;
        this.reload$ = new Subject();
        this.reloading$ = new BehaviorSubject(false);
        this.updateFirmware$ = new Subject();
        this.firmwareUpdated$ = new Subject();
        this.baseVersionsUpdated$ = new Subject();
        this.patchVersionsUpdated$ = new Subject();
        this.firmware$ = merge(this.activatedRoute.params.pipe(map(params => params.id), switchMap(id => defer(() => this.inventoryService.detail(id).then(result => result.data)))), this.reload$.pipe(tap(() => this.reloading$.next(true)), switchMap(() => this.activatedRoute.params), map(params => params.id), switchMap(id => defer(() => this.inventoryService.detail(id).then(result => result.data))), tap(() => this.reloading$.next(false))), this.firmwareUpdated$).pipe(shareReplay(1));
        this.baseVersions$ = merge(this.firmware$.pipe(distinctUntilKeyChanged('id')), this.baseVersionsUpdated$, this.patchVersionsUpdated$, this.reload$).pipe(switchMap(() => this.firmware$), switchMap(firmware => this.repositoryService.listBaseVersions(firmware)), shareReplay(1));
        this.isLegacy$ = this.firmware$.pipe(map(firmware => this.repositoryService.isLegacyEntry(firmware)), shareReplay(1));
        this.canAddPatchVersions$ = combineLatest(this.isLegacy$, this.baseVersions$.pipe(map(({ data }) => data.length > 0))).pipe(map(([isLegacy, hasBaseVersions]) => !isLegacy && hasBaseVersions));
        this.expanded = {};
        this.destroy$ = new Subject();
    }
    ngOnInit() {
        this.updateFirmware$
            .pipe(withLatestFrom(this.firmware$), switchMap(([firmwarePartial, firmware]) => this.inventoryService.update(Object.assign({ id: firmware.id }, firmwarePartial))), map(({ data }) => data), tap(firmware => this.firmwareUpdated$.next(firmware)), tap(() => this.alertService.success(gettext('Saved.'))), takeUntil(this.destroy$))
            .subscribe();
    }
    getPatchVersionsCount$(baseVersion) {
        return merge(this.firmware$.pipe(distinctUntilKeyChanged('id')), this.baseVersionsUpdated$, this.patchVersionsUpdated$, this.reload$).pipe(switchMap(() => this.firmware$), switchMap(firmware => this.repositoryService.getPatchVersionsCount$(firmware, baseVersion)), shareReplay(1));
    }
    getBinaryName$(binaryUrl) {
        return this.repositoryService.getBinaryName$(binaryUrl);
    }
    getPatchVersions$(baseVersion) {
        return merge(this.firmware$.pipe(distinctUntilKeyChanged('id')), this.patchVersionsUpdated$, this.reload$).pipe(switchMap(() => this.firmware$), switchMap(firmware => this.repositoryService.listPatchVersions(firmware, baseVersion)), shareReplay(1));
    }
    addBaseVersion() {
        this.firmware$
            .pipe(take(1), switchMap(firmware => {
            const initialState = {
                model: {
                    selected: firmware,
                    description: firmware.description
                }
            };
            const config = {
                class: 'modal-sm',
                ignoreBackdropClick: true,
                initialState
            };
            const modalRef = this.bsModalService.show(AddFirmwareModalComponent, config);
            return modalRef.content.saved;
        }))
            .subscribe(() => this.baseVersionsUpdated$.next());
    }
    addPatchVersion() {
        this.firmware$
            .pipe(take(1), switchMap(firmware => {
            const initialState = {
                model: {
                    selected: firmware
                }
            };
            const config = {
                class: 'modal-sm',
                ignoreBackdropClick: true,
                initialState
            };
            const modalRef = this.bsModalService.show(AddFirmwarePatchModalComponent, config);
            return modalRef.content.saved;
        }))
            .subscribe(() => this.patchVersionsUpdated$.next());
    }
    deleteBaseVersion(baseVersion) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const title = gettext('Delete firmware');
                const body = `
        ${this.translateService.instant(gettext('You are about to delete firmware {{ version }} with all its patches.'), { version: baseVersion.c8y_Firmware.version })}
        ${this.translateService.instant(gettext('This operation is irreversible.'))}
        ${this.translateService.instant(gettext('Do you want to proceed?'))}
      `;
                const labels = {
                    ok: gettext('Delete')
                };
                yield this.modalService.confirm(title, body, Status.DANGER, labels);
                yield this.repositoryService.delete(baseVersion);
                this.alertService.success(gettext('Firmware deleted.'));
                this.baseVersionsUpdated$.next();
            }
            catch (ex) {
                // only if not cancel from modal
                if (ex) {
                    this.alertService.addServerFailure(ex);
                }
            }
        });
    }
    deletePatchVersion(patchVersion) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const title = gettext('Delete firmware patch');
                const body = `
        ${this.translateService.instant(gettext('You are about to delete firmware patch {{ version }}.'), { version: patchVersion.c8y_Firmware.version })}
        ${this.translateService.instant(gettext('This operation is irreversible.'))}
        ${this.translateService.instant(gettext('Do you want to proceed?'))}
      `;
                const labels = {
                    ok: gettext('Delete')
                };
                yield this.modalService.confirm(title, body, Status.DANGER, labels);
                yield this.repositoryService.delete(patchVersion);
                this.alertService.success(gettext('Firmware patch deleted.'));
                this.patchVersionsUpdated$.next();
            }
            catch (ex) {
                // only if not cancel from modal
                if (ex) {
                    this.alertService.addServerFailure(ex);
                }
            }
        });
    }
    ngOnDestroy() {
        this.destroy$.next(true);
        this.destroy$.unsubscribe();
    }
}
FirmwareDetailsComponent.decorators = [
    { type: Component, args: [{
                selector: 'c8y-firmware-details',
                template: "<c8y-title>\n  {{ (firmware$ | async)?.name }}\n</c8y-title>\n\n<c8y-breadcrumb>\n  <c8y-breadcrumb-item\n    path=\"#/firmware\"\n    label=\"{{ 'Firmware repository' | translate }}\"\n    icon=\"c8y-firmware\"\n  >\n  </c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n  <button\n    *ngIf=\"!(isLegacy$ | async)\"\n    class=\"btn btn-link\"\n    title=\"{{ 'Add firmware' | translate }}\"\n    (click)=\"addBaseVersion()\"\n  >\n    <i c8yIcon=\"plus-circle\"></i>\n    {{ 'Add firmware' | translate }}\n  </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n  <button\n    *ngIf=\"canAddPatchVersions$ | async\"\n    class=\"btn btn-link\"\n    title=\"{{ 'Add firmware patch' | translate }}\"\n    (click)=\"addPatchVersion()\"\n  >\n    <i c8yIcon=\"plus-circle\"></i>\n    {{ 'Add firmware patch' | translate }}\n  </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n  <button class=\"btn btn-link\" title=\"{{ 'Reload' | translate }}\" (click)=\"reload$.next()\">\n    <i c8yIcon=\"refresh\" [ngClass]=\"{ 'icon-spin': reloading$ | async }\"></i>\n    {{ 'Reload' | translate }}\n  </button>\n</c8y-action-bar-item>\n\n<div class=\"row\">\n  <div class=\"col-lg-12 col-lg-max\">\n    <div class=\"card m-b-4\">\n      <div class=\"card-header separator\">\n        <h4 class=\"card-title\" translate>\n          Name, description and device type filter\n        </h4>\n      </div>\n      <div class=\"card-block\">\n        <div class=\"row\">\n          <div class=\"col-md-4\">\n            <c8y-form-group>\n              <label class=\"control-label\">\n                {{ 'Name' | translate }}\n              </label>\n              <div class=\"input-group input-group-editable\">\n                <input\n                  #nameInput\n                  type=\"text\"\n                  class=\"form-control\"\n                  [ngModel]=\"(firmware$ | async)?.name\"\n                  #nameModel=\"ngModel\"\n                  placeholder=\"{{ 'e.g. My firmware' | translate }}\"\n                  [ngStyle]=\"{ 'width.ch': (firmware$ | async)?.name?.length || 31 }\"\n                  required\n                />\n                <span></span>\n                <div class=\"input-group-btn\">\n                  <button\n                    class=\"btn btn-primary\"\n                    title=\"{{ 'Save' | translate }}\"\n                    (click)=\"updateFirmware$.next({ name: nameInput.value }); nameModel.reset()\"\n                    [disabled]=\"nameInput.value.length == 0\"\n                  >\n                    {{ 'Save' | translate }}\n                  </button>\n                </div>\n              </div>\n            </c8y-form-group>\n          </div>\n          <div class=\"col-md-4\">\n            <c8y-form-group>\n              <label class=\"control-label\">\n                {{ 'Description' | translate }}\n              </label>\n              <div class=\"input-group input-group-editable\">\n                <input\n                  #descriptionInput\n                  type=\"text\"\n                  class=\"form-control\"\n                  [ngModel]=\"(firmware$ | async)?.description\"\n                  #descriptionModel=\"ngModel\"\n                  placeholder=\"{{ 'e.g. Firmware for hardware revision b' | translate }}\"\n                  [ngStyle]=\"{ 'width.ch': (firmware$ | async)?.description?.length || 31 }\"\n\n                />\n                <span></span>\n                <div class=\"input-group-btn\">\n                  <button\n                    class=\"btn btn-primary\"\n                    title=\"{{ 'Save' | translate }}\"\n                    (click)=\" updateFirmware$.next({ description: descriptionInput.value }); descriptionModel.reset() \"\n                  >\n                    {{ 'Save' | translate }}\n                  </button>\n                </div>\n              </div>\n            </c8y-form-group>\n          </div>\n          <div class=\"col-md-4\">\n            <c8y-form-group>\n              <label class=\"control-label\">\n                {{ 'Device type filter' | translate }}\n\n                <button\n                 class=\"btn-clean\"\n                  popover=\"{{ 'If the filter is set, the firmware will show up for installation only for devices of that type. If no filter is set, it will be available for all devices.' | translate }}\"\n                  [outsideClick]=\"true\"\n                  container=\"body\"\n                >\n                  <i c8yIcon=\"question-circle-o\" class=\"text-info\"></i>\n                </button>\n              </label>\n              <div class=\"input-group input-group-editable\">\n                <input\n                  #deviceTypeInput\n                  type=\"text\"\n                  class=\"form-control\"\n                  [ngModel]=\"(firmware$ | async)?.c8y_Filter?.type\"\n                  #deviceTypeModel=\"ngModel\"\n                  placeholder=\"{{ 'e.g.' | translate }} c8y_Linux\"\n                  [ngStyle]=\"{ 'width.ch': (firmware$ | async)?.type?.length || 31 }\"\n                />\n                <span></span>\n                <div class=\"input-group-btn\">\n                  <button\n                    class=\"btn btn-primary\"\n                    title=\"{{ 'Save' | translate }}\"\n                    (click)=\" updateFirmware$.next({ c8y_Filter: { type: deviceTypeInput.value } }); deviceTypeModel.reset()\"\n                  >\n                    {{ 'Save' | translate }}\n                  </button>\n                </div>\n              </div>\n            </c8y-form-group>\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n<div class=\"row\">\n  <div class=\"col-lg-12 col-lg-max\">\n    <div class=\"card\">\n      <div class=\"card-header separator\">\n        <h4 class=\"card-title\" translate>\n          Versions and patches\n        </h4>\n      </div>\n\n      <div class=\"card-block p-t-0 p-b-24\">\n        <div *ngIf=\"(baseVersions$ | async)?.data.length === 0\">\n          <div class=\"c8y-empty-state text-center\">\n            <h1 c8yIcon=\"c8y-firmware\" class=\"c8y-icon-duocolor\"></h1>\n            <h3 translate>No versions to display.</h3>\n            <p translate>Add a new version by clicking below.</p>\n            <p>\n              <button\n                class=\"btn btn-primary\"\n                title=\"{{ 'Add firmware' | translate }}\"\n                (click)=\"addBaseVersion()\"\n              >\n                {{ 'Add firmware' | translate }}\n              </button>\n            </p>\n          </div>\n        </div>\n\n        <c8y-list-group\n          [ngClass]=\"{ 'dd-low': (baseVersions$ | async)?.data.length < 10 }\"\n          *ngIf=\"(baseVersions$ | async)?.data.length > 0\"\n        >\n          <c8y-li\n            *c8yFor=\"let baseVersion of baseVersions$ | async; let i = index; loadMore: 'auto'\"\n            [ngClass]=\"{ 'c8y-list__item--empty-actions': !(getPatchVersions$(baseVersion) | async)?.data.length }\"\n            [collapsed]=\"!expanded[baseVersion.id]\"\n            (collapsedChange)=\"expanded[baseVersion.id] = !$event\"\n          >\n            <c8y-li-icon>\n              <i c8yIcon=\"c8y-firmware\"></i>\n            </c8y-li-icon>\n\n            <c8y-li-body class=\"content-flex-50\">\n              <div class=\"col-4\">\n                <p class=\"text-truncate-wrap\" title=\"{{ baseVersion.c8y_Firmware.version }}\">\n                  {{ baseVersion.c8y_Firmware.version }}\n                </p>\n              </div>\n              <div class=\"col-5\">\n                <p class=\"text-truncate-wrap\">\n                  <span class=\"text-label-small m-r-8\" translate>\n                    File\n                  </span>\n                  <span title=\"{{ getBinaryName$(baseVersion.c8y_Firmware.url) | async }}\">\n                    <c8y-file-download url=\"{{ baseVersion.c8y_Firmware.url }}\"></c8y-file-download>\n                  </span>\n                </p>\n              </div>\n              <div class=\"col-2 flex-row a-i-start\">\n                <span *ngIf=\"isLegacy$ | async\" class=\"label label-warning flex-item-right-sm\">\n                  {{ 'Legacy' | translate }}\n                </span>\n\n                <span *ngIf=\"!(isLegacy$ | async)\">\n                  <span *ngIf=\"(getPatchVersionsCount$(baseVersion) | async) === null\">\n                    <span class=\"label label-info\">\n                      <i c8yIcon=\"circle-o-notch\" class=\"icon-spin\"></i>\n                    </span>\n                  </span>\n                  <span *ngIf=\"(getPatchVersionsCount$(baseVersion) | async) !== null\">\n                    <span [ngPlural]=\"getPatchVersionsCount$(baseVersion) | async\">\n                      <ng-template ngPluralCase=\"=0\">\n                        <span class=\"label label-default flex-item-right-sm\">\n                          <span translate>No patches</span>\n                        </span>\n                      </ng-template>\n                      <ng-template ngPluralCase=\"=1\">\n                        <span class=\"label label-info\">\n                          <span translate>1 patch</span>\n                        </span>\n                      </ng-template>\n                      <ng-template ngPluralCase=\"other\">\n                        <span class=\"label label-info\">\n                          <span\n                            ngNonBindable\n                            translate\n                            [translateParams]=\"{ count: getPatchVersionsCount$(baseVersion) | async }\"\n                          >\n                            {{ count }} patches\n                          </span>\n                        </span>\n                      </ng-template>\n                    </span>\n                  </span>\n                </span>\n              </div>\n              <div class=\"fit-h-20 visible-xs\" *ngIf=\"!(isLegacy$ | async)\">\n                <button\n                  class=\"btn btn-danger btn-xs m-t-8 \"\n                  (click)=\"deleteBaseVersion(baseVersion)\"\n                  title=\"{{ 'Delete' | translate }}\"\n                >\n                  <i c8yIcon=\"minus-circle\"></i>\n                  {{ 'Delete' | translate }}\n                </button>\n              </div>\n              <div *ngIf=\"!(isLegacy$ | async)\" class=\"flex-item-right fit-h-20 p-r-8 hidden-xs\">\n                <button\n                  class=\"btn btn-dot text-danger showOnHover\"\n                  (click)=\"deleteBaseVersion(baseVersion)\"\n                  title=\"{{ 'Delete' | translate }}\"\n                >\n                  <i c8yIcon=\"minus-circle\"></i>\n                </button>\n              </div>\n            </c8y-li-body>\n            <c8y-li-collapse *ngIf=\"(getPatchVersions$(baseVersion) | async)?.data.length\">\n              <c8y-list-group class=\"separator-top\">\n                <c8y-li\n                  *c8yFor=\" let patchVersion of getPatchVersions$(baseVersion) | async; let i = index; loadMore: 'auto' \"\n                >\n                  <c8y-li-icon>\n                    <i c8yIcon=\"c8y-firmware\"></i>\n                  </c8y-li-icon>\n                  <c8y-li-body class=\"content-flex-50\">\n                    <div class=\"col-4\">\n                      {{ patchVersion.c8y_Firmware.version }}\n                    </div>\n                    <div class=\"col-5\">\n                      <div class=\"text-truncate\">\n                        <span class=\"text-label-small m-r-8\" translate>\n                          File\n                        </span>\n                        <c8y-file-download\n                          url=\"{{ patchVersion.c8y_Firmware.url }}\"\n                        ></c8y-file-download>\n                      </div>\n                    </div>\n                    <div class=\"visible-xs m-t-8\">\n                      <button\n                        class=\"btn btn-danger btn-xs\"\n                        (click)=\"deletePatchVersion(patchVersion)\"\n                        title=\"{{ 'Delete' | translate }}\"\n                      >\n                        <i c8yIcon=\"minus-circle\"></i>\n                        {{ 'Delete' | translate }}\n                      </button>\n                    </div>\n                    <div class=\"flex-item-right p-r-8 hidden-xs fit-h-20\">\n                      <button\n                        class=\"btn btn-dot text-danger showOnHover\"\n                        (click)=\"deletePatchVersion(patchVersion)\"\n                        title=\"{{ 'Delete' | translate }}\"\n                      >\n                        <i c8yIcon=\"minus-circle\"></i>\n                      </button>\n                    </div>\n                  </c8y-li-body>\n                </c8y-li>\n              </c8y-list-group>\n            </c8y-li-collapse>\n          </c8y-li>\n        </c8y-list-group>\n      </div>\n    </div>\n  </div>\n</div>\n"
            },] }
];
FirmwareDetailsComponent.ctorParameters = () => [
    { type: ActivatedRoute },
    { type: InventoryService },
    { type: RepositoryService },
    { type: AlertService },
    { type: TranslateService },
    { type: ModalService },
    { type: BsModalService }
];
__decorate([
    memoize(property('id'))
], FirmwareDetailsComponent.prototype, "getPatchVersionsCount$", null);
__decorate([
    memoize()
], FirmwareDetailsComponent.prototype, "getBinaryName$", null);
__decorate([
    memoize(property('id'))
], FirmwareDetailsComponent.prototype, "getPatchVersions$", null);
//# sourceMappingURL=data:application/json;base64, 