import { __decorate, __awaiter, __generator, __rest, __param, __spread } from 'tslib';
import { Injectable, Injector, Optional, TemplateRef, ViewContainerRef, Directive, Input, ɵɵdefineInjectable, ɵɵinject, APP_INITIALIZER, NgModule } from '@angular/core';
import { first, map, tap, distinctUntilChanged, catchError, filter, take, switchMap, finalize } from 'rxjs/operators';
import { Storage } from '@bravobit/bb-foundation/storage';
import { Api, ApiError } from '@bravobit/bb-foundation/api';
import { BehaviorSubject, of, throwError } from 'rxjs';
import { Router } from '@angular/router';
import { HttpErrorResponse, HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';

var AuthConfig = /** @class */ (function () {
    function AuthConfig() {
    }
    return AuthConfig;
}());

var JwtHelper = /** @class */ (function () {
    function JwtHelper() {
        var _this = this;
        this.baseDecodeUnicode = function (value) {
            return decodeURIComponent(atob(value).replace(/(.)/g, function (m, p) {
                var code = p.charCodeAt(0).toString(16).toUpperCase();
                if (code.length < 2) {
                    code = '0' + code;
                }
                return '%' + code;
            }));
        };
        this.parse = function (data) {
            return {
                id: data['iss'] || null,
                type: data['typ'] || null,
                audience: data['aud'] || null,
                issuer: data['iss'] || null,
                subject: data['sub'] || null,
                role: data['role'] || null,
                notValidBefore: _this.parseDate(data['nbf']),
                expiresAt: _this.parseDate(data['exp']),
                issuedAt: _this.parseDate(data['iat'])
            };
        };
        this.parseDate = function (epochInSeconds) {
            if (!epochInSeconds || epochInSeconds <= 0) {
                return null;
            }
            return new Date(epochInSeconds * 1000);
        };
    }
    JwtHelper.prototype.decode = function (token) {
        try {
            var json = JSON.parse(this.urlDecode(token.split('.')[1]));
            return this.parse(json);
        }
        catch (_a) {
            return null;
        }
    };
    JwtHelper.prototype.urlDecode = function (token) {
        var value = token || '';
        var output = value
            .replace(/-/g, '+')
            .replace(/_/g, '/');
        switch (output.length % 4) {
            case 0:
                break;
            case 2:
                output += '==';
                break;
            case 3:
                output += '=';
                break;
            default:
                throw 'Illegal base64url string!';
        }
        try {
            return this.baseDecodeUnicode(output);
        }
        catch (_a) {
            return atob(output);
        }
    };
    return JwtHelper;
}());

var AuthMapper = /** @class */ (function () {
    function AuthMapper() {
        // Routes.
        this.me = 'auth/me';
        this.register = 'auth/register';
        this.resendCode = 'auth/resend';
        this.logout = 'auth/logout';
        this.refresh = 'auth/refresh';
        this.requestPassword = 'auth/reset';
        this.resetPassword = 'auth/reset-password';
    }
    AuthMapper.prototype.role = function (data) {
        return (data && data.role) || null;
    };
    AuthMapper.prototype.toRegister = function (data) {
        // Retrieve the params.
        var token = data.token, refresh_token = data.refresh_token, user = data.user;
        // Map the data to the correct format.
        return { accessToken: token, refreshToken: refresh_token, user: user };
    };
    AuthMapper.prototype.toRefresh = function (data) {
        // Retrieve the params.
        var token = data.token, refresh_token = data.refresh_token;
        // Map the data to the correct format.
        return { accessToken: token, refreshToken: refresh_token };
    };
    AuthMapper = __decorate([
        Injectable()
    ], AuthMapper);
    return AuthMapper;
}());

var AuthVerifyProvider = /** @class */ (function () {
    function AuthVerifyProvider(_code, _verifyToken, _endpoint) {
        if (_endpoint === void 0) { _endpoint = 'auth/verify'; }
        this._code = _code;
        this._verifyToken = _verifyToken;
        this._endpoint = _endpoint;
    }
    AuthVerifyProvider.prototype.authenticate = function (api) {
        return __awaiter(this, void 0, void 0, function () {
            var _a, token, refresh_token, user;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0: return [4 /*yield*/, api.post(this._endpoint, {
                            token: this._code,
                            verify_token: this._verifyToken
                        })];
                    case 1:
                        _a = _b.sent(), token = _a.token, refresh_token = _a.refresh_token, user = _a.user;
                        // Map the data to the correct format.
                        return [2 /*return*/, { accessToken: token, refreshToken: refresh_token, user: user }];
                }
            });
        });
    };
    return AuthVerifyProvider;
}());

