import * as i0 from '@angular/core';
import { Input, Component } from '@angular/core';
import * as i3 from '@c8y/ngx-components';
import { CoreModule, TitleComponent, ActionBarItemComponent, C8yTranslateDirective, IconDirective, LoadingComponent, C8yTranslatePipe } from '@c8y/ngx-components';
import { gettext } from '@c8y/ngx-components/gettext';
import * as i1$1 from '@c8y/ngx-components/remote-access/data';
import * as i2$1 from '@angular/router';
import * as i4 from '@angular/common';
import { NgIf, NgClass } from '@angular/common';
import { saveAs } from 'file-saver';
import * as i2 from 'ngx-bootstrap/modal';
import * as i1 from '@angular/forms';
import { Validators } from '@angular/forms';
import { BehaviorSubject, combineLatest, defer } from 'rxjs';
import { filter, map, distinctUntilChanged } from 'rxjs/operators';

class VncCredentialsPromptComponent {
    constructor(formBuilder, modalRef) {
        this.formBuilder = formBuilder;
        this.modalRef = modalRef;
        this.title = gettext('VNC credentials');
        this.types = [];
        this.result = new Promise((resolve, reject) => {
            this._resolve = resolve;
            this._reject = reject;
        });
        this.showUsername = false;
        this.form = this.initForm();
    }
    ngOnInit() {
        this.showUsername = this.types.includes('username');
        this.form = this.initForm();
    }
    initForm() {
        return this.formBuilder.group({
            username: [undefined, this.showUsername ? [Validators.required] : []],
            password: [undefined, [Validators.required]]
        });
    }
    cancel() {
        this._reject();
    }
    save() {
        this._resolve(this.form.value);
    }
    submit() {
        if (!this.form.valid) {
            return;
        }
        this.modalRef.hide();
        this.save();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VncCredentialsPromptComponent, deps: [{ token: i1.FormBuilder }, { token: i2.BsModalRef }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: VncCredentialsPromptComponent, isStandalone: true, selector: "c8y-vnc-credentials-prompt", inputs: { types: "types" }, ngImport: i0, template: "<c8y-modal\n  [title]=\"title\"\n  [headerClasses]=\"'dialog-header'\"\n  (onDismiss)=\"cancel()\"\n  (onClose)=\"save()\"\n  [disabled]=\"form.invalid\"\n  [labels]=\"{ cancel: 'Cancel', ok: 'Save' }\"\n>\n  <ng-container c8y-modal-title>\n    <span [c8yIcon]=\"'key'\"></span>\n  </ng-container>\n  <form\n    class=\"p-24\"\n    [formGroup]=\"form\"\n    (submit)=\"submit()\"\n  >\n    <c8y-form-group *ngIf=\"showUsername\">\n      <label\n        for=\"username\"\n        translate\n      >\n        Username\n      </label>\n      <input\n        class=\"form-control\"\n        id=\"username\"\n        name=\"username\"\n        type=\"text\"\n        [placeholder]=\"'e.g. {{ example }}' | translate: { example: 'admin' }\"\n        formControlName=\"username\"\n      />\n      <c8y-messages></c8y-messages>\n    </c8y-form-group>\n\n    <c8y-form-group>\n      <label\n        for=\"password\"\n        translate\n      >\n        Password\n      </label>\n      <input\n        class=\"form-control\"\n        id=\"password\"\n        name=\"password\"\n        type=\"password\"\n        formControlName=\"password\"\n      />\n      <c8y-messages></c8y-messages>\n    </c8y-form-group>\n\n    <button type=\"submit\" class=\"hidden\">hidden submit</button>\n  </form>\n</c8y-modal>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "directive", type: i3.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i3.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.ModalComponent, selector: "c8y-modal", inputs: ["disabled", "close", "dismiss", "title", "body", "customFooter", "headerClasses", "labels"], outputs: ["onDismiss", "onClose"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: i3.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "component", type: i3.MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage", "additionalMessages"] }, { kind: "directive", type: i3.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: i3.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VncCredentialsPromptComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-vnc-credentials-prompt', standalone: true, imports: [CoreModule, NgIf], template: "<c8y-modal\n  [title]=\"title\"\n  [headerClasses]=\"'dialog-header'\"\n  (onDismiss)=\"cancel()\"\n  (onClose)=\"save()\"\n  [disabled]=\"form.invalid\"\n  [labels]=\"{ cancel: 'Cancel', ok: 'Save' }\"\n>\n  <ng-container c8y-modal-title>\n    <span [c8yIcon]=\"'key'\"></span>\n  </ng-container>\n  <form\n    class=\"p-24\"\n    [formGroup]=\"form\"\n    (submit)=\"submit()\"\n  >\n    <c8y-form-group *ngIf=\"showUsername\">\n      <label\n        for=\"username\"\n        translate\n      >\n        Username\n      </label>\n      <input\n        class=\"form-control\"\n        id=\"username\"\n        name=\"username\"\n        type=\"text\"\n        [placeholder]=\"'e.g. {{ example }}' | translate: { example: 'admin' }\"\n        formControlName=\"username\"\n      />\n      <c8y-messages></c8y-messages>\n    </c8y-form-group>\n\n    <c8y-form-group>\n      <label\n        for=\"password\"\n        translate\n      >\n        Password\n      </label>\n      <input\n        class=\"form-control\"\n        id=\"password\"\n        name=\"password\"\n        type=\"password\"\n        formControlName=\"password\"\n      />\n      <c8y-messages></c8y-messages>\n    </c8y-form-group>\n\n    <button type=\"submit\" class=\"hidden\">hidden submit</button>\n  </form>\n</c8y-modal>\n" }]
        }], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i2.BsModalRef }], propDecorators: { types: [{
                type: Input
            }] } });

