"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
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 PairingCodeSchema_exports = {};
__export(PairingCodeSchema_exports, {
  CommissioningFlowType: () => CommissioningFlowType,
  DiscoveryCapabilitiesBitmap: () => DiscoveryCapabilitiesBitmap,
  DiscoveryCapabilitiesSchema: () => DiscoveryCapabilitiesSchema,
  MATTER_QR_CODE_ALL_PAYLOAD_MAX_LENGTH: () => MATTER_QR_CODE_ALL_PAYLOAD_MAX_LENGTH,
  MATTER_QR_CODE_SINGLE_PAYLOAD_MAX_LENGTH: () => MATTER_QR_CODE_SINGLE_PAYLOAD_MAX_LENGTH,
  ManualPairingCodeCodec: () => ManualPairingCodeCodec,
  QrCodeTlvDataDefaultFields: () => QrCodeTlvDataDefaultFields,
  QrPairingCodeCodec: () => QrPairingCodeCodec
});
module.exports = __toCommonJS(PairingCodeSchema_exports);
var import_general = require("#general");
var import_VendorId = require("../datatype/VendorId.js");
var import_TlvAny = require("../tlv/TlvAny.js");
var import_TlvCodec = require("../tlv/TlvCodec.js");
var import_TlvNumber = require("../tlv/TlvNumber.js");
var import_TlvObject = require("../tlv/TlvObject.js");
var import_TlvString = require("../tlv/TlvString.js");
var import_Base38Schema = require("./Base38Schema.js");
var import_BitmapSchema = require("./BitmapSchema.js");
var import_Schema = require("./Schema.js");
/**
 * @license
 * Copyright 2022-2025 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
const MATTER_QR_CODE_SINGLE_PAYLOAD_MAX_LENGTH = 255;
const MATTER_QR_CODE_ALL_PAYLOAD_MAX_LENGTH = 4296;
var CommissioningFlowType = /* @__PURE__ */ ((CommissioningFlowType2) => {
  CommissioningFlowType2[CommissioningFlowType2["Standard"] = 0] = "Standard";
  CommissioningFlowType2[CommissioningFlowType2["UserIntent"] = 1] = "UserIntent";
  CommissioningFlowType2[CommissioningFlowType2["Custom"] = 2] = "Custom";
  return CommissioningFlowType2;
})(CommissioningFlowType || {});
const DiscoveryCapabilitiesBitmap = {
  /**
   * BLE
   * * Set when device supports BLE for discovery when not commissioned.
   * * Not-Set when device does not support BLE for discovery or is currently commissioned into one or more fabrics.
   */
  ble: (0, import_BitmapSchema.BitFlag)(1),
  /**
   * On the IP network
   * * Set when device is already on the IP network.
   */
  onIpNetwork: (0, import_BitmapSchema.BitFlag)(2),
  /**
   * Wi-Fi Public Action Frame
   * * Set when device supports Wi-Fi Public Action Frame for discovery when not commissioned.
   * * Not-Set when device does not support Wi-Fi Public Action Frame for discovery or is currently commissioned into
   *   one or more fabrics.
   */
  wifiPublicActionFrame: (0, import_BitmapSchema.BitFlag)(3)
};
const DiscoveryCapabilitiesSchema = (0, import_BitmapSchema.BitmapSchema)(DiscoveryCapabilitiesBitmap);
const QrCodeDataSchema = (0, import_BitmapSchema.ByteArrayBitmapSchema)({
  version: (0, import_BitmapSchema.BitField)(0, 3),
  vendorId: (0, import_BitmapSchema.BitField)(3, 16),
  productId: (0, import_BitmapSchema.BitField)(19, 16),
  flowType: (0, import_BitmapSchema.BitFieldEnum)(35, 2),
  discoveryCapabilities: (0, import_BitmapSchema.BitField)(37, 8),
  discriminator: (0, import_BitmapSchema.BitField)(45, 12),
  passcode: (0, import_BitmapSchema.BitField)(57, 27)
});
const QrCodeTlvDataDefaultFields = {
  /** Device Serial # */
  serialNumber: (0, import_TlvObject.TlvOptionalField)(0, import_TlvAny.TlvAny),
  // can be TlvString with up to 32 bytes or Unsigned Int up to 8 bytes
  pbkdfIterations: (0, import_TlvObject.TlvOptionalField)(1, import_TlvNumber.TlvUInt32.bound({ min: 1e3, max: 1e5 })),
  // Or could also be UInt 16?
  pbkdfSalt: (0, import_TlvObject.TlvOptionalField)(2, import_TlvString.TlvByteString.bound({ minLength: 16, maxLength: 32 })),
  /**
   * Number of devices that are expected to be onboarded using this payload when using the Enhanced Commissioning
   * Method
   */
  numberOfDevices: (0, import_TlvObject.TlvOptionalField)(3, import_TlvNumber.TlvUInt8.bound({ min: 1 })),
  /**
   * Time, in seconds, during which the device(s) are expected to be commissionable using the Enhanced Commissioning
   * Method
   */
  commissioningTimeout: (0, import_TlvObject.TlvOptionalField)(4, import_TlvNumber.TlvUInt16)
};
const PREFIX = "MT:";
class QrPairingCodeSchema extends import_Schema.Schema {
  encodeInternal(payloadData) {
    if (payloadData.length === 0) throw new import_general.ImplementationError("Provided Payload data is empty");
    const result = PREFIX + payloadData.map((payloadData2) => {
      const { tlvData } = payloadData2;
      const data = tlvData !== void 0 && tlvData.byteLength > 0 ? import_general.Bytes.of(import_general.Bytes.concat(QrCodeDataSchema.encode(payloadData2), tlvData)) : QrCodeDataSchema.encode(payloadData2);
      const result2 = import_Base38Schema.Base38.encode(data);
      if (result2.length > MATTER_QR_CODE_SINGLE_PAYLOAD_MAX_LENGTH) {
        throw new import_general.UnexpectedDataError(
          `Encoded pairing code is too long: ${result2.length} characters (max ${MATTER_QR_CODE_SINGLE_PAYLOAD_MAX_LENGTH})`
        );
      }
      return result2;
    }).join("*");
    if (result.length > MATTER_QR_CODE_ALL_PAYLOAD_MAX_LENGTH) {
      throw new import_general.UnexpectedDataError(
        `Encoded pairing code is too long: ${result.length} characters (max ${MATTER_QR_CODE_ALL_PAYLOAD_MAX_LENGTH})`
      );
    }
    return result;
  }
  decodeInternal(encoded) {
    if (!encoded.startsWith(PREFIX)) throw new import_general.UnexpectedDataError("The pairing code should start with MT:");
    return encoded.slice(PREFIX.length).split("*").map((encodedData) => {
      const data = import_general.Bytes.of(import_Base38Schema.Base38.decode(encodedData));
      return {
        ...QrCodeDataSchema.decode(data.slice(0, 11)),
        tlvData: data.length > 11 ? data.slice(11) : void 0
        // TlvData (if any) is after the fixed-length data
      };
    });
  }
  /**
   * Decodes the TLV data from the QR code payload.
   * This method especially also handles that an encoded serialNumber can be UTF-8-String or a Unsigned Integer.
   *
   * @param data Encoded TLV data
   * @param schema The schema to use for decoding the TLV data, by default a schema with the QrCodeTlvDataDefaultFields is used
   */
  decodeTlvData(data, schema = (0, import_TlvObject.TlvObject)(QrCodeTlvDataDefaultFields)) {
    const decoded = schema.decode(data);
    if (decoded.serialNumber !== void 0) {
      if (!Array.isArray(decoded.serialNumber) || decoded.serialNumber.length !== 1 || decoded.serialNumber[0].typeLength === void 0 || decoded.serialNumber[0].value === void 0) {
        throw new import_general.UnexpectedDataError("Invalid serial number TLV data");
      }
      switch (decoded.serialNumber[0].typeLength.type) {
        case import_TlvCodec.TlvType.Utf8String:
        case import_TlvCodec.TlvType.UnsignedInt:
          decoded.serialNumber = decoded.serialNumber[0].value;
          break;
        default:
          throw new import_general.UnexpectedDataError("Invalid serial number TLV data");
      }
    }
    return decoded;
  }
  /**
   * Encodes the TLV data for the QR code payload.
   * This method especially also handles that an encoded serialNumber can be UTF-8-String or a Unsigned Integer.
   *
   * @param data Data object to encode
   * @param schema The schema to use for encoding the TLV data, by default a schema with the QrCodeTlvDataDefaultFields is used
   */
  encodeTlvData(data, schema = (0, import_TlvObject.TlvObject)(QrCodeTlvDataDefaultFields)) {
    const dataToEncode = (0, import_general.deepCopy)(data);
    if ("serialNumber" in dataToEncode && dataToEncode.serialNumber !== void 0) {
      switch (typeof dataToEncode.serialNumber) {
        case "string":
          dataToEncode.serialNumber = import_TlvString.TlvString.encodeTlv(dataToEncode.serialNumber);
          break;
        case "number":
          dataToEncode.serialNumber = import_TlvNumber.TlvUInt8.encodeTlv(dataToEncode.serialNumber);
          break;
        default:
          throw new import_general.ImplementationError("Invalid serial number data");
      }
    }
    return schema.encode(dataToEncode);
  }
}
const QrPairingCodeCodec = new QrPairingCodeSchema();
class ManualPairingCodeSchema extends import_Schema.Schema {
  encodeInternal({ discriminator, passcode, vendorId, productId }) {
    if (discriminator === void 0) throw new import_general.UnexpectedDataError("discriminator is required");
    if (discriminator > 4095) throw new import_general.UnexpectedDataError("discriminator value must be less than 4096");
    let result = "";
    const hasVendorProductIds = vendorId !== void 0 && productId !== void 0;
    result += discriminator >> 10 | (hasVendorProductIds ? 1 << 2 : 0);
    result += ((discriminator & 768) << 6 | passcode & 16383).toString().padStart(5, "0");
    result += (passcode >> 14).toString().padStart(4, "0");
    if (hasVendorProductIds) {
      result += vendorId.toString().padStart(5, "0");
      result += productId.toString().padStart(5, "0");
    }
    result += new import_general.Verhoeff().computeChecksum(result);
    return result;
  }
  decodeInternal(encoded) {
    encoded = encoded.replace(/\D/g, "");
    if (encoded.length !== 11 && encoded.length !== 21) {
      throw new import_general.UnexpectedDataError("Invalid pairing code");
    }
    if (new import_general.Verhoeff().computeChecksum(encoded.slice(0, -1)) !== parseInt(encoded.slice(-1))) {
      throw new import_general.UnexpectedDataError("Invalid checksum");
    }
    const hasVendorProductIds = !!(parseInt(encoded[0]) & 1 << 2);
    const shortDiscriminator = (parseInt(encoded[0]) & 3) << 2 | parseInt(encoded.slice(1, 6)) >> 14 & 3;
    const passcode = parseInt(encoded.slice(1, 6)) & 16383 | parseInt(encoded.slice(6, 10)) << 14;
    let vendorId;
    let productId;
    if (hasVendorProductIds) {
      vendorId = (0, import_VendorId.VendorId)(parseInt(encoded.slice(10, 15)));
      productId = parseInt(encoded.slice(15, 20));
    }
    return { shortDiscriminator, passcode, vendorId, productId };
  }
}
const ManualPairingCodeCodec = new ManualPairingCodeSchema();
//# sourceMappingURL=PairingCodeSchema.js.map
