"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.timedIntentFunctionCall = exports.timedIdentityClientFunctionCall = exports.timedMatrixClientFunctionCall = void 0;
const names_1 = require("./names");
/**
 * Times a MatrixClient function call for metrics.
 * @category Metrics
 */
function timedMatrixClientFunctionCall() {
    return function (target, propertyKey, descriptor) {
        const originalMethod = descriptor.value;
        descriptor.value = function (...args) {
            const metrics = this.metrics;
            const context = metrics.assignUniqueContextId({
                functionName: propertyKey,
                client: this,
            });
            metrics.start(names_1.METRIC_MATRIX_CLIENT_FUNCTION_CALL, context);
            let result;
            let exception;
            try {
                result = originalMethod.apply(this, args);
            }
            catch (e) {
                exception = e;
                result = Promise.reject(e);
            }
            let promise = result;
            if (!(result instanceof Promise) && result !== null && result !== undefined) {
                promise = Promise.resolve(result);
            }
            promise
                .then(() => metrics.increment(names_1.METRIC_MATRIX_CLIENT_SUCCESSFUL_FUNCTION_CALL, context, 1))
                .catch(() => metrics.increment(names_1.METRIC_MATRIX_CLIENT_FAILED_FUNCTION_CALL, context, 1))
                .finally(() => metrics.end(names_1.METRIC_MATRIX_CLIENT_FUNCTION_CALL, context));
            if (exception)
                throw exception;
            return result;
        };
    };
}
exports.timedMatrixClientFunctionCall = timedMatrixClientFunctionCall;
/**
 * Times an IdentityClient function call for metrics.
 * @category Metrics
 */
function timedIdentityClientFunctionCall() {
    return function (target, propertyKey, descriptor) {
        const originalMethod = descriptor.value;
        descriptor.value = function (...args) {
            const metrics = this.metrics;
            const context = metrics.assignUniqueContextId({
                functionName: propertyKey,
                client: this,
            });
            metrics.start(names_1.METRIC_IDENTITY_CLIENT_FUNCTION_CALL, context);
            let result;
            let exception;
            try {
                result = originalMethod.apply(this, args);
            }
            catch (e) {
                exception = e;
                result = Promise.reject(e);
            }
            let promise = result;
            if (!(result instanceof Promise) && result !== null && result !== undefined) {
                promise = Promise.resolve(result);
            }
            promise
                .then(() => metrics.increment(names_1.METRIC_IDENTITY_CLIENT_SUCCESSFUL_FUNCTION_CALL, context, 1))
                .catch(() => metrics.increment(names_1.METRIC_IDENTITY_CLIENT_FAILED_FUNCTION_CALL, context, 1))
                .finally(() => metrics.end(names_1.METRIC_IDENTITY_CLIENT_FUNCTION_CALL, context));
            if (exception)
                throw exception;
            return result;
        };
    };
}
exports.timedIdentityClientFunctionCall = timedIdentityClientFunctionCall;
/**
 * Times an Intent function call for metrics.
 * @category Metrics
 */
function timedIntentFunctionCall() {
    return function (target, propertyKey, descriptor) {
        const originalMethod = descriptor.value;
        descriptor.value = function (...args) {
            const metrics = this.metrics;
            const context = metrics.assignUniqueContextId({
                functionName: propertyKey,
                client: this.client,
                intent: this,
            });
            metrics.start(names_1.METRIC_INTENT_FUNCTION_CALL, context);
            let result;
            let exception;
            try {
                result = originalMethod.apply(this, args);
            }
            catch (e) {
                exception = e;
                result = Promise.reject(e);
            }
            let promise = result;
            if (!(result instanceof Promise) && result !== null && result !== undefined) {
                promise = Promise.resolve(result);
            }
            promise
                .then(() => metrics.increment(names_1.METRIC_INTENT_SUCCESSFUL_FUNCTION_CALL, context, 1))
                .catch(() => metrics.increment(names_1.METRIC_INTENT_FAILED_FUNCTION_CALL, context, 1))
                .finally(() => metrics.end(names_1.METRIC_INTENT_FUNCTION_CALL, context));
            if (exception)
                throw exception;
            return result;
        };
    };
}
exports.timedIntentFunctionCall = timedIntentFunctionCall;