class VncViewerComponent {
    constructor(remoteAccess, activatedRoute, modalService) {
        this.remoteAccess = remoteAccess;
        this.activatedRoute = activatedRoute;
        this.modalService = modalService;
        this.titlePrefix = gettext('VNC viewer');
        this.title = '';
        this.container = null;
        this.powerCapability = false;
        this.status = 'connecting';
        this.container$ = new BehaviorSubject(null);
        const container$ = this.container$.pipe(filter(Boolean));
        const configurationId$ = this.activatedRoute.params.pipe(map(params => params.configurationId), filter(Boolean), distinctUntilChanged());
        const deviceId$ = this.activatedRoute.parent.params.pipe(map(params => params.id), filter(Boolean), distinctUntilChanged());
        this.connectionSubscription = combineLatest([
            container$,
            deviceId$,
            configurationId$,
            defer(() => this.getNoVNCClient())
        ]).subscribe(([container, deviceId, configurationId, noVNC]) => {
            this.disconnectFromOldSession();
            this.connect(container, deviceId, configurationId, noVNC);
        });
    }
    ngOnDestroy() {
        this.connectionSubscription?.unsubscribe();
        this.disconnectFromOldSession();
    }
    ngAfterViewInit() {
        this.container$.next(document.getElementById('vnc-screen'));
    }
    disconnectFromOldSession() {
        this.powerCapability = false;
        this.title = '';
        if (!this.noVNCClient) {
            return;
        }
        this.noVNCClient.disconnect();
        delete this.noVNCClient;
    }
    connect(container, deviceId, configId, noVNC) {
        this.container = container;
        this.changeStatus('connecting');
        const options = {
            wsProtocols: ['binary']
        };
        const uri = this.remoteAccess.getWebSocketUri(deviceId, configId);
        this.noVNCClient = new noVNC(container, uri, options);
        this.noVNCClient.resizeSession = true;
        this.noVNCClient.scaleViewport = true;
        this.noVNCClient.showDotCursor = true;
        this.noVNCClient.viewOnly = false;
        this.noVNCClient.qualityLevel = 6;
        // need to set compressionLevel to something different than the default 2 as 2 seems to be causing issues..
        this.noVNCClient.compressionLevel = 9;
        this.noVNCClient.addEventListener('connect', _e => {
            this.changeStatus('connected');
            this.noVNCClient.focus();
        });
        this.noVNCClient.addEventListener('credentialsrequired', e => {
            this.requestCredentials(e.detail.types);
        });
        this.noVNCClient.addEventListener('desktopname', e => {
            this.title = e.detail.name;
        });
        this.noVNCClient.addEventListener('disconnect', () => {
            this.changeStatus('disconnected');
        });
        this.noVNCClient.addEventListener('capabilities', e => {
            this.powerCapability = e.detail.capabilities.power;
        });
    }
    downloadScreenshot() {
        this.noVNCClient.toBlob(blob => {
            const date = new Date().toISOString();
            saveAs(blob, `screenshot-${this.title}-${date}.png`);
        }, 'image/png', 1);
    }
    changeStatus(status) {
        this.status = status;
    }
    toggleFullscreen() {
        if (document.fullscreenElement) {
            document.exitFullscreen();
        }
        else {
            this.container.requestFullscreen();
        }
    }
    sendCtrlAltDel() {
        this.noVNCClient.sendCtrlAltDel();
    }
    sendShutDown() {
        this.noVNCClient.machineShutdown();
    }
    sendReset() {
        this.noVNCClient.machineReset();
    }
    sendReboot() {
        this.noVNCClient.machineReboot();
    }
    async getNoVNCClient() {
        const lib = await import('@novnc/novnc/lib/rfb');
        if (typeof lib.default === 'function') {
            return lib.default;
        }
        const libDefault = lib.default;
        if (typeof libDefault.default === 'function') {
            return libDefault.default;
        }
        throw new Error('NoVNC library not found');
    }
    async requestCredentials(types) {
        const modalRef = this.modalService.show(VncCredentialsPromptComponent, {
            ignoreBackdropClick: true,
            keyboard: false,
            initialState: { types: types }
        });
        try {
            const { username, password } = await modalRef.content.result;
            this.noVNCClient.sendCredentials({ username, password, target: undefined });
        }
        catch (e) {
            this.noVNCClient.disconnect();
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VncViewerComponent, deps: [{ token: i1$1.RemoteAccessService }, { token: i2$1.ActivatedRoute }, { token: i2.BsModalService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: VncViewerComponent, isStandalone: true, selector: "c8y-vnc-viewer", ngImport: i0, template: "<c8y-title>{{ titlePrefix | translate }}: {{ title | translate }}</c8y-title>\n\n<ng-container *ngIf=\"status === 'connected'\">\n  <c8y-action-bar-item [placement]=\"'right'\">\n    <button\n      class=\"btn btn-link\"\n      (click)=\"toggleFullscreen()\"\n    >\n      <i [c8yIcon]=\"'expand'\"></i>\n      <span translate>Fullscreen</span>\n    </button>\n  </c8y-action-bar-item>\n\n  <c8y-action-bar-item [placement]=\"'right'\">\n    <button\n      class=\"btn btn-link\"\n      (click)=\"downloadScreenshot()\"\n    >\n      <i [c8yIcon]=\"'download'\"></i>\n      <span translate>Screenshot</span>\n    </button>\n  </c8y-action-bar-item>\n\n  <c8y-action-bar-item [placement]=\"'more'\">\n    <button\n      class=\"btn btn-link\"\n      (click)=\"sendCtrlAltDel()\"\n    >\n      <i [c8yIcon]=\"'keyboard'\"></i>\n      <span translate>Send Ctrl+Alt+Del</span>\n    </button>\n  </c8y-action-bar-item>\n</ng-container>\n\n<ng-container *ngIf=\"powerCapability && status === 'connected'\">\n  <c8y-action-bar-item [placement]=\"'more'\">\n    <button\n      class=\"btn btn-link\"\n      (click)=\"sendShutDown()\"\n    >\n      <i [c8yIcon]=\"'shutdown'\"></i>\n      <span translate>Shutdown</span>\n    </button>\n  </c8y-action-bar-item>\n\n  <c8y-action-bar-item [placement]=\"'more'\">\n    <button\n      class=\"btn btn-link\"\n      (click)=\"sendReboot()\"\n    >\n      <i [c8yIcon]=\"'reset'\"></i>\n      <span translate>Reboot</span>\n    </button>\n  </c8y-action-bar-item>\n\n  <c8y-action-bar-item [placement]=\"'more'\">\n    <button\n      class=\"btn btn-link\"\n      (click)=\"sendReset()\"\n    >\n      <i [c8yIcon]=\"'reset'\"></i>\n      <span translate>Reset</span>\n    </button>\n  </c8y-action-bar-item>\n</ng-container>\n\n<c8y-loading *ngIf=\"status === 'connecting'\"></c8y-loading>\n\n<div\n  class=\"content-fullpage\"\n  [ngClass]=\"{ hidden: status !== 'connected' }\"\n>\n  <div\n    class=\"inner-scroll\"\n    id=\"vnc-screen\"\n  ></div>\n</div>\n", dependencies: [{ kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VncViewerComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-vnc-viewer', standalone: true, imports: [
                        C8yTranslatePipe,
                        TitleComponent,
                        ActionBarItemComponent,
                        C8yTranslateDirective,
                        IconDirective,
                        NgIf,
                        NgClass,
                        LoadingComponent
                    ], template: "<c8y-title>{{ titlePrefix | translate }}: {{ title | translate }}</c8y-title>\n\n<ng-container *ngIf=\"status === 'connected'\">\n  <c8y-action-bar-item [placement]=\"'right'\">\n    <button\n      class=\"btn btn-link\"\n      (click)=\"toggleFullscreen()\"\n    >\n      <i [c8yIcon]=\"'expand'\"></i>\n      <span translate>Fullscreen</span>\n    </button>\n  </c8y-action-bar-item>\n\n  <c8y-action-bar-item [placement]=\"'right'\">\n    <button\n      class=\"btn btn-link\"\n      (click)=\"downloadScreenshot()\"\n    >\n      <i [c8yIcon]=\"'download'\"></i>\n      <span translate>Screenshot</span>\n    </button>\n  </c8y-action-bar-item>\n\n  <c8y-action-bar-item [placement]=\"'more'\">\n    <button\n      class=\"btn btn-link\"\n      (click)=\"sendCtrlAltDel()\"\n    >\n      <i [c8yIcon]=\"'keyboard'\"></i>\n      <span translate>Send Ctrl+Alt+Del</span>\n    </button>\n  </c8y-action-bar-item>\n</ng-container>\n\n<ng-container *ngIf=\"powerCapability && status === 'connected'\">\n  <c8y-action-bar-item [placement]=\"'more'\">\n    <button\n      class=\"btn btn-link\"\n      (click)=\"sendShutDown()\"\n    >\n      <i [c8yIcon]=\"'shutdown'\"></i>\n      <span translate>Shutdown</span>\n    </button>\n  </c8y-action-bar-item>\n\n  <c8y-action-bar-item [placement]=\"'more'\">\n    <button\n      class=\"btn btn-link\"\n      (click)=\"sendReboot()\"\n    >\n      <i [c8yIcon]=\"'reset'\"></i>\n      <span translate>Reboot</span>\n    </button>\n  </c8y-action-bar-item>\n\n  <c8y-action-bar-item [placement]=\"'more'\">\n    <button\n      class=\"btn btn-link\"\n      (click)=\"sendReset()\"\n    >\n      <i [c8yIcon]=\"'reset'\"></i>\n      <span translate>Reset</span>\n    </button>\n  </c8y-action-bar-item>\n</ng-container>\n\n<c8y-loading *ngIf=\"status === 'connecting'\"></c8y-loading>\n\n<div\n  class=\"content-fullpage\"\n  [ngClass]=\"{ hidden: status !== 'connected' }\"\n>\n  <div\n    class=\"inner-scroll\"\n    id=\"vnc-screen\"\n  ></div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1$1.RemoteAccessService }, { type: i2$1.ActivatedRoute }, { type: i2.BsModalService }] });

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

export { VncViewerComponent };
//# sourceMappingURL=c8y-ngx-components-remote-access-vnc-vnc-viewer.mjs.map
