"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const url = require("url");
const utils = require("@cobalt-engine/utils");
const requestPromise = require("request-promise-native");
const request = require("request");
const Custom_error_1 = require("../Custom-error");
const WizError_1 = require("../WizError");
const createOutputStream = require("create-output-stream");
const Config_1 = require("../Config");
class Request {
    constructor() { }
    get(url, data) {
        return sendRequest('GET', url, data);
    }
    post(url, data) {
        return sendRequest('POST', url, data);
    }
    put(url, data) {
        return sendRequest('PUT', url, data);
    }
    delete(url, data) {
        return sendRequest('DELETE', url, data);
    }
    patch(url, data) {
        return sendRequest('PATCH', url, data);
    }
    download(url, filename, data) {
        return Promise.resolve(this.downloadProcces(url, filename, data))
            .then(() => { })
            .catch(err => errorHandler(err, url));
    }
    downloadProcces(url, filename, data) {
        return this.getStream(url, data)
            .then((res) => {
            const output = new Promise((resolve, reject) => {
                const outputStream = createOutputStream(filename);
                outputStream.once('close', () => {
                    resolve();
                });
                outputStream.on('error', reject);
                res.pipe(outputStream);
            });
            return output;
        });
    }
    getStream(url, data) {
        return new Promise((resolve, reject) => {
            request.get(url, data)
                .on('response', (response) => {
                if (response.statusCode !== 200) {
                    const statusCode = response.statusCode;
                    if (statusCode) {
                        reject(new Custom_error_1.default(statusCode));
                    }
                    else {
                        reject(new Custom_error_1.default('Server error'));
                    }
                }
                resolve(response);
            })
                .on('error', reject);
        });
    }
}
exports.default = Request;
function sendRequest(method, url, data = {}) {
    return Config_1.Config.get()
        .then(config => config.authServer.realm)
        .then(tenant => Object.assign(data, {
        method,
        uri: url,
        transform: parseResponse,
        headers: {
            tenant
        }
    }))
        .then(options => requestPromise(options))
        .catch(err => errorHandler(err.cause, url));
}
function parseResponse(body, res) {
    const data = utils.jsonOrText(body);
    if (res.statusCode === 200) {
        return data;
    }
    if (data.error && data.error_description) {
        throw new Custom_error_1.default(data.error.toUpperCase(), data.error_description);
    }
    if (data.status && data.message) {
        throw new Custom_error_1.default(data.status, data.message);
    }
    if (res.statusCode) {
        throw new Custom_error_1.default(res.statusCode);
    }
}
function errorHandler(err, url) {
    if (isInvalidUrlError(err)) {
        throw new WizError_1.WizError('INVALID_URL', url);
    }
    else if (isServerError(err)) {
        throw new WizError_1.WizError('SERVER_UNAVAILABLE', extractHost(url));
    }
    throw err;
}
function extractHost(fullUrl) {
    const urlObj = url.parse(fullUrl);
    return url.format({
        protocol: urlObj.protocol,
        host: urlObj.host,
    });
}
function isInvalidUrlError(err) {
    return err.message && err.message.indexOf('Invalid URI') > -1 || err.code === 'ENOTFOUND';
}
function isServerError(err) {
    return err.code === 'SERVER_ERROR';
}
//# sourceMappingURL=index.js.map