var AuthEmailProvider = /** @class */ (function () {
    function AuthEmailProvider(_email, _password, _endpoint) {
        if (_endpoint === void 0) { _endpoint = 'auth/login'; }
        this._email = _email;
        this._password = _password;
        this._endpoint = _endpoint;
    }
    AuthEmailProvider.prototype.authenticate = function (api) {
        return __awaiter(this, void 0, void 0, function () {
            var _a, token, refresh_token, user, provider, verify_token;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0: return [4 /*yield*/, api.post(this._endpoint, {
                            email: this._email,
                            password: this._password
                        })];
                    case 1:
                        _a = _b.sent(), token = _a.token, refresh_token = _a.refresh_token, user = _a.user, provider = _a.provider, verify_token = _a.verify_token;
                        // Map the data to the correct format.
                        return [2 /*return*/, {
                                accessToken: token,
                                refreshToken: refresh_token,
                                user: user,
                                provider: provider,
                                verifyToken: verify_token
                            }];
                }
            });
        });
    };
    return AuthEmailProvider;
}());

var Auth = /** @class */ (function () {
    function Auth(_storage, _mapper, _injector, _api, _config) {
        this._storage = _storage;
        this._mapper = _mapper;
        this._injector = _injector;
        this._api = _api;
        this._config = _config;
        // Data.
        this._user$ = new BehaviorSubject(null);
        // Validate the API was injected.
        if (!this._api) {
            throw new Error('The API is required for this module to work.');
        }
        // Set the storage keys based on the application id.
        var applicationId = this.getConfigString('applicationId') || 'angular';
        this._apiUserStorageKey = applicationId + "_auth-user";
        this._apiTokenStorageKey = applicationId + "_auth-token";
        this._apiRefreshTokenStorageKey = applicationId + "_auth-refresh-token";
        // Fetch the user from the storage.
        var user = this._storage.cookie.get(this._apiUserStorageKey);
        // Cache the user in memory.
        this._user$.next(user);
    }
    Auth.prototype.initialize = function () {
        var _this = this;
        return function () { return __awaiter(_this, void 0, void 0, function () {
            var shouldBootstrap, user;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        shouldBootstrap = this.getConfigBoolean('bootstrap', true);
                        // Check if the app should bootstrap
                        // the authentication.
                        if (!shouldBootstrap) {
                            return [2 /*return*/];
                        }
                        // Only retrieve from the server
                        // when an access token is saved.
                        if (!this.accessToken && !this.refreshToken) {
                            return [2 /*return*/];
                        }
                        return [4 /*yield*/, this.me().pipe(first()).toPromise()];
                    case 1:
                        user = _a.sent();
                        // Save the user in the storage.
                        return [2 /*return*/, this.setUser(user)];
                }
            });
        }); };
    };
    Object.defineProperty(Auth.prototype, "isAuthenticated", {
        get: function () {
            return !!this.payload;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Auth.prototype, "user", {
        get: function () {
            return this._user$.asObservable();
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Auth.prototype, "accessToken", {
        get: function () {
            return this._storage.cookie.get(this._apiTokenStorageKey);
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Auth.prototype, "refreshToken", {
        get: function () {
            return this._storage.cookie.get(this._apiRefreshTokenStorageKey);
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Auth.prototype, "payload", {
        get: function () {
            return new JwtHelper().decode(this.accessToken);
        },
        enumerable: true,
        configurable: true
    });
    Auth.prototype.me = function () {
        return this._api.get(this._mapper.me);
    };
    Auth.prototype.signIn = function (provider, as) {
        return __awaiter(this, void 0, void 0, function () {
            var _a, accessToken, refreshToken, user, result, apiProvider, apiVerifyToken, availableProviders;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0: return [4 /*yield*/, provider.authenticate(this._api)];
                    case 1:
                        _a = _b.sent(), accessToken = _a.accessToken, refreshToken = _a.refreshToken, user = _a.user, result = __rest(_a, ["accessToken", "refreshToken", "user"]);
                        // Check if the role matches.
                        if (as && !as.includes(this._mapper.role(user))) {
                            throw new Error('Invalid role.');
                        }
                        apiProvider = (result && result.provider) || null;
                        apiVerifyToken = (result && result.verifyToken) || null;
                        availableProviders = ['email', 'sms', 'totp'];
                        if (availableProviders.includes(apiProvider)) {
                            return [2 /*return*/, { user: user, provider: apiProvider, verifyToken: apiVerifyToken }];
                        }
                        // Set the tokens in storage.
                        this.setTokens(accessToken, refreshToken);
                        // Set the user in storage.
                        this.setUser(user);
                        // Return the user.
                        return [2 /*return*/, { user: user }];
                }
            });
        });
    };
    Auth.prototype.signInWithEmail = function (email, password, as) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                return [2 /*return*/, this.signIn(new AuthEmailProvider(email, password), as)];
            });
        });
    };
    Auth.prototype.signInWithVerifyCode = function (code, verifyToken) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                return [2 /*return*/, this.signIn(new AuthVerifyProvider(code, verifyToken))];
            });
        });
    };
    Auth.prototype.resendVerifyCode = function (verifyToken) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this._api.post(this._mapper.resendCode, {
                            verify_token: verifyToken
                        })];
                    case 1: return [2 /*return*/, _a.sent()];
                }
            });
        });
    };
    Auth.prototype.register = function (data) {
        return __awaiter(this, void 0, void 0, function () {
            var result, _a, accessToken, refreshToken, user;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0: return [4 /*yield*/, this._api.post(this._mapper.register, data)];
                    case 1:
                        result = _b.sent();
                        _a = this._mapper.toRegister(result), accessToken = _a.accessToken, refreshToken = _a.refreshToken, user = _a.user;
                        // Set the tokens in storage.
                        this.setTokens(accessToken, refreshToken);
                        // Set the user in storage.
                        this.setUser(user);
                        // Return the user.
                        return [2 /*return*/, user];
                }
            });
        });
    };
    Auth.prototype.logout = function () {
        try {
            // Log the user out.
            this._api.get(this._mapper.logout, { headers: { Authorization: this.refreshToken } })
                .toPromise().then(function (_) { return _; });
        }
        catch (_a) {
            // Do nothing because the tokens will be deleted anyways from the storage.
        }
        // Delete the tokens from the session.
        return this.clear();
    };
    Auth.prototype.refresh = function () {
        var _this = this;
        // If the refresh token does
        // not exist just return an observable of null.
        if (!this.refreshToken) {
            return of(null);
        }
        // Perform the refresh call.
        var scheme = this.getConfigString('schema', 'Bearer');
        return this._api.get(this._mapper.refresh, {
            headers: {
                'Authorization': scheme + " " + this.refreshToken,
                'X-No-Authorization': 'yes'
            }
        }).pipe(map(function (data) { return _this._mapper.toRefresh(data); }), tap(function (_a) {
            var accessToken = _a.accessToken, refreshToken = _a.refreshToken;
            return _this.setTokens(accessToken, refreshToken);
        }), map(function (_a) {
            var accessToken = _a.accessToken;
            return accessToken;
        }));
    };
    Auth.prototype.requestPassword = function (email) {
        return __awaiter(this, void 0, void 0, function () {
            var error_1;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        _a.trys.push([0, 2, , 3]);
                        return [4 /*yield*/, this._api.post(this._mapper.requestPassword, { email: email })];
                    case 1: return [2 /*return*/, _a.sent()];
                    case 2:
                        error_1 = _a.sent();
                        throw error_1;
                    case 3: return [2 /*return*/];
                }
            });
        });
    };
    Auth.prototype.resetPassword = function (token, newPassword) {
        return __awaiter(this, void 0, void 0, function () {
            var error_2;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        _a.trys.push([0, 2, , 3]);
                        return [4 /*yield*/, this._api.post(this._mapper.resetPassword, { token: token, password: newPassword })];
                    case 1: return [2 /*return*/, _a.sent()];
                    case 2:
                        error_2 = _a.sent();
                        throw error_2;
                    case 3: return [2 /*return*/];
                }
            });
        });
    };
    Auth.prototype.guard = function (type, redirectUrl) {
        var newUrl = null;
        // Get the correct new url.
        switch (type) {
            case 'authenticated':
                newUrl = this.getConfigString('loggedInUrl', null);
                break;
            case 'unauthenticated':
                newUrl = this.getConfigString('redirectUrl', null);
                break;
        }
        // Append a redirect url if the user is deemed
        // unauthenticated.
        if (type === 'unauthenticated') {
            var setRedirectOnFailedAuth = this.getConfigBoolean('setRedirectOnFailedAuth', true);
            if (setRedirectOnFailedAuth && redirectUrl && newUrl) {
                newUrl += "?redirectUrl=" + redirectUrl;
            }
        }
        // Parse the url if it exists.
        if (this.router && newUrl) {
            return this.router.parseUrl(newUrl);
        }
        // Return false if the user is not allowed.
        return false;
    };
    Auth.prototype.setTokens = function (accessToken, refreshToken) {
        // Set the token if the token exists.
        if (accessToken) {
            var expiresAt = new JwtHelper().decode(accessToken).expiresAt;
            this._storage.cookie.set(this._apiTokenStorageKey, accessToken, {
                expires: expiresAt
            });
        }
        // Set the refresh token if the refresh token exists.
        if (refreshToken) {
            var expiresAt = new JwtHelper().decode(refreshToken).expiresAt;
            this._storage.cookie.set(this._apiRefreshTokenStorageKey, refreshToken, {
                expires: expiresAt
            });
        }
    };
    Auth.prototype.setUser = function (user) {
        // Validate the user exists.
        if (!user) {
            return;
        }
        // Push the next user.
        this._user$.next(user);
        // Make the user data valid for one year.
        var date = new Date();
        date.setFullYear(date.getFullYear() + 1);
        var timestamp = date.getTime();
        // Save the user in the storage.
        return this._storage.cookie.set(this._apiUserStorageKey, user, {
            expires: timestamp
        });
    };
    Auth.prototype.clear = function () {
        // Delete the items from the local storage.
        this._storage.cookie.remove(this._apiUserStorageKey);
        this._storage.cookie.remove(this._apiTokenStorageKey);
        this._storage.cookie.remove(this._apiRefreshTokenStorageKey);
        // Push an empty user.
        this._user$.next(null);
    };
    Object.defineProperty(Auth.prototype, "router", {
        get: function () {
            return this._injector.get(Router);
        },
        enumerable: true,
        configurable: true
    });
    Auth.prototype.getConfigBoolean = function (name, defaultValue) {
        if (defaultValue === void 0) { defaultValue = false; }
        return (this._config && this._config[name]) === undefined
            ? defaultValue
            : this._config[name];
    };
    Auth.prototype.getConfigString = function (name, defaultValue) {
        if (defaultValue === void 0) { defaultValue = null; }
        return (this._config && this._config[name]) === undefined
            ? defaultValue
            : this._config[name];
    };
    Auth.ctorParameters = function () { return [
        { type: Storage },
        { type: AuthMapper },
        { type: Injector },
        { type: Api, decorators: [{ type: Optional }] },
        { type: AuthConfig, decorators: [{ type: Optional }] }
    ]; };
    Auth = __decorate([
        Injectable(),
        __param(3, Optional()),
        __param(4, Optional())
    ], Auth);
    return Auth;
}());

