"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.EnsembleAuthService = void 0;
const XHR_1 = require("../../icc-api/api/XHR");
var XHRError = XHR_1.XHR.XHRError;
class EnsembleAuthService {
    constructor(jwtAuth, sessionAuth, basicAuth) {
        this.jwtAuth = jwtAuth;
        this.sessionAuth = sessionAuth;
        this.basicAuth = basicAuth;
        this.error = null;
        this.jwtGetter = this.getIcureTokens;
        this.stateMap = {
            start: { state: null, next: 'jwt' },
            jwt: { state: this.jwtAuth, next: 'session' },
            session: { state: this.sessionAuth, next: 'basic' },
            basic: { state: this.basicAuth, next: null },
        };
        this.currentState = 'start';
    }
    getIcureTokens() {
        var _a, _b;
        return (_b = (_a = this.jwtAuth) === null || _a === void 0 ? void 0 : _a.getIcureTokens()) !== null && _b !== void 0 ? _b : Promise.resolve();
    }
    getAuthHeaders(minimumAuthenticationClass) {
        return __awaiter(this, void 0, void 0, function* () {
            this.currentState = !!this.currentState ? this.stateMap[this.currentState].next : this.currentState;
            if (!!this.currentState) {
                // If I have a state I return the headers, otherwise I return empty headers
                // And delegate the responsibility of handling the error to the next call
                return !!this.stateMap[this.currentState].state
                    ? this.stateMap[this.currentState].state.getAuthHeaders(minimumAuthenticationClass).catch((e) => {
                        if (e instanceof XHRError && e.statusCode === 417) {
                            throw e;
                        }
                        // If I get an error, it is also responsibility of the next call, but I give a warning
                        console.warn(e.message);
                        this.error = e;
                        return [];
                    })
                    : Promise.resolve([]);
            }
            else if (!!this.error) {
                // If I have no more states, I throw the last error or a default one
                throw this.error;
            }
            else {
                throw new Error('Cannot authenticate');
            }
        });
    }
    invalidateHeader(error) {
        var _a;
        this.error = error;
        if (!!this.currentState) {
            (_a = this.stateMap[this.currentState].state) === null || _a === void 0 ? void 0 : _a.invalidateHeader(error);
        }
    }
}
exports.EnsembleAuthService = EnsembleAuthService;
//# sourceMappingURL=EnsembleAuthService.js.map