/**
 * @license
 * Copyright 2025-2026 Open Home Foundation
 * SPDX-License-Identifier: Apache-2.0
 */
import { createPromise, Logger, Seconds, withTimeout } from "@matter/main";
import { BleError, MatterBle } from "@matter/main/protocol";
const logger = Logger.get("ProxyBleClient");
const SCAN_CONNECT_WAIT = Seconds(30);
class ProxyBleClient {
  #handler;
  #discoveredPeripherals = /* @__PURE__ */ new Map();
  #deviceDiscoveredCallback;
  #isScanning = false;
  #deviceDiscoveredObserver = (data, _connection) => {
    this.#handleDeviceDiscovered(data);
  };
  #scanStoppedObserver = (reason) => {
    logger.info(`Scan stopped by proxy client: ${reason}`);
    this.#isScanning = false;
  };
  constructor(handler) {
    this.#handler = handler;
    this.#handler.deviceDiscovered.on(this.#deviceDiscoveredObserver);
    this.#handler.scanStopped.on(this.#scanStoppedObserver);
  }
  setDiscoveryCallback(callback) {
    this.#deviceDiscoveredCallback = callback;
    for (const { peripheral, matterServiceData } of this.#discoveredPeripherals.values()) {
      this.#deviceDiscoveredCallback(peripheral, matterServiceData);
    }
  }
  async startScanning() {
    if (this.#isScanning) {
      return;
    }
    if (!this.#handler.connected) {
      logger.info(`BLE proxy not connected, waiting up to ${SCAN_CONNECT_WAIT}ms for client`);
      const { promise, resolver } = createPromise();
      const onConnect = () => resolver();
      this.#handler.connectionEstablished.on(onConnect);
      try {
        await withTimeout(SCAN_CONNECT_WAIT, promise);
      } catch {
        throw new BleError(
          `BLE proxy client did not connect within ${SCAN_CONNECT_WAIT}ms \u2014 cannot start scan`
        );
      } finally {
        this.#handler.connectionEstablished.off(onConnect);
      }
    }
    logger.debug("Start BLE scanning via proxy ...");
    await this.#handler.startScan({ service_uuids: ["fff6"], allow_duplicates: false });
    this.#isScanning = true;
  }
  async stopScanning() {
    this.#isScanning = false;
    logger.debug("Stop BLE scanning via proxy ...");
    await this.#handler.stopScan();
  }
  close() {
    this.#isScanning = false;
    this.#handler.deviceDiscovered.off(this.#deviceDiscoveredObserver);
    this.#handler.scanStopped.off(this.#scanStoppedObserver);
  }
  #handleDeviceDiscovered(data) {
    const { address, name, rssi, connectable, service_data } = data;
    const serviceData = /* @__PURE__ */ new Map();
    let matterServiceData;
    if (service_data) {
      for (const [uuid, base64Value] of Object.entries(service_data)) {
        const bytes = Buffer.from(base64Value, "base64");
        serviceData.set(uuid, bytes);
        if (MatterBle.isServiceUuid(uuid)) {
          matterServiceData = bytes;
        }
      }
    }
    const peripheral = {
      address,
      name,
      rssi,
      connectable,
      serviceData
    };
    if (!connectable) {
      logger.debug(`Peripheral ${address} is not connectable, ignoring`);
      return;
    }
    if (matterServiceData === void 0 || matterServiceData.length !== 8) {
      logger.debug(`Peripheral ${address} does not advertise valid Matter service data, ignoring`);
      return;
    }
    logger.info(
      `Discovered commissionable device ${address} (${name ?? "unnamed"}) rssi=${rssi ?? "n/a"} via proxy`
    );
    this.#discoveredPeripherals.set(address, { peripheral, matterServiceData });
    this.#deviceDiscoveredCallback?.(peripheral, matterServiceData);
  }
}
export {
  ProxyBleClient
};
//# sourceMappingURL=ProxyBleClient.js.map
