"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var Driver_exports = {};
__export(Driver_exports, {
  DRIVER_LABEL: () => DRIVER_LABEL,
  DriverLogger: () => DriverLogger
});
module.exports = __toCommonJS(Driver_exports);
var import_cc = require("@zwave-js/cc");
var import_core = require("@zwave-js/core");
var import_serial = require("@zwave-js/serial");
var import_serialapi = require("@zwave-js/serial/serialapi");
var import_shared = require("@zwave-js/shared");
var import_Types = require("../node/_Types.js");
const DRIVER_LABEL = "DRIVER";
const DRIVER_LOGLEVEL = "verbose";
const SENDQUEUE_LOGLEVEL = "debug";
class DriverLogger extends import_core.ZWaveLoggerBase {
  static {
    __name(this, "DriverLogger");
  }
  driver;
  constructor(driver, loggers) {
    super(loggers, DRIVER_LABEL);
    this.driver = driver;
  }
  isDriverLogVisible() {
    return this.container.isLoglevelVisible(DRIVER_LOGLEVEL);
  }
  isSendQueueLogVisible() {
    return this.container.isLoglevelVisible(SENDQUEUE_LOGLEVEL);
  }
  /**
   * Logs a message
   * @param msg The message to output
   */
  print(message, level) {
    const actualLevel = level || DRIVER_LOGLEVEL;
    if (!this.container.isLoglevelVisible(actualLevel))
      return;
    this.logger.log({
      level: actualLevel,
      message,
      direction: (0, import_core.getDirectionPrefix)("none"),
      context: { source: "driver", direction: "none" }
    });
  }
  /**
   * Serializes a message that starts a transaction, i.e. a message that is sent and may expect a response
   */
  transaction(transaction) {
    if (!this.isDriverLogVisible())
      return;
    const { message } = transaction;
    const secondaryTags = [];
    secondaryTags.push(`P: ${import_core.MessagePriority[transaction.priority]}`);
    this.logMessage(message, {
      secondaryTags,
      // Since we are programming a controller, the first message of a transaction is always outbound
      // (not to confuse with the message type, which may be Request or Response)
      direction: "outbound"
    });
  }
  /** Logs information about a message that is received as a response to a transaction */
  transactionResponse(message, originalTransaction, role) {
    if (!this.isDriverLogVisible())
      return;
    this.logMessage(message, {
      nodeId: originalTransaction?.message?.getNodeId(),
      secondaryTags: [role],
      direction: "inbound"
    });
  }
  logMessage(message, {
    // Used to relate this log message to a node
    nodeId,
    secondaryTags,
    direction = "none"
  } = {}) {
    if (!this.isDriverLogVisible())
      return;
    if (nodeId == void 0)
      nodeId = message.getNodeId();
    if (nodeId != void 0 && !this.container.isNodeLoggingVisible(nodeId)) {
      return;
    }
    const isCCContainer = (0, import_serialapi.containsCC)(message);
    const logEntry = message.toLogEntry();
    let msg = [(0, import_core.tagify)(logEntry.tags)];
    if (logEntry.message) {
      msg.push(...(0, import_core.messageRecordToLines)(logEntry.message).map((line) => (isCCContainer ? "\u2502 " : "  ") + line));
    }
    try {
      if (isCCContainer) {
        msg = msg.filter((line) => !line.startsWith("\u2502 payload:"));
        const logCC = /* @__PURE__ */ __name((cc, indent = 0) => {
          const isEncapCC = (0, import_cc.isEncapsulatingCommandClass)(cc) || (0, import_cc.isMultiEncapsulatingCommandClass)(cc);
          const loggedCC = cc.toLogEntry(this.driver);
          msg.push(" ".repeat(indent * 2) + "\u2514\u2500" + (0, import_core.tagify)(loggedCC.tags));
          indent++;
          if (loggedCC.message) {
            msg.push(...(0, import_core.messageRecordToLines)(loggedCC.message).map((line) => `${" ".repeat(indent * 2)}${isEncapCC ? "\u2502 " : "  "}${line}`));
          }
          if ((0, import_cc.isEncapsulatingCommandClass)(cc)) {
            logCC(cc.encapsulated, indent);
          } else if ((0, import_cc.isMultiEncapsulatingCommandClass)(cc)) {
            for (const encap of cc.encapsulated) {
              logCC(encap, indent);
            }
          }
        }, "logCC");
        logCC(message.command);
      }
      this.logger.log({
        level: DRIVER_LOGLEVEL,
        secondaryTags: secondaryTags && secondaryTags.length > 0 ? (0, import_core.tagify)(secondaryTags) : void 0,
        message: msg,
        // Since we are programming a controller, responses are always inbound
        // (not to confuse with the message type, which may be Request or Response)
        direction: (0, import_core.getDirectionPrefix)(direction),
        context: { source: "driver", direction }
      });
    } catch {
    }
  }
  /** Logs what's currently in the driver's send queue */
  sendQueue(...queues) {
    if (!this.isSendQueueLogVisible())
      return;
    let message = "Send queue:";
    let length = 0;
    for (const queue of queues) {
      length += queue.length;
      if (queue.length > 0) {
        for (const trns of queue.transactions) {
          const node = trns.message.tryGetNode(this.driver);
          const prefix = trns.message.type === import_serial.MessageType.Request ? "[REQ]" : "[RES]";
          const postfix = node != void 0 ? ` [Node ${node.id}, ${(0, import_shared.getEnumMemberName)(import_Types.NodeStatus, node.status)}]` : "";
          const command = (0, import_serialapi.containsCC)(trns.message) ? `: ${trns.message.command.constructor.name}` : "";
          message += `
\xB7 ${prefix} ${import_serial.FunctionType[trns.message.functionType]}${command}${postfix} (P: ${(0, import_shared.getEnumMemberName)(import_core.MessagePriority, trns.priority)})`;
        }
      } else {
        message += " (empty)";
      }
    }
    this.logger.log({
      level: SENDQUEUE_LOGLEVEL,
      message,
      secondaryTags: `(${length} message${length === 1 ? "" : "s"})`,
      direction: (0, import_core.getDirectionPrefix)("none"),
      context: { source: "driver", direction: "none" }
    });
  }
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  DRIVER_LABEL,
  DriverLogger
});
//# sourceMappingURL=Driver.js.map
