var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
    if (kind === "m") throw new TypeError("Private method is not writable");
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
    return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
    return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _LogRecord_args, _LogRecord_datetime, _Logger_instances, _Logger_level, _Logger_loggerName, _Logger_log;
// Copyright 2018-2025 the Deno authors. MIT license.
// This module is browser compatible.
import { getLevelByName, getLevelName, LogLevels } from "./levels.js";
/**
 * Configuration options for a logger instance.
 *
 * @example Usage
 *
 * ```ts
 * import { ConsoleHandler, getLogger, setup, type LogConfig} from "@std/log";
 * import { assert } from "@std/assert";
 *
 * const handler = new ConsoleHandler("INFO");
 * const logConfig: LogConfig = {
 *     handlers: {
 *         default: handler,
 *     },
 *     loggers: {
 *         default: {
 *             level: "INFO",
 *             handlers: ["default"],
 *         },
 *     },
 * }
 * setup(logConfig);
 * const logger = getLogger();
 *
 * assert(logger.handlers.at(0) instanceof ConsoleHandler);
 * ```
 */
export class LoggerConfig {
    constructor() {
        /** The minimum log level for the logger.
         *
         * @example Usage
         *
         * ```ts
         * import { ConsoleHandler, getLogger, setup, type LogConfig} from "@std/log";
         * import { assert } from "@std/assert";
         *
         * const handler = new ConsoleHandler("INFO");
         * const logConfig: LogConfig = {
         *     handlers: {
         *         default: handler,
         *     },
         *     loggers: {
         *         default: {
         *             level: "INFO",
         *             handlers: ["default"],
         *         },
         *     },
         * }
         * setup(logConfig);
         * const logger = getLogger();
         *
         * assert(logger.handlers.at(0) instanceof ConsoleHandler);
         * ```
         */
        Object.defineProperty(this, "level", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        /** A list of handler names attached to this logger.
         *
         * @example Usage
         *
         * ```ts
         * import { ConsoleHandler, getLogger, setup, type LogConfig} from "@std/log";
         * import { assert } from "@std/assert";
         *
         * const handler = new ConsoleHandler("INFO");
         * const logConfig: LogConfig = {
         *     handlers: {
         *         default: handler,
         *     },
         *     loggers: {
         *         default: {
         *             level: "INFO",
         *             handlers: ["default"],
         *         },
         *     },
         * }
         * setup(logConfig);
         * const logger = getLogger();
         *
         * assert(logger.handlers.at(0) instanceof ConsoleHandler);
         * ``` */
        Object.defineProperty(this, "handlers", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
    }
}
/**
 * An object that encapsulates provided message and arguments as well some
 * metadata that can be later used when formatting a message.
 *
 * @example Usage
 * ```ts
 * import { LogRecord } from "@std/log/logger";
 * import { LogLevels } from "@std/log/levels";
 * import { assertEquals } from "@std/assert/equals";
 *
 * const record = new LogRecord({
 *   msg: "Hello, world!",
 *   args: ["foo", "bar"],
 *   level: LogLevels.INFO,
 *   loggerName: "example",
 * });
 *
 * assertEquals(record.msg, "Hello, world!");
 * assertEquals(record.args, ["foo", "bar"]);
 * assertEquals(record.level, LogLevels.INFO);
 * assertEquals(record.loggerName, "example");
 * ```
 */
export class LogRecord {
    /**
     * Constructs a new instance.
     *
     * @param options The options to create a new log record.
     *
     * @example Usage
     * ```ts
     * import { LogRecord } from "@std/log/logger";
     * import { LogLevels } from "@std/log/levels";
     *
     * const record = new LogRecord({
     *   msg: "Hello, world!",
     *   args: ["foo", "bar"],
     *   level: LogLevels.INFO,
     *   loggerName: "example",
     * });
     * ```
     */
    constructor(options) {
        /** The message to log.
         *
         * @example Usage
         * ```ts
         * import { LogRecord } from "@std/log/logger";
         * import { LogLevels } from "@std/log/levels";
         * import { assertEquals } from "@std/assert/equals";
         *
         * const record = new LogRecord({
         *   msg: "Hello, world!",
         *   args: ["foo", "bar"],
         *   level: LogLevels.INFO,
         *   loggerName: "example",
         * });
         *
         * assertEquals(record.msg, "Hello, world!");
         * ```
         */
        Object.defineProperty(this, "msg", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        _LogRecord_args.set(this, void 0);
        _LogRecord_datetime.set(this, void 0);
        /**
         * The numeric log level of the log record.
         *
         * @example Usage
         * ```ts
         * import { LogRecord } from "@std/log/logger";
         * import { LogLevels } from "@std/log/levels";
         * import { assertEquals } from "@std/assert/equals";
         *
         * const record = new LogRecord({
         *   msg: "Hello, world!",
         *   args: ["foo", "bar"],
         *   level: LogLevels.INFO,
         *   loggerName: "example",
         * });
         *
         * assertEquals(record.level, LogLevels.INFO);
         * ```
         */
        Object.defineProperty(this, "level", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        /**
         * The name of the log level of the log record.
         *
         * @example Usage
         * ```ts
         * import { LogRecord } from "@std/log/logger";
         * import { LogLevels } from "@std/log/levels";
         * import { assertEquals } from "@std/assert/equals";
         *
         * const record = new LogRecord({
         *   msg: "Hello, world!",
         *   args: ["foo", "bar"],
         *   level: LogLevels.INFO,
         *   loggerName: "example",
         * });
         *
         * assertEquals(record.levelName, "INFO");
         * ```
         */
        Object.defineProperty(this, "levelName", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        /**
         * The name of the logger that created the log record.
         *
         * @example Usage
         * ```ts
         * import { LogRecord } from "@std/log/logger";
         * import { LogLevels } from "@std/log/levels";
         * import { assertEquals } from "@std/assert/equals";
         *
         * const record = new LogRecord({
         *   msg: "Hello, world!",
         *   args: ["foo", "bar"],
         *   level: LogLevels.INFO,
         *   loggerName: "example",
         * });
         *
         * assertEquals(record.loggerName, "example");
         * ```
         */
        Object.defineProperty(this, "loggerName", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        this.msg = options.msg;
        __classPrivateFieldSet(this, _LogRecord_args, [...options.args], "f");
        this.level = options.level;
        this.loggerName = options.loggerName;
        __classPrivateFieldSet(this, _LogRecord_datetime, new Date(), "f");
        this.levelName = getLevelName(options.level);
    }
    /**
     * Getter for the arguments to log.
     *
     * @example Usage
     * ```ts
     * import { LogRecord } from "@std/log/logger";
     * import { LogLevels } from "@std/log/levels";
     * import { assertEquals } from "@std/assert/equals";
     *
     * const record = new LogRecord({
     *   msg: "Hello, world!",
     *   args: ["foo", "bar"],
     *   level: LogLevels.INFO,
     *   loggerName: "example",
     * });
     *
     * assertEquals(record.args, ["foo", "bar"]);
     * ```
     *
     * @returns A copy of the arguments to log.
     */
    get args() {
        return [...__classPrivateFieldGet(this, _LogRecord_args, "f")];
    }
    /**
     * Getter for the date and time the log record was created.
     *
     * @example Usage
     * ```ts
     * import { LogRecord } from "@std/log/logger";
     * import { LogLevels } from "@std/log/levels";
     * import { assertAlmostEquals } from "@std/assert/almost-equals";
     *
     * const record = new LogRecord({
     *   msg: "Hello, world!",
     *   args: ["foo", "bar"],
     *   level: LogLevels.INFO,
     *   loggerName: "example",
     * });
     *
     * assertAlmostEquals(record.datetime.getTime(), Date.now(), 1);
     * ```
     *
     * @returns The date and time the log record was created.
     */
    get datetime() {
        return new Date(__classPrivateFieldGet(this, _LogRecord_datetime, "f").getTime());
    }
}
_LogRecord_args = new WeakMap(), _LogRecord_datetime = new WeakMap();
function asString(data, isProperty = false) {
    if (typeof data === "string") {
        if (isProperty)
            return `"${data}"`;
        return data;
    }
    else if (data === null ||
        typeof data === "number" ||
        typeof data === "bigint" ||
        typeof data === "boolean" ||
        typeof data === "undefined" ||
        typeof data === "symbol") {
        return String(data);
    }
    else if (data instanceof Error) {
        return data.stack;
    }
    else if (typeof data === "object") {
        return `{${Object.entries(data)
            .map(([k, v]) => `"${k}":${asString(v, true)}`)
            .join(",")}}`;
    }
    return "undefined";
}
/**
 * A logger that can log messages at different levels.
 *
 * @example Usage
 * ```ts
 * import { Logger } from "@std/log/logger";
 * import { assertEquals } from "@std/assert/equals";
 *
 * const logger = new Logger("example", "INFO");
 * const result = logger.info("Hello, world!");
 *
 * assertEquals(result, "Hello, world!");
 * ```
 */
export class Logger {
    /**
     * Constructs a new instance.
     *
     * @param loggerName The name of the logger.
     * @param levelName The name of the log level.
     * @param options The options to create a new logger.
     */
    constructor(loggerName, levelName, options = {}) {
        _Logger_instances.add(this);
        _Logger_level.set(this, void 0);
        /**
         * The handlers to use for the logger.
         *
         * @example Usage
         * ```ts
         * import { Logger } from "@std/log/logger";
         * import { ConsoleHandler } from "@std/log/console-handler";
         * import { assertEquals } from "@std/assert/equals";
         *
         * const handler = new ConsoleHandler("INFO");
         * const logger = new Logger("example", "INFO", {
         *  handlers: [handler],
         * });
         *
         * assertEquals(logger.handlers, [handler]);
         * ```
         */
        Object.defineProperty(this, "handlers", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        _Logger_loggerName.set(this, void 0);
        __classPrivateFieldSet(this, _Logger_loggerName, loggerName, "f");
        __classPrivateFieldSet(this, _Logger_level, getLevelByName(levelName), "f");
        this.handlers = options.handlers ?? [];
    }
    /**
     * Getter for the log level.
     *
     * @returns The log level.
     *
     * @example Usage
     * ```ts
     * import { Logger } from "@std/log/logger";
     * import { LogLevels } from "@std/log/levels";
     * import { assertEquals } from "@std/assert/equals";
     *
     * const logger = new Logger("example", "INFO");
     * assertEquals(logger.level, LogLevels.INFO);
     * ```
     */
    get level() {
        return __classPrivateFieldGet(this, _Logger_level, "f");
    }
    /**
     * Setter for the log level.
     *
     * @param level The log level to set.
     *
     * @example Usage
     * ```ts
     * import { Logger } from "@std/log/logger";
     * import { LogLevels } from "@std/log/levels";
     * import { assertEquals } from "@std/assert/equals";
     *
     * const logger = new Logger("example", "INFO");
     * logger.level = LogLevels.DEBUG;
     *
     * assertEquals(logger.level, LogLevels.DEBUG);
     * ```
     */
    set level(level) {
        try {
            __classPrivateFieldSet(this, _Logger_level, getLevelByName(getLevelName(level)), "f");
        }
        catch (_) {
            throw new TypeError(`Invalid log level: ${level}`);
        }
    }
    /**
     * Getter for the name of the log level.
     *
     * @returns The name of the log level.
     *
     * @example Usage
     * ```ts
     * import { Logger } from "@std/log/logger";
     * import { assertEquals } from "@std/assert/equals";
     *
     * const logger = new Logger("example", "INFO");
     * assertEquals(logger.levelName, "INFO");
     * ```
     */
    get levelName() {
        return getLevelName(__classPrivateFieldGet(this, _Logger_level, "f"));
    }
    /**
     * Setter for the name of the log level.
     *
     * @param levelName The name of the log level to set.
     *
     * @example Usage
     * ```ts
     * import { Logger } from "@std/log/logger";
     * import { LogLevels } from "@std/log/levels";
     * import { assertEquals } from "@std/assert/equals";
     *
     * const logger = new Logger("example", "INFO");
     * logger.levelName = "DEBUG";
     *
     * assertEquals(logger.level, LogLevels.DEBUG);
     * ```
     */
    set levelName(levelName) {
        __classPrivateFieldSet(this, _Logger_level, getLevelByName(levelName), "f");
    }
    /**
     * Getter for the name of the logger.
     *
     * @returns The name of the logger.
     *
     * @example Usage
     * ```ts
     * import { Logger } from "@std/log/logger";
     * import { assertEquals } from "@std/assert/equals";
     *
     * const logger = new Logger("example", "INFO");
     *
     * assertEquals(logger.loggerName, "example");
     * ```
     */
    get loggerName() {
        return __classPrivateFieldGet(this, _Logger_loggerName, "f");
    }
    debug(msg, ...args) {
        return __classPrivateFieldGet(this, _Logger_instances, "m", _Logger_log).call(this, LogLevels.DEBUG, msg, ...args);
    }
    info(msg, ...args) {
        return __classPrivateFieldGet(this, _Logger_instances, "m", _Logger_log).call(this, LogLevels.INFO, msg, ...args);
    }
    warn(msg, ...args) {
        return __classPrivateFieldGet(this, _Logger_instances, "m", _Logger_log).call(this, LogLevels.WARN, msg, ...args);
    }
    error(msg, ...args) {
        return __classPrivateFieldGet(this, _Logger_instances, "m", _Logger_log).call(this, LogLevels.ERROR, msg, ...args);
    }
    critical(msg, ...args) {
        return __classPrivateFieldGet(this, _Logger_instances, "m", _Logger_log).call(this, LogLevels.CRITICAL, msg, ...args);
    }
}
_Logger_level = new WeakMap(), _Logger_loggerName = new WeakMap(), _Logger_instances = new WeakSet(), _Logger_log = function _Logger_log(level, msg, ...args) {
    if (this.level > level) {
        return msg instanceof Function ? undefined : msg;
    }
    let fnResult;
    let logMessage;
    if (msg instanceof Function) {
        fnResult = msg();
        logMessage = asString(fnResult);
    }
    else {
        logMessage = asString(msg);
    }
    const record = new LogRecord({
        msg: logMessage,
        args: args,
        level: level,
        loggerName: this.loggerName,
    });
    this.handlers.forEach((handler) => {
        handler.handle(record);
    });
    return msg instanceof Function ? fnResult : msg;
};
