/*! firebase-admin v4.0.5
    https://firebase.google.com/terms/ */
"use strict";
var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var deep_copy_1 = require("./deep-copy");
var https = require("https");
/**
 * Base class for handling HTTP requests.
 */
var HttpRequestHandler = (function () {
    function HttpRequestHandler() {
    }
    /**
     * Sends HTTP requests and returns a promise that resolves with the result.
     *
     * @param {string} host The HTTP host.
     * @param {number} port The port number.
     * @param {string} path The endpoint path.
     * @param {HttpMethod} httpMethod The http method.
     * @param {Object} [data] The request JSON.
     * @param {Object} [headers] The request headers.
     * @param {number} [timeout] The request timeout in milliseconds.
     * @return {Promise<Object>} A promise that resolves with the response.
     */
    HttpRequestHandler.prototype.sendRequest = function (host, port, path, httpMethod, data, headers, timeout) {
        var requestData;
        if (data) {
            try {
                requestData = JSON.stringify(data);
            }
            catch (e) {
                return Promise.reject(e);
            }
        }
        var options = {
            method: httpMethod,
            host: host,
            port: port,
            path: path,
            headers: headers,
        };
        // Only https endpoints.
        return new Promise(function (resolve, reject) {
            var req = https.request(options, function (res) {
                var buffers = [];
                res.on('data', function (buffer) { return buffers.push(buffer); });
                res.on('end', function () {
                    try {
                        var json = JSON.parse(Buffer.concat(buffers).toString());
                        resolve(json);
                    }
                    catch (err) {
                        reject('Failed to parse response data: ' + err.toString());
                    }
                });
            });
            if (timeout) {
                // Listen to timeouts and throw a network error.
                req.on('socket', function (socket) {
                    socket.setTimeout(timeout);
                    socket.on('timeout', function () {
                        req.abort();
                        reject(new Error(host + ' network timeout. Try again.'));
                    });
                });
            }
            req.on('error', reject);
            if (requestData) {
                req.write(requestData);
            }
            req.end();
        });
    };
    return HttpRequestHandler;
}());
exports.HttpRequestHandler = HttpRequestHandler;
/**
 * Class that extends HttpRequestHandler and signs HTTP requests with a service
 * credential access token.
 *
 * @param {Credential} credential The service account credential used to
 *     sign HTTP requests.
 * @constructor
 */
var SignedApiRequestHandler = (function (_super) {
    __extends(SignedApiRequestHandler, _super);
    function SignedApiRequestHandler(app_) {
        var _this = _super.call(this) || this;
        _this.app_ = app_;
        return _this;
    }
    /**
     * Sends HTTP requests and returns a promise that resolves with the result.
     *
     * @param {string} host The HTTP host.
     * @param {number} port The port number.
     * @param {string} path The endpoint path.
     * @param {HttpMethod} httpMethod The http method.
     * @param {Object} data The request JSON.
     * @param {Object} headers The request headers.
     * @param {number} timeout The request timeout in milliseconds.
     * @return {Promise} A promise that resolves with the response.
     */
    SignedApiRequestHandler.prototype.sendRequest = function (host, port, path, httpMethod, data, headers, timeout) {
        var ancestorSendRequest = _super.prototype.sendRequest;
        return this.app_.INTERNAL.getToken().then(function (accessTokenObj) {
            if (accessTokenObj == null) {
                return Promise.reject('Unable to fetch Google OAuth2 access token. ' +
                    'Make sure you initialized the SDK with a credential that can f' +
                    'etch access tokens.');
            }
            var headersCopy = deep_copy_1.deepCopy(headers);
            var authorizationHeaderKey = 'Authorization';
            headersCopy[authorizationHeaderKey] = 'Bearer ' + accessTokenObj.accessToken;
            return ancestorSendRequest(host, port, path, httpMethod, data, headersCopy, timeout);
        });
    };
    return SignedApiRequestHandler;
}(HttpRequestHandler));
exports.SignedApiRequestHandler = SignedApiRequestHandler;
/**
 * Class that defines all the settings for the backend API endpoint.
 *
 * @param {string} endpoint The Firebase Auth backend endpoint.
 * @param {HttpMethod} httpMethod The http method for that endpoint.
 * @constructor
 */
var ApiSettings = (function () {
    function ApiSettings(endpoint, httpMethod) {
        if (httpMethod === void 0) { httpMethod = 'POST'; }
        this.endpoint = endpoint;
        this.httpMethod = httpMethod;
        if (!endpoint) {
            throw new Error('Unspecified API settings endpoint');
        }
        this.setRequestValidator(null)
            .setResponseValidator(null);
    }
    /** @return {string} The backend API endpoint. */
    ApiSettings.prototype.getEndpoint = function () {
        return this.endpoint;
    };
    /** @return {HttpMethod} The request HTTP method. */
    ApiSettings.prototype.getHttpMethod = function () {
        return this.httpMethod;
    };
    /**
     * @param {ApiCallbackFunction} requestValidator The request validator.
     * @return {ApiSettings} The current API settings instance.
     */
    ApiSettings.prototype.setRequestValidator = function (requestValidator) {
        var nullFunction = function (request) { return undefined; };
        this.requestValidator = requestValidator || nullFunction;
        return this;
    };
    /** @return {ApiCallbackFunction} The request validator. */
    ApiSettings.prototype.getRequestValidator = function () {
        return this.requestValidator;
    };
    /**
     * @param {ApiCallbackFunction} responseValidator The response validator.
     * @return {ApiSettings} The current API settings instance.
     */
    ApiSettings.prototype.setResponseValidator = function (responseValidator) {
        var nullFunction = function (request) { return undefined; };
        this.responseValidator = responseValidator || nullFunction;
        return this;
    };
    /** @return {ApiCallbackFunction} The response validator. */
    ApiSettings.prototype.getResponseValidator = function () {
        return this.responseValidator;
    };
    return ApiSettings;
}());
exports.ApiSettings = ApiSettings;
