"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.JwtAuthService = void 0;
const XHR_1 = require("../../icc-api/api/XHR");
const JwtUtils_1 = require("./JwtUtils");
const JwtError_1 = require("./JwtError");
/**
 * Differs from JwtBridgedAuthService in that it cannot create new refresh tokens
 */
class JwtAuthService {
    constructor(authApi, initialJwt) {
        this.authApi = authApi;
        this._error = null;
        this._currentPromise = Promise.resolve(undefined);
        this.jwtGetter = this.getIcureTokens;
        if (!!initialJwt) {
            this._currentPromise = Promise.resolve(initialJwt);
        }
    }
    get refreshToken() {
        return this._currentPromise.then((x) => x === null || x === void 0 ? void 0 : x.refreshJwt);
    }
    getIcureTokens() {
        return this._currentPromise.then((x) => (x ? { token: x.authJwt, refreshToken: x.refreshJwt } : undefined));
    }
    getAuthHeaders() {
        return __awaiter(this, void 0, void 0, function* () {
            return this._currentPromise
                .then((x) => ({ authJwt: x === null || x === void 0 ? void 0 : x.authJwt, refreshJwt: x === null || x === void 0 ? void 0 : x.refreshJwt }), (e) => {
                if (e instanceof JwtError_1.JwtError && !!e.jwt && !!e.refreshJwt) {
                    return { authJwt: e.jwt, refreshJwt: e.refreshJwt };
                }
                else {
                    throw new Error('There was an error while refreshing the token, please re-instantiate the API.');
                }
            })
                .then((x) => {
                const authJwt = x === null || x === void 0 ? void 0 : x.authJwt;
                const refreshJwt = x === null || x === void 0 ? void 0 : x.refreshJwt;
                if ((!authJwt || (0, JwtUtils_1.isJwtInvalidOrExpired)(authJwt)) && refreshJwt) {
                    // If it does not have the JWT, tries to get it
                    // If the JWT is expired, tries to refresh it
                    this._currentPromise = this._refreshAuthJwt(refreshJwt).then((updatedTokens) => {
                        // If here the token is null,
                        // it goes in a suspension status
                        if (!updatedTokens.authJwt) {
                            throw new Error('Your iCure back-end version does not support JWT authentication');
                        }
                        return updatedTokens;
                    }, (e) => {
                        throw new JwtError_1.JwtError(authJwt, refreshJwt, 'There was an error while refreshing the token, please re-instantiate the API or try again.', e);
                    });
                }
                else if (!!this._error) {
                    throw this._error;
                }
                return this._currentPromise;
            })
                .then((x) => {
                return (x === null || x === void 0 ? void 0 : x.authJwt) ? [new XHR_1.XHR.Header('Authorization', `Bearer ${x.authJwt}`)] : Promise.reject('Cannot provide auth: No JWT');
            });
        });
    }
    _refreshAuthJwt(refreshJwt) {
        return __awaiter(this, void 0, void 0, function* () {
            // If I do not have a refresh JWT or the refresh JWT is expired,
            // I have to log in again
            if ((0, JwtUtils_1.isJwtInvalidOrExpired)(refreshJwt)) {
                throw Error('Missing or expired refresh token: please log in again');
            }
            else {
                return this.authApi.refreshAuthenticationJWT(refreshJwt).then((refreshResponse) => ({
                    authJwt: refreshResponse.token,
                    refreshJwt: refreshJwt,
                }));
            }
        });
    }
    invalidateHeader(error) {
        this._error = error;
    }
    isInErrorState() {
        return !!this._error;
    }
}
exports.JwtAuthService = JwtAuthService;
//# sourceMappingURL=JwtAuthService.js.map