"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 SerialAPIParser_exports = {};
__export(SerialAPIParser_exports, {
  SerialAPIParser: () => SerialAPIParser
});
module.exports = __toCommonJS(SerialAPIParser_exports);
var import_shared = require("@zwave-js/shared");
var import_MessageHeaders = require("../message/MessageHeaders.js");
var import_ZWaveSerialFrame = require("./ZWaveSerialFrame.js");
function containsCompleteMessage(data) {
  return !!data && data.length >= 5 && data.length >= getMessageLength(data);
}
__name(containsCompleteMessage, "containsCompleteMessage");
function getMessageLength(data) {
  const remainingLength = data[1];
  return remainingLength + 2;
}
__name(getMessageLength, "getMessageLength");
function wrapSerialAPIChunk(chunk) {
  return {
    type: import_ZWaveSerialFrame.ZWaveSerialFrameType.SerialAPI,
    data: chunk
  };
}
__name(wrapSerialAPIChunk, "wrapSerialAPIChunk");
class SerialAPIParserTransformer {
  static {
    __name(this, "SerialAPIParserTransformer");
  }
  logger;
  constructor(logger) {
    this.logger = logger;
  }
  receiveBuffer = new import_shared.Bytes();
  // Allow ignoring the high nibble of an ACK once to work around an issue in the 700 series firmware
  ignoreAckHighNibble = false;
  transform(chunk, controller) {
    this.receiveBuffer = import_shared.Bytes.concat([this.receiveBuffer, chunk]);
    while (this.receiveBuffer.length > 0) {
      if (this.receiveBuffer[0] !== import_MessageHeaders.MessageHeaders.SOF) {
        let skip = 1;
        switch (this.receiveBuffer[0]) {
          // Emit the single-byte messages directly
          case import_MessageHeaders.MessageHeaders.ACK: {
            this.logger?.ACK("inbound");
            controller.enqueue(wrapSerialAPIChunk(import_MessageHeaders.MessageHeaders.ACK));
            this.ignoreAckHighNibble = false;
            break;
          }
          case import_MessageHeaders.MessageHeaders.NAK: {
            this.logger?.NAK("inbound");
            controller.enqueue(wrapSerialAPIChunk(import_MessageHeaders.MessageHeaders.NAK));
            break;
          }
          case import_MessageHeaders.MessageHeaders.CAN: {
            this.logger?.CAN("inbound");
            controller.enqueue(wrapSerialAPIChunk(import_MessageHeaders.MessageHeaders.CAN));
            break;
          }
          default: {
            if (this.ignoreAckHighNibble && (this.receiveBuffer[0] & 15) === import_MessageHeaders.MessageHeaders.ACK) {
              this.logger?.message(`received corrupted ACK: ${(0, import_shared.num2hex)(this.receiveBuffer[0])}`);
              this.logger?.ACK("inbound");
              controller.enqueue(wrapSerialAPIChunk(import_MessageHeaders.MessageHeaders.ACK));
              this.ignoreAckHighNibble = false;
              break;
            }
            while (skip < this.receiveBuffer.length) {
              const byte = this.receiveBuffer[skip];
              if (byte === import_MessageHeaders.MessageHeaders.SOF || byte === import_MessageHeaders.MessageHeaders.ACK || byte === import_MessageHeaders.MessageHeaders.NAK || byte === import_MessageHeaders.MessageHeaders.CAN) {
                break;
              }
              skip++;
            }
            const discarded = this.receiveBuffer.subarray(0, skip);
            this.logger?.discarded(discarded);
            controller.enqueue({
              type: import_ZWaveSerialFrame.ZWaveSerialFrameType.Discarded,
              data: discarded
            });
          }
        }
        this.receiveBuffer = this.receiveBuffer.subarray(skip);
        continue;
      }
      if (!containsCompleteMessage(this.receiveBuffer)) {
        break;
      } else {
        const msgLength = getMessageLength(this.receiveBuffer);
        const msg = this.receiveBuffer.subarray(0, msgLength);
        this.receiveBuffer = this.receiveBuffer.subarray(msgLength);
        this.logger?.data("inbound", msg);
        controller.enqueue(wrapSerialAPIChunk(msg));
      }
    }
  }
}
class SerialAPIParser extends TransformStream {
  static {
    __name(this, "SerialAPIParser");
  }
  constructor(logger) {
    const transformer = new SerialAPIParserTransformer(logger);
    super(transformer);
    this.#transformer = transformer;
  }
  #transformer;
  get ignoreAckHighNibble() {
    return this.#transformer.ignoreAckHighNibble;
  }
  set ignoreAckHighNibble(value) {
    this.#transformer.ignoreAckHighNibble = value;
  }
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  SerialAPIParser
});
//# sourceMappingURL=SerialAPIParser.js.map
