"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils = require("@cobalt-engine/utils");
const fs = require("fs");
const WizError_1 = require("../WizError");
const Config_1 = require("../Config");
const stream_1 = require("stream");
const Request_1 = require("../Request");
const config = Config_1.Config.getSync();
class SecureRequest extends Request_1.default {
    constructor(tokenHandler, authService) {
        super();
        this.tokenHandler = tokenHandler;
        this.authService = authService;
    }
    get(url, options = {}) {
        return this.sendRequest(data => super.get(url, utils.deepMixin(options, data)));
    }
    post(url, options = {}) {
        return this.sendRequest(data => super.post(url, createFormData(data, options)));
    }
    put(url, options = {}) {
        return this.sendRequest(data => super.put(url, createFormData(data, options)));
    }
    patch(url, options = {}) {
        return this.sendRequest(data => super.patch(url, createFormData(data, options)));
    }
    delete(url, options = {}) {
        return this.sendRequest(data => super.delete(url, createFormData(data, options)));
    }
    sendRequest(request) {
        const sendRequest = this.createRequestWithAuth(request);
        return this.tokenHandler.get()
            .then(sendRequest)
            .catch(err => this.refreshTokenAndTryAgain(err, sendRequest));
    }
    createRequestWithAuth(request) {
        return data => request({
            headers: {
                authorization: `Bearer ${data.access_token}`,
                realm: config.authServer.realm,
            },
        });
    }
    refreshTokenAndTryAgain(err, action) {
        if (isNotAuthorized(err.code)) {
            return this.authService.refreshTokenAndTryAgain(action)
                .catch(authErrorHandler);
        }
        throw err;
    }
}
exports.default = SecureRequest;
function authErrorHandler(err) {
    if (hasNoPermission(err.code)) {
        throw new WizError_1.WizError('FORBIDDEN');
    }
    if (isNotAuthorized(err.code)) {
        throw new WizError_1.WizError('NOT_LOGGED_IN');
    }
    throw err;
}
function isNotAuthorized(code) {
    return code === 'FORBIDDEN' || code === 'UNAUTHORIZED' || code === 'TOKEN_EXPIRED';
}
function hasNoPermission(code) {
    return code === 'FORBIDDEN';
}
function createFormData(data, options) {
    return utils.deepMixin(data, {
        formData: refreshClosedStreams(options.formData),
        form: refreshClosedStreams(options.form),
    });
}
function refreshClosedStreams(data) {
    if (!data) {
        return;
    }
    return Object.keys(data).reduce((acc, key) => {
        const value = data[key];
        if (value instanceof stream_1.Readable && value.closed) {
            acc[key] = fs.createReadStream(value.path);
        }
        else {
            acc[key] = value;
        }
        return acc;
    }, {});
}
//# sourceMappingURL=index.js.map