var BbAuthenticated = /** @class */ (function () {
    function BbAuthenticated(_auth, _template, _viewContainerRef) {
        this._auth = _auth;
        this._template = _template;
        this._viewContainerRef = _viewContainerRef;
    }
    BbAuthenticated.prototype.ngOnInit = function () {
        var _this = this;
        this._subscription = this._auth.user.pipe(map(function (user) { return !!user; }), distinctUntilChanged()).subscribe(function (isAuthenticated) {
            if (isAuthenticated) {
                _this._viewContainerRef.createEmbeddedView(_this._template);
            }
            else {
                _this._viewContainerRef.clear();
            }
        });
    };
    BbAuthenticated.prototype.ngOnDestroy = function () {
        this._subscription && this._subscription.unsubscribe();
    };
    BbAuthenticated.ctorParameters = function () { return [
        { type: Auth },
        { type: TemplateRef },
        { type: ViewContainerRef }
    ]; };
    BbAuthenticated = __decorate([
        Directive({
            selector: '[bbAuthenticated]'
        })
    ], BbAuthenticated);
    return BbAuthenticated;
}());

var BbRole = /** @class */ (function () {
    function BbRole(_auth, _template, _viewContainerRef) {
        this._auth = _auth;
        this._template = _template;
        this._viewContainerRef = _viewContainerRef;
        this.getPermissions = function (value) {
            return Array.isArray(value) ? value : [value];
        };
    }
    BbRole.prototype.ngOnInit = function () {
        var _this = this;
        this._subscription = this._auth.user.pipe(map(function (user) { return (user && user.role) || null; }), distinctUntilChanged()).subscribe(function (role) {
            var permissions = _this.getPermissions(_this.bbRole);
            if (permissions.includes(role)) {
                _this._viewContainerRef.createEmbeddedView(_this._template);
            }
            else {
                _this._viewContainerRef.clear();
            }
        });
    };
    BbRole.prototype.ngOnDestroy = function () {
        this._subscription && this._subscription.unsubscribe();
    };
    BbRole.ctorParameters = function () { return [
        { type: Auth },
        { type: TemplateRef },
        { type: ViewContainerRef }
    ]; };
    __decorate([
        Input()
    ], BbRole.prototype, "bbRole", void 0);
    BbRole = __decorate([
        Directive({
            selector: '[bbRole]'
        })
    ], BbRole);
    return BbRole;
}());

