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 _DefaultSystemLogger_instances, _DefaultSystemLogger_logger, _DefaultSystemLogger_tags, _DefaultSystemLogger_log;
import { LoggerDefinition, Severity, } from '@devvit/protos/types/devvit/plugin/logger/logger.js';
import { Hostname, resolvePluginDefinitionHostname } from '@devvit/shared-types/HostnameUtil.js';
import { StringUtil } from '@devvit/shared-types/StringUtil.js';
import { EnvelopeClientBuilder } from '../../common/envelope/EnvelopeClientBuilder.js';
import { ConsoleLogger } from '../../plugins/logger/ConsoleLogger.js';
/**
 * Log categories.
 *
 * This enum is to encourage consistent tagging but any string may be used. Keep
 * this enum up-to-date with what's needed.
 */
export const SystemLogTag = Object.freeze({
    /** A script lifecycle event such as loaded or unloaded. */
    ScriptLifecycle: 'ScriptLifecycle',
    /**
     * A script threw an unhandled error when processing a request or response.
     */
    ScriptMessageError: 'ScriptMessageError',
    /**
     * A log recorded by Compute. This may occur in any environment (web, Node.js,
     * worker, Go, etc). All SystemLog-recorded logs are expected to have this
     * tag.
     */
    System: 'System',
});
/** A do-nothing SystemLogger. */
export class VoidSystemLogger {
    constructor() {
        this.bind = () => { };
        this.debug = async () => { };
        this.error = async () => { };
        this.event = async () => { };
        this.info = async () => { };
        this.messageError = async () => { };
        this.unbind = async () => { };
        this.verbose = async () => { };
        this.warn = async () => { };
    }
}
/** A SystemLogger facade over the conventional logger plugin service API. */
export class DefaultSystemLogger {
    constructor(...tags) {
        _DefaultSystemLogger_instances.add(this);
        /**
         * The underlying Logger client initialized to console output. ConsoleLogger
         * itself is a plugin usually provided to a runtime. However, we're using it
         * like a plain JavaScript object because that's all it is without an
         * EnvelopeServer wrapping it.
         *
         * It's preferable to never actually use the ConsoleLogger implementation
         * since those likely won't be recorded.
         */
        _DefaultSystemLogger_logger.set(this, new ConsoleLogger());
        _DefaultSystemLogger_tags.set(this, void 0);
        __classPrivateFieldSet(this, _DefaultSystemLogger_tags, [SystemLogTag.System, ...tags], "f");
    }
    bind(dispatcher, namespace = getSystemLoggerWorkerNamespace()) {
        // In worker contexts, a runtime is unavailable but a dispatcher is.
        // Regardless of wether this is a worker or a runtime, assume a logger
        // plugin exists, create a client, and bind it to the dispatcher. This
        // creates an implicit dependency (uses) on logger.
        const hostname = resolvePluginDefinitionHostname(LoggerDefinition, namespace);
        const client = EnvelopeClientBuilder.build(hostname, [LoggerDefinition]);
        dispatcher.bind(client);
        __classPrivateFieldSet(this, _DefaultSystemLogger_logger, client, "f");
    }
    async error(errOrMessage, metadata, tags) {
        const errMessage = {
            name: errOrMessage instanceof Error ? errOrMessage.name : 'Error',
            message: StringUtil.caughtToString(errOrMessage),
            tags: filterDuplicates([...__classPrivateFieldGet(this, _DefaultSystemLogger_tags, "f"), ...(tags ?? [])]),
            // Default to now.
            timestamp: new Date(),
        };
        await __classPrivateFieldGet(this, _DefaultSystemLogger_logger, "f").Error(errMessage, metadata);
    }
    async event(type, labels, data, metadata) {
        await __classPrivateFieldGet(this, _DefaultSystemLogger_logger, "f").Event({ type, labels: labels ?? {}, data: data ?? {}, timestamp: new Date() }, metadata);
    }
    info(message, metadata, tags) {
        return __classPrivateFieldGet(this, _DefaultSystemLogger_instances, "m", _DefaultSystemLogger_log).call(this, message, Severity.INFO, metadata, tags);
    }
    messageError(envelope, error) {
        return this.error(error, envelope.metadata, [SystemLogTag.ScriptMessageError]);
    }
    async unbind(dispatcher) {
        if (!(__classPrivateFieldGet(this, _DefaultSystemLogger_logger, "f") instanceof ConsoleLogger)) {
            // Assume bound to a legitimate EnvelopeClient instance, a private class
            // of EnvelopeClientBuilder.
            await dispatcher.release(__classPrivateFieldGet(this, _DefaultSystemLogger_logger, "f"));
        }
        __classPrivateFieldSet(this, _DefaultSystemLogger_logger, new ConsoleLogger(), "f");
    }
    verbose(message, metadata, tags) {
        return __classPrivateFieldGet(this, _DefaultSystemLogger_instances, "m", _DefaultSystemLogger_log).call(this, message, Severity.VERBOSE, metadata, tags);
    }
    warn(message, metadata, tags) {
        return __classPrivateFieldGet(this, _DefaultSystemLogger_instances, "m", _DefaultSystemLogger_log).call(this, message, Severity.WARN, metadata, tags);
    }
}
_DefaultSystemLogger_logger = new WeakMap(), _DefaultSystemLogger_tags = new WeakMap(), _DefaultSystemLogger_instances = new WeakSet(), _DefaultSystemLogger_log = async function _DefaultSystemLogger_log(message, severity, metadata, tags) {
    const logMessage = {
        message,
        severity,
        tags: filterDuplicates([...__classPrivateFieldGet(this, _DefaultSystemLogger_tags, "f"), ...(tags ?? [])]),
        timestamp: new Date(),
    };
    await __classPrivateFieldGet(this, _DefaultSystemLogger_logger, "f").Log(logMessage, metadata);
};
/** Returns a new array of unique items. */
function filterDuplicates(array) {
    return [...new Set(array)];
}
/**
 * Get the appropriate namespace for a worker's logger. For server runtimes,
 * this is the runtime namespace. For web and Node.js runtimes, this is the web
 * runtime namespace.
 */
function getSystemLoggerWorkerNamespace() {
    return { hostname: Hostname.getRoot(self.name) };
}
