import * as i0 from '@angular/core';
import { InjectionToken, inject, Injectable, Inject, Optional, EventEmitter, Directive, Output, HostListener } from '@angular/core';
import * as i1 from '@angular/router';
import { Router } from '@angular/router';
import { BehaviorSubject, ReplaySubject, take, switchMap, of, EMPTY } from 'rxjs';
import { tap } from 'rxjs/operators';

const RXAP_AUTHENTICATION_DEACTIVATED = new InjectionToken('rxap/authentication/deactivated');
const RXAP_AUTHENTICATION_ACCESS_TOKEN = new InjectionToken('rxap/authentication/access-token', {
    providedIn: 'root',
    factory: () => new BehaviorSubject(null),
});
const RXAP_INITIAL_AUTHENTICATION_STATE = new InjectionToken('rxap/authentication/initial-state', {
    providedIn: 'root',
    factory: () => false,
});
function withDisabledAuthentication(disabled = true) {
    return {
        provide: RXAP_AUTHENTICATION_DEACTIVATED,
        useValue: disabled,
    };
}

var AuthenticationEventType;
(function (AuthenticationEventType) {
    AuthenticationEventType["OnAuthSuccess"] = "on-auth-success";
    AuthenticationEventType["OnAuthError"] = "on-auth-error";
    AuthenticationEventType["OnLogout"] = "on-logout";
})(AuthenticationEventType || (AuthenticationEventType = {}));
class RxapAuthenticationService {
    constructor() {
        this.isAuthenticated$ = new BehaviorSubject(null);
        this.events$ = new ReplaySubject();
        this._authenticated = inject(RXAP_INITIAL_AUTHENTICATION_STATE);
        this.isAuthenticated().then(isAuthenticated => this.isAuthenticated$.next(isAuthenticated));
    }
    async signOut() {
        this._authenticated = false;
        this.isAuthenticated$.next(this._authenticated);
        this.events$.next({ type: AuthenticationEventType.OnLogout });
    }
    isAuthenticated() {
        return Promise.resolve(this._authenticated);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: RxapAuthenticationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: RxapAuthenticationService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: RxapAuthenticationService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [] });

class AuthenticationRoutingService {
    constructor(router, authenticationService, deactivated = null) {
        this.router = router;
        this.authenticationService = authenticationService;
        this.deactivated = deactivated;
        if (!deactivated) {
            console.log('Authentication is enabled');
            this.authenticationService.isAuthenticated$.pipe(tap(isAuthenticated => {
                if (isAuthenticated) {
                    return this.router.navigate(['/']);
                }
                else {
                    return this.router.navigate(['/', 'authentication', 'login']);
                }
            })).subscribe();
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: AuthenticationRoutingService, deps: [{ token: Router }, { token: RxapAuthenticationService }, { token: RXAP_AUTHENTICATION_DEACTIVATED, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: AuthenticationRoutingService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: AuthenticationRoutingService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root',
                }]
        }], ctorParameters: () => [{ type: i1.Router, decorators: [{
                    type: Inject,
                    args: [Router]
                }] }, { type: RxapAuthenticationService, decorators: [{
                    type: Inject,
                    args: [RxapAuthenticationService]
                }] }, { type: undefined, decorators: [{
                    type: Optional
                }, {
                    type: Inject,
                    args: [RXAP_AUTHENTICATION_DEACTIVATED]
                }] }] });

