"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApiLogger = void 0;
var tslib_1 = require("tslib");
var httpHeaders_1 = require("../http/httpHeaders");
/**
 * Represents a logger implementation for API logging.
 * This logger provides methods to log HTTP requests and responses.
 */
var ApiLogger = /** @class */ (function () {
    /**
     * Constructs a new instance of ApiLogger.
     * @param loggingOpt The logging options for configuring the logger behavior.
     */
    function ApiLogger(loggingOpt) {
        this._loggingOptions = loggingOpt;
        this._logger = loggingOpt.logger;
    }
    /**
     * Logs an HTTP request.
     * @param request The HTTP request to log.
     */
    ApiLogger.prototype.logRequest = function (request) {
        var logLevel = this._loggingOptions.logLevel;
        var contentTypeHeader = this._getContentType(request.headers);
        var url = this._loggingOptions.logRequest.includeQueryInPath
            ? request.url
            : this._removeQueryParams(request.url);
        this._logger.log(logLevel, 'Request ${method} ${url} ${contentType}', {
            method: request.method,
            url: url,
            contentType: contentTypeHeader,
        });
        this._applyLogRequestOptions(logLevel, request);
    };
    /**
     * Logs an HTTP response.
     * @param response The HTTP response to log.
     */
    ApiLogger.prototype.logResponse = function (response) {
        var logLevel = this._loggingOptions.logLevel;
        var contentTypeHeader = this._getContentType(response.headers);
        var contentLengthHeader = this._getContentLength(response.headers);
        this._logger.log(logLevel, 'Response ${statusCode} ${contentLength} ${contentType}', {
            statusCode: response.statusCode,
            contentLength: contentLengthHeader,
            contentType: contentTypeHeader,
        });
        this._applyLogResponseOptions(logLevel, response);
    };
    ApiLogger.prototype._applyLogRequestOptions = function (level, request) {
        this._applyLogRequestHeaders(level, request, this._loggingOptions.logRequest);
        this._applyLogRequestBody(level, request, this._loggingOptions.logRequest);
    };
    ApiLogger.prototype._applyLogRequestHeaders = function (level, request, logRequest) {
        var _a, _b;
        var logHeaders = logRequest.logHeaders, headersToInclude = logRequest.headersToInclude, headersToExclude = logRequest.headersToExclude, headersToWhitelist = logRequest.headersToWhitelist;
        if (logHeaders) {
            var clonedHeaders = tslib_1.__assign({}, request.headers);
            // If request.auth exists, encode it as Basic Auth and add it in cloned headers
            if (((_a = request.auth) === null || _a === void 0 ? void 0 : _a.username) && ((_b = request.auth) === null || _b === void 0 ? void 0 : _b.password)) {
                var authString = "".concat(request.auth.username, ":").concat(request.auth.password);
                clonedHeaders.Authorization = "Basic ".concat(Buffer.from(authString, 'utf-8').toString('base64'));
            }
            var headersToLog = this._extractHeadersToLog(headersToInclude, headersToExclude, headersToWhitelist, clonedHeaders);
            this._logger.log(level, 'Request headers ${headers}', {
                headers: headersToLog,
            });
        }
    };
    ApiLogger.prototype._applyLogRequestBody = function (level, request, logRequest) {
        if (logRequest.logBody) {
            this._logger.log(level, 'Request body ${body}', {
                body: request.body,
            });
        }
    };
    ApiLogger.prototype._applyLogResponseOptions = function (level, response) {
        this._applyLogResponseHeaders(level, response, this._loggingOptions.logResponse);
        this._applyLogResponseBody(level, response, this._loggingOptions.logResponse);
    };
    ApiLogger.prototype._applyLogResponseHeaders = function (level, response, logResponse) {
        var logHeaders = logResponse.logHeaders, headersToInclude = logResponse.headersToInclude, headersToExclude = logResponse.headersToExclude, headersToWhitelist = logResponse.headersToWhitelist;
        if (logHeaders) {
            var headersToLog = this._extractHeadersToLog(headersToInclude, headersToExclude, headersToWhitelist, response.headers);
            this._logger.log(level, 'Response headers ${headers}', {
                headers: headersToLog,
            });
        }
    };
    ApiLogger.prototype._applyLogResponseBody = function (level, response, logResponse) {
        if (logResponse.logBody) {
            this._logger.log(level, 'Response body ${body}', {
                body: response.body,
            });
        }
    };
    ApiLogger.prototype._getContentType = function (headers) {
        var _a;
        return headers ? (_a = (0, httpHeaders_1.getHeader)(headers, httpHeaders_1.CONTENT_TYPE_HEADER)) !== null && _a !== void 0 ? _a : '' : '';
    };
    ApiLogger.prototype._getContentLength = function (headers) {
        var _a;
        return headers ? (_a = (0, httpHeaders_1.getHeader)(headers, httpHeaders_1.CONTENT_LENGTH_HEADER)) !== null && _a !== void 0 ? _a : '' : '';
    };
    ApiLogger.prototype._removeQueryParams = function (url) {
        var queryStringIndex = url.indexOf('?');
        return queryStringIndex !== -1 ? url.substring(0, queryStringIndex) : url;
    };
    ApiLogger.prototype._extractHeadersToLog = function (headersToInclude, headersToExclude, headersToWhitelist, headers) {
        var filteredHeaders = {};
        if (!headers) {
            return {};
        }
        if (headersToInclude.length > 0) {
            filteredHeaders = this._includeHeadersToLog(headers, filteredHeaders, headersToInclude);
        }
        else if (headersToExclude.length > 0) {
            filteredHeaders = this._excludeHeadersToLog(headers, filteredHeaders, headersToExclude);
        }
        else {
            filteredHeaders = headers;
        }
        return this._maskSenstiveHeaders(filteredHeaders, headersToWhitelist);
    };
    ApiLogger.prototype._includeHeadersToLog = function (headers, filteredHeaders, headersToInclude) {
        // Filter headers based on the keys specified in headersToInclude
        headersToInclude.forEach(function (name) {
            var key = Object.keys(headers).find(function (headerKey) { return headerKey.toLowerCase() === name.toLowerCase(); });
            var val = (0, httpHeaders_1.getHeader)(headers, name);
            if (val !== null && key) {
                filteredHeaders[key] = val;
            }
        });
        return filteredHeaders;
    };
    ApiLogger.prototype._excludeHeadersToLog = function (headers, filteredHeaders, headersToExclude) {
        var e_1, _a;
        var _loop_1 = function (key) {
            if (!headersToExclude.some(function (excludedName) { return excludedName.toLowerCase() === key.toLowerCase(); })) {
                var value = (0, httpHeaders_1.getHeader)(headers, key);
                if (value !== null) {
                    filteredHeaders[key] = value;
                }
            }
        };
        try {
            // Filter headers based on the keys specified in headersToExclude
            for (var _b = tslib_1.__values(Object.keys(headers)), _c = _b.next(); !_c.done; _c = _b.next()) {
                var key = _c.value;
                _loop_1(key);
            }
        }
        catch (e_1_1) { e_1 = { error: e_1_1 }; }
        finally {
            try {
                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
            }
            finally { if (e_1) throw e_1.error; }
        }
        return filteredHeaders;
    };
    ApiLogger.prototype._maskSenstiveHeaders = function (headers, headersToWhitelist) {
        var e_2, _a;
        var _b;
        var masked_headers = tslib_1.__assign({}, headers);
        if (this._loggingOptions.maskSensitiveHeaders) {
            try {
                for (var _c = tslib_1.__values(Object.keys(headers)), _d = _c.next(); !_d.done; _d = _c.next()) {
                    var key = _d.value;
                    var val = (_b = (0, httpHeaders_1.getHeader)(headers, key)) !== null && _b !== void 0 ? _b : '';
                    (0, httpHeaders_1.setHeader)(masked_headers, key, this._maskIfSenstiveHeader(key, val, headersToWhitelist));
                }
            }
            catch (e_2_1) { e_2 = { error: e_2_1 }; }
            finally {
                try {
                    if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
                }
                finally { if (e_2) throw e_2.error; }
            }
        }
        return masked_headers;
    };
    ApiLogger.prototype._maskIfSenstiveHeader = function (name, value, headersToWhiteList) {
        var nonSensitiveHeaders = [
            'accept',
            'accept-charset',
            'accept-encoding',
            'accept-language',
            'access-control-allow-origin',
            'cache-control',
            'connection',
            'content-encoding',
            'content-language',
            'content-length',
            'content-location',
            'content-md5',
            'content-range',
            'content-type',
            'date',
            'etag',
            'expect',
            'expires',
            'from',
            'host',
            'if-match',
            'if-modified-since',
            'if-none-match',
            'if-range',
            'if-unmodified-since',
            'keep-alive',
            'last-modified',
            'location',
            'max-forwards',
            'pragma',
            'range',
            'referer',
            'retry-after',
            'server',
            'trailer',
            'transfer-encoding',
            'upgrade',
            'user-agent',
            'vary',
            'via',
            'warning',
            'x-forwarded-for',
            'x-requested-with',
            'x-powered-by',
        ];
        var lowerCaseHeadersToWhiteList = headersToWhiteList.map(function (header) {
            return header.toLowerCase();
        });
        return nonSensitiveHeaders.includes(name.toLowerCase()) ||
            lowerCaseHeadersToWhiteList.includes(name.toLowerCase())
            ? value
            : '**Redacted**';
    };
    return ApiLogger;
}());
exports.ApiLogger = ApiLogger;
