"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createDebugMethod = void 0;
exports.debug = debug;
exports.getDebugConfig = getDebugConfig;
exports.setDebugConfig = setDebugConfig;
const debug_1 = __importDefault(require("debug"));
const generator_1 = require("../Hash/generator");
let config = {
    serialize: false,
    logDuration: false,
};
function getDurationLog(start) {
    if (config.logDuration) {
        const duration = new Date().getTime() - start.getTime();
        return ` (${duration}ms)`;
    }
}
const createDebugMethod = (localDebug) => (originalMethod, that, label, args) => {
    const invocationUid = (0, generator_1.generateUniqueHash)(10);
    const start = new Date();
    localDebug(`invoking ${label} <${invocationUid}>`, ...serializeArgsIfEnabled(args));
    try {
        const returnValue = originalMethod.apply(that, args);
        if (returnValue instanceof Promise) {
            return returnValue
                .then((result) => {
                localDebug(`success ${label} <${invocationUid}>${getDurationLog(start)}`, result);
                return result;
            })
                .catch((error) => {
                localDebug(`fail ${label} <${invocationUid}>${getDurationLog(start)}`, error);
                throw error;
            });
        }
        else {
            localDebug(`success ${label} <${invocationUid}>${getDurationLog(start)}`, returnValue);
            return returnValue;
        }
    }
    catch (error) {
        localDebug(`fail ${label} <${invocationUid}>${getDurationLog(start)}`, error);
        throw error;
    }
};
exports.createDebugMethod = createDebugMethod;
function serializeArgsIfEnabled(args) {
    return args.map((arg) => {
        if (typeof arg === 'object' && arg !== null && config.serialize) {
            return JSON.stringify(arg);
        }
        else {
            return arg;
        }
    });
}
/**
 * Add to a class method to debug it's calls
 *
 * For more information see https://www.npmjs.com/package/debug
 *
 * @param namespace Namespace of the debug logs. Run program with env variable DEBUG=<namespace> to enable the logs.
 */
function debug(namespace, debugFactory = debug_1.default) {
    const debugMethod = (0, exports.createDebugMethod)(debugFactory(namespace));
    return function (_target, propertyKey, descriptor) {
        const originalMethod = descriptor.value;
        descriptor.value = function (...args) {
            return debugMethod(originalMethod, this, `${this.constructor.name}:${propertyKey}`, args);
        };
    };
}
function getDebugConfig() {
    return config;
}
function setDebugConfig(newConfig) {
    config = {
        ...config,
        ...newConfig,
    };
}
//# sourceMappingURL=debugDecorator.js.map