class RxapAuthenticationGuard {
    constructor(authentication, router, deactivated = null) {
        this.authentication = authentication;
        this.router = router;
        this.deactivated = deactivated;
        this.lastUrl = null;
    }
    canActivate(route, state) {
        console.debug('[RxapAuthenticationGuard] can activate', state.url);
        return this.checkAuthStatus(route, state);
    }
    canActivateChild(childRoute, state) {
        console.debug('[RxapAuthenticationGuard] can activate child', state.url);
        return this.checkAuthStatus(childRoute, state);
    }
    async checkAuthStatus(route, state) {
        if (this.deactivated) {
            return true;
        }
        const authenticated = await this.authentication.isAuthenticated();
        if (authenticated === null) {
            if (!this.lastUrl || (state.url !== '/' && !state.url.match(/authentication\/login/))) {
                this.lastUrl = state.url;
            }
            return this.router.createUrlTree(['/', 'authentication', 'loading']);
        }
        if (authenticated) {
            if (this.lastUrl && (state.url /*?*/ === '/' || state.url.match(/authentication\/login/))) {
                const lastUrl = this.lastUrl;
                this.lastUrl = null;
                return this.createUrlTreeToLastUrl(lastUrl);
            }
            else {
                if (state.url.match(/authentication/)) {
                    if (state.url.match(/authentication\/reset-password/)) {
                        return true;
                    }
                    return this.router.createUrlTree(['/']);
                }
                else {
                    this.lastUrl = null;
                    return true;
                }
            }
        }
        else {
            if (!state.url.match(/^\/?authentication/)) {
                this.lastUrl = state.url;
            }
            if (state.url.match(/^\/?authentication/)) {
                if (this.lastUrl && this.lastUrl.match(/^\/?authentication/)) {
                    const lastUrl = this.lastUrl;
                    this.lastUrl = null;
                    return this.createUrlTreeToLastUrl(lastUrl);
                }
                return true;
            }
            else {
                return this.router.createUrlTree(['/', 'authentication', 'login']);
            }
        }
    }
    createUrlTreeToLastUrl(lastUrl) {
        const urlMatch = lastUrl.match(/^([^?#]+)(\?([^#]+))?(#(.+))?$/);
        if (urlMatch) {
            let queryParams = {};
            if (urlMatch[3]) {
                const queryParamsString = urlMatch[3];
                queryParams = queryParamsString.split('&').map(param => {
                    const split = param.split('=');
                    return { [split[0]]: split[1] };
                }).reduce((params, param) => ({ ...params, ...param }), {});
            }
            let fragment = undefined;
            if (urlMatch[5]) {
                fragment = urlMatch[5];
            }
            return this.router.createUrlTree([urlMatch[1]], {
                queryParams,
                fragment,
            });
        }
        return this.router.createUrlTree([lastUrl]);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: RxapAuthenticationGuard, deps: [{ token: RxapAuthenticationService }, { token: Router }, { token: RXAP_AUTHENTICATION_DEACTIVATED, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: RxapAuthenticationGuard, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: RxapAuthenticationGuard, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: RxapAuthenticationService, decorators: [{
                    type: Inject,
                    args: [RxapAuthenticationService]
                }] }, { type: i1.Router, decorators: [{
                    type: Inject,
                    args: [Router]
                }] }, { type: undefined, decorators: [{
                    type: Optional
                }, {
                    type: Inject,
                    args: [RXAP_AUTHENTICATION_DEACTIVATED]
                }] }] });

function BearerTokenInterceptor(req, next) {
    const accessToken$ = inject(RXAP_AUTHENTICATION_ACCESS_TOKEN);
    if (req.url.match(/https?:\/\/[^/]+\/api/)) {
        return accessToken$.pipe(take(1), switchMap(accessToken => {
            if (accessToken && (accessToken.valid === undefined || accessToken.valid)) {
                console.debug('Add access token to request', req.url);
                return next(req.clone({
                    setHeaders: {
                        Authorization: `Bearer ${accessToken.token}`,
                    },
                }));
            }
            else {
                console.debug('No valid access token found!', req.url);
            }
            return next(req);
        }));
    }
    else {
        console.debug('Skip adding access token to request', req.url);
    }
    return next(req);
}

class DisabledAuthenticationService {
    constructor() {
        this.isAuthenticated$ = of(true);
        this.events$ = EMPTY;
    }
    async signOut() {
        console.log('Authentication is disabled. No sign out possible');
    }
    async isAuthenticated() {
        return true;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: DisabledAuthenticationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: DisabledAuthenticationService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: DisabledAuthenticationService, decorators: [{
            type: Injectable
        }] });

function provideAuthentication(service, ...additionalProviders) {
    return [
        {
            provide: RxapAuthenticationService,
            useClass: service,
        },
        ...additionalProviders,
    ];
}
function withInitialAuthenticationState(state) {
    return {
        provide: RXAP_INITIAL_AUTHENTICATION_STATE,
        useValue: state,
    };
}

/* ignore coverage */
class RegisterService {
    constructor() {
        console.warn('The default RegisterService implementation should only be used in a development environment!');
    }
    register(email, password) {
        return Promise.resolve(true);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: RegisterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: RegisterService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: RegisterService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [] });

class SignOutDirective {
    constructor(auth) {
        this.auth = auth;
        this.successful = new EventEmitter();
        this.failure = new EventEmitter();
    }
    async onClick() {
        try {
            await this.auth.signOut();
            this.successful.emit();
        }
        catch (e) {
            this.failure.emit(e);
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: SignOutDirective, deps: [{ token: RxapAuthenticationService }], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.0.1", type: SignOutDirective, isStandalone: true, selector: "[rxapSignOut]", outputs: { successful: "successful", failure: "failure" }, host: { listeners: { "click": "onClick()" } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: SignOutDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[rxapSignOut]',
                    standalone: true,
                }]
        }], ctorParameters: () => [{ type: RxapAuthenticationService }], propDecorators: { successful: [{
                type: Output
            }], failure: [{
                type: Output
            }], onClick: [{
                type: HostListener,
                args: ['click']
            }] } });

// region 
// endregion

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

export { AuthenticationEventType, AuthenticationRoutingService, BearerTokenInterceptor, DisabledAuthenticationService, RXAP_AUTHENTICATION_ACCESS_TOKEN, RXAP_AUTHENTICATION_DEACTIVATED, RXAP_INITIAL_AUTHENTICATION_STATE, RegisterService, RxapAuthenticationGuard, RxapAuthenticationService, SignOutDirective, provideAuthentication, withDisabledAuthentication, withInitialAuthenticationState };
//# sourceMappingURL=rxap-authentication.mjs.map
