"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var node_exports = {};
__export(node_exports, {
  createDefaultTransportFormat: () => createDefaultTransportFormat,
  createLoggerFormat: () => createLoggerFormat,
  log: () => log,
  restoreSilence: () => restoreSilence,
  unsilence: () => unsilence
});
module.exports = __toCommonJS(node_exports);
var import_shared = require("@zwave-js/shared");
var import_pathe = __toESM(require("pathe"), 1);
var import_triple_beam = require("triple-beam");
var import_winston = __toESM(require("winston"), 1);
var import_winston_daily_rotate_file = __toESM(require("winston-daily-rotate-file"), 1);
var import_Colorizer = require("../../log/Colorizer.js");
var import_format = require("../../log/format.js");
var import_shared2 = require("../../log/shared.js");
const isTTY = process.stdout.isTTY;
const isUnitTest = process.env.NODE_ENV === "test";
const loglevels = import_triple_beam.configs.npm.levels;
function getTransportLoglevel() {
  const loglevel = (0, import_shared.getenv)("LOGLEVEL");
  return loglevel in loglevels ? loglevel : "debug";
}
__name(getTransportLoglevel, "getTransportLoglevel");
function loglevelFromNumber(numLevel) {
  if (numLevel == void 0)
    return;
  for (const [level, value] of Object.entries(loglevels)) {
    if (value === numLevel)
      return level;
  }
}
__name(loglevelFromNumber, "loglevelFromNumber");
function createLoggerFormat(channel) {
  return (0, import_format.combine)(
    // add the channel as a label
    (0, import_format.label)(channel),
    // default to short timestamps
    (0, import_format.timestamp)(import_shared2.timestampFormat)
  );
}
__name(createLoggerFormat, "createLoggerFormat");
function createDefaultTransportFormat(colorize, shortTimestamps) {
  const formats = [
    // overwrite the default timestamp format if necessary
    shortTimestamps ? (0, import_format.timestamp)(import_shared2.timestampFormatShort) : void 0,
    import_format.formatLogMessage,
    colorize ? (0, import_Colorizer.colorizer)() : void 0,
    (0, import_format.printLogMessage)(shortTimestamps)
  ].filter((f) => f != void 0);
  return (0, import_format.combine)(...formats);
}
__name(createDefaultTransportFormat, "createDefaultTransportFormat");
function unsilence(logger) {
  const consoleTransport = logger.transports.find((t) => t.name === "console");
  if (consoleTransport) {
    const ret = !!consoleTransport.silent;
    consoleTransport.silent = false;
    return ret;
  }
  return false;
}
__name(unsilence, "unsilence");
function restoreSilence(logger, original) {
  const consoleTransport = logger.transports.find((t) => t.name === "console");
  if (consoleTransport) {
    consoleTransport.silent = original;
  }
}
__name(restoreSilence, "restoreSilence");
class ZWaveLogContainer extends import_winston.default.Container {
  static {
    __name(this, "ZWaveLogContainer");
  }
  fileTransport;
  consoleTransport;
  loglevelVisibleCache = /* @__PURE__ */ new Map();
  logConfig = {
    enabled: true,
    level: getTransportLoglevel(),
    logToFile: !!(0, import_shared.getenv)("LOGTOFILE"),
    maxFiles: 7,
    nodeFilter: (0, import_shared2.stringToNodeList)((0, import_shared.getenv)("LOG_NODES")),
    transports: void 0,
    filename: import_pathe.default.join(process.cwd(), `zwavejs_%DATE%.log`),
    forceConsole: false
  };
  constructor(config = {}) {
    super();
    this.updateConfiguration(config);
  }
  getLogger(label2) {
    if (!this.has(label2)) {
      this.add(label2, {
        transports: this.getAllTransports(),
        format: createLoggerFormat(label2),
        // Accept all logs, no matter what. The individual loggers take care
        // of filtering the wrong loglevels
        level: "silly"
      });
    }
    return this.get(label2);
  }
  updateConfiguration(config) {
    for (const key of import_shared2.nonUndefinedLogConfigKeys) {
      if (key in config && config[key] === void 0) {
        delete config[key];
      }
    }
    const changedLoggingTarget = config.logToFile != void 0 && config.logToFile !== this.logConfig.logToFile || config.forceConsole != void 0 && config.forceConsole !== this.logConfig.forceConsole;
    if (typeof config.level === "number") {
      config.level = loglevelFromNumber(config.level);
    }
    const changedLogLevel = config.level != void 0 && config.level !== this.logConfig.level;
    if (config.filename != void 0 && !config.filename.includes("%DATE%")) {
      config.filename += "_%DATE%.log";
    }
    const changedFilename = config.filename != void 0 && config.filename !== this.logConfig.filename;
    if (config.maxFiles != void 0) {
      if (typeof config.maxFiles !== "number" || config.maxFiles < 1 || config.maxFiles > 365) {
        delete config.maxFiles;
      }
    }
    const changedMaxFiles = config.maxFiles != void 0 && config.maxFiles !== this.logConfig.maxFiles;
    this.logConfig = Object.assign(this.logConfig, config);
    if (changedLogLevel) {
      this.loglevelVisibleCache.clear();
    }
    const recreateInternalTransports = this.fileTransport == void 0 && this.consoleTransport == void 0 || changedLoggingTarget || changedFilename || changedMaxFiles;
    if (recreateInternalTransports) {
      this.fileTransport?.destroy();
      this.fileTransport = void 0;
      this.consoleTransport?.destroy();
      this.consoleTransport = void 0;
    }
    if (recreateInternalTransports || config.transports != void 0) {
      this.loggers.forEach((logger) => logger.configure({ transports: this.getAllTransports() }));
    }
  }
  getConfiguration() {
    return this.logConfig;
  }
  /** Tests whether a log using the given loglevel will be logged */
  isLoglevelVisible(loglevel) {
    if (!this.fileTransport && !this.consoleTransport && (!this.logConfig.transports || this.logConfig.transports.length === 0)) {
      return false;
    }
    if (!this.loglevelVisibleCache.has(loglevel)) {
      this.loglevelVisibleCache.set(loglevel, loglevel in loglevels && loglevels[loglevel] <= loglevels[this.logConfig.level]);
    }
    return this.loglevelVisibleCache.get(loglevel);
  }
  destroy() {
    for (const key in this.loggers) {
      this.close(key);
    }
    this.fileTransport = void 0;
    this.consoleTransport = void 0;
    this.logConfig.transports = [];
  }
  getAllTransports() {
    return [
      ...this.getInternalTransports(),
      ...this.logConfig.transports ?? []
    ];
  }
  getInternalTransports() {
    const ret = [];
    if (!this.logConfig.enabled) {
      return ret;
    }
    if (this.logConfig.logToFile) {
      if (!this.fileTransport) {
        this.fileTransport = this.createFileTransport();
      }
      ret.push(this.fileTransport);
    }
    if (
      // when in production
      !isUnitTest && (isTTY && !this.logConfig.logToFile || this.logConfig.forceConsole)
    ) {
      if (!this.consoleTransport) {
        this.consoleTransport = this.createConsoleTransport();
      }
      ret.push(this.consoleTransport);
    }
    return ret;
  }
  createConsoleTransport() {
    return new import_winston.default.transports.Console({
      format: createDefaultTransportFormat(
        // Only colorize the output if logging to a TTY, otherwise we'll get
        // ansi color codes in logfiles or redirected shells
        isTTY || isUnitTest,
        // Only use short timestamps if logging to a TTY
        isTTY
      ),
      silent: this.isConsoleTransportSilent()
    });
  }
  isConsoleTransportSilent() {
    return process.env.NODE_ENV === "test" || !this.logConfig.enabled;
  }
  isFileTransportSilent() {
    return !this.logConfig.enabled;
  }
  createFileTransport() {
    const ret = new import_winston_daily_rotate_file.default({
      filename: this.logConfig.filename,
      auditFile: `${this.logConfig.filename.replace("_%DATE%", "_logrotate").replace(/\.log$/, "")}.json`,
      datePattern: "YYYY-MM-DD",
      createSymlink: true,
      symlinkName: import_pathe.default.basename(this.logConfig.filename).replace(`_%DATE%`, "_current"),
      zippedArchive: true,
      maxFiles: `${this.logConfig.maxFiles}d`,
      format: createDefaultTransportFormat(false, false),
      silent: this.isFileTransportSilent()
    });
    ret.on("new", (newFilename) => {
      console.log(`Logging to file:
	${newFilename}`);
    });
    ret.on("error", (err) => {
      console.error(`Error in file stream rotator: ${err.message}`);
    });
    return ret;
  }
  /**
   * Checks the log configuration whether logs should be written for a given node id
   */
  isNodeLoggingVisible(nodeId) {
    if (!this.logConfig.nodeFilter)
      return true;
    return this.logConfig.nodeFilter.includes(nodeId);
  }
}
const log = /* @__PURE__ */ __name((config) => new ZWaveLogContainer(config), "log");
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  createDefaultTransportFormat,
  createLoggerFormat,
  log,
  restoreSilence,
  unsilence
});
//# sourceMappingURL=node.js.map