var BbAnonymousGuard = /** @class */ (function () {
    function BbAnonymousGuard(_auth) {
        this._auth = _auth;
    }
    BbAnonymousGuard.prototype.canActivate = function (route, state) {
        return __awaiter(this, void 0, void 0, function () {
            var isAuthenticated;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this._auth.user.pipe(map(function (user) { return !!user; }), first()).toPromise()];
                    case 1:
                        isAuthenticated = _a.sent();
                        // If the user is not authenticated it can
                        // access the anonymous page.
                        if (!isAuthenticated) {
                            return [2 /*return*/, true];
                        }
                        // Return the user back to the authenticated page.
                        return [2 /*return*/, this._auth.guard('authenticated', state.url)];
                }
            });
        });
    };
    BbAnonymousGuard.prototype.canActivateChild = function (childRoute, state) {
        return this.canActivate(childRoute, state);
    };
    BbAnonymousGuard.ctorParameters = function () { return [
        { type: Auth }
    ]; };
    BbAnonymousGuard.ɵprov = ɵɵdefineInjectable({ factory: function BbAnonymousGuard_Factory() { return new BbAnonymousGuard(ɵɵinject(Auth)); }, token: BbAnonymousGuard, providedIn: "root" });
    BbAnonymousGuard = __decorate([
        Injectable({
            providedIn: 'root'
        })
    ], BbAnonymousGuard);
    return BbAnonymousGuard;
}());

var BbAuthenticatedGuard = /** @class */ (function () {
    function BbAuthenticatedGuard(_auth) {
        this._auth = _auth;
    }
    BbAuthenticatedGuard.prototype.canActivate = function (route, state) {
        return __awaiter(this, void 0, void 0, function () {
            var isAuthenticated;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this._auth.user.pipe(map(function (user) { return !!user; }), first()).toPromise()];
                    case 1:
                        isAuthenticated = _a.sent();
                        // If the user is authenticated it can
                        // access the authenticated page.
                        if (isAuthenticated) {
                            return [2 /*return*/, true];
                        }
                        // The user is not authorized to see that
                        // page so un-authorize him.
                        return [2 /*return*/, this._auth.guard('unauthenticated', state.url)];
                }
            });
        });
    };
    BbAuthenticatedGuard.prototype.canActivateChild = function (childRoute, state) {
        return this.canActivate(childRoute, state);
    };
    BbAuthenticatedGuard.ctorParameters = function () { return [
        { type: Auth }
    ]; };
    BbAuthenticatedGuard.ɵprov = ɵɵdefineInjectable({ factory: function BbAuthenticatedGuard_Factory() { return new BbAuthenticatedGuard(ɵɵinject(Auth)); }, token: BbAuthenticatedGuard, providedIn: "root" });
    BbAuthenticatedGuard = __decorate([
        Injectable({
            providedIn: 'root'
        })
    ], BbAuthenticatedGuard);
    return BbAuthenticatedGuard;
}());

var AuthInterceptor = /** @class */ (function () {
    function AuthInterceptor(_auth, _router, _config) {
        var _this = this;
        this._auth = _auth;
        this._router = _router;
        this._config = _config;
        // Data.
        this.isRefreshing = false;
        this.token$ = new BehaviorSubject(null);
        this.getToken = function (request) {
            // Get the token based on header.
            if (request.headers.has('Authorization')) {
                return request.headers.get('Authorization');
            }
            // Return the default access token.
            return _this._auth.accessToken;
        };
        this.composeRequest = function (request, token) {
            if (token === void 0) { token = null; }
            // If the token is not set, delete the authorization header.
            if (!token) {
                return request.clone({ headers: request.headers.delete('Authorization') });
            }
            // Get the auth scheme from the config,
            // if the scheme was not set use bearer.
            var authScheme = (_this._config && _this._config.scheme) || 'Bearer';
            // Clone and add the authorization header.
            return request.clone({
                setHeaders: { Authorization: authScheme + " " + token }
            });
        };
    }
    AuthInterceptor.prototype.intercept = function (request, next) {
        var _this = this;
        // Just return when the user is performing an refresh request.
        if (request.headers.has('X-No-Authorization')) {
            var newRequest_1 = request.clone({ headers: request.headers.delete('X-No-Authorization') });
            return next.handle(newRequest_1);
        }
        // Compose the new request.
        var newRequest = this.composeRequest(request, this.getToken(request));
        // Handle all errors.
        return next.handle(newRequest).pipe(catchError(function (error) {
            // Create a custom error.
            var apiError = new ApiError(error.status, error.error);
            // Check if it is an error response.
            if (!(error instanceof HttpErrorResponse)) {
                return throwError(apiError);
            }
            // Handle a 401 error.
            if (error.status === 401) {
                return _this.handle401Error(request, next);
            }
            // Just re-throw the error.
            return throwError(apiError);
        }));
    };
    AuthInterceptor.prototype.handle401Error = function (request, next) {
        var _this = this;
        // If already refreshing wait for the token to complete.
        if (this.isRefreshing) {
            return this.token$.pipe(filter(function (token) { return token !== null; }), take(1), switchMap(function (token) { return next.handle(_this.composeRequest(request, token)); }));
        }
        // Set the refreshing to true.
        this.isRefreshing = true;
        this.token$.next(null);
        return this._auth.refresh().pipe(switchMap(function (newToken) {
            if (!newToken) {
                return throwError('No refresh token was available.');
            }
            _this.token$.next(newToken);
            return next.handle(_this.composeRequest(request, newToken));
        }), catchError(function (error) {
            return _this.logoutUser(error);
        }), finalize(function () {
            _this.isRefreshing = false;
        }));
    };
    AuthInterceptor.prototype.logoutUser = function (error) {
        // Delete the tokens from the session.
        this._auth.clear();
        // Compose the route url.
        var routeUrl = this._config && this._config.redirectUrl;
        // Route back if the user provided a redirect url.
        if (this._router && routeUrl) {
            this._router.navigate([routeUrl]).then(function (_) { return _; });
        }
        // Throw the error.
        return throwError(error || 'Invalid refresh token; user was logged out.');
    };
    AuthInterceptor.ctorParameters = function () { return [
        { type: Auth },
        { type: Router, decorators: [{ type: Optional }] },
        { type: AuthConfig, decorators: [{ type: Optional }] }
    ]; };
    AuthInterceptor = __decorate([
        Injectable(),
        __param(1, Optional()),
        __param(2, Optional())
    ], AuthInterceptor);
    return AuthInterceptor;
}());

var DECLARATIONS_EXPORTS = [
    BbAuthenticated,
    BbRole
];
var AuthModule = /** @class */ (function () {
    function AuthModule() {
    }
    AuthModule_1 = AuthModule;
    AuthModule.forRoot = function (config) {
        return {
            ngModule: AuthModule_1,
            providers: [
                Auth,
                { provide: AuthConfig, useValue: config },
                { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
                { useFactory: initializeAuth, provide: APP_INITIALIZER, deps: [Auth], multi: true }
            ]
        };
    };
    var AuthModule_1;
    AuthModule = AuthModule_1 = __decorate([
        NgModule({
            imports: [HttpClientModule],
            declarations: __spread(DECLARATIONS_EXPORTS),
            exports: __spread(DECLARATIONS_EXPORTS),
            providers: [
                { provide: AuthMapper, useClass: AuthMapper }
            ]
        })
    ], AuthModule);
    return AuthModule;
}());
function initializeAuth(auth) {
    return auth.initialize();
}

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

export { Auth, AuthConfig, AuthEmailProvider, AuthMapper, AuthModule, AuthVerifyProvider, BbAnonymousGuard, BbAuthenticated, BbAuthenticatedGuard, BbRole, JwtHelper, initializeAuth, AuthInterceptor as ɵa };
//# sourceMappingURL=bravobit-bb-foundation-auth.js.map
