// src/logic/adbDeviceKit.ts
import { createRequire } from "node:module";

// src/utils/adbPath.ts
import { existsSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
function getPlatformDir() {
  const platform = process.platform;
  if (platform === "win32") {
    return "windows";
  }
  if (platform === "darwin") {
    return "darwin";
  }
  if (platform === "linux") {
    return "linux";
  }
  throw new Error(`Unsupported platform: ${platform}`);
}
function getAdbBinaryName() {
  if (process.platform === "win32") {
    return "adb.exe";
  }
  return "adb";
}
function getAdbBinaryPath() {
  const __filename = fileURLToPath(import.meta.url);
  const __dirname = path.dirname(__filename);
  let packageRoot;
  if (__dirname.includes("dist")) {
    packageRoot = path.resolve(__dirname, "..", "..");
  } else {
    packageRoot = path.resolve(__dirname, "..", "..");
  }
  const platformDir = getPlatformDir();
  const binaryName = getAdbBinaryName();
  const distPath = path.join(packageRoot, "dist", "resources", "bin", platformDir, binaryName);
  if (existsSync(distPath)) {
    return distPath;
  }
  const devPath = path.join(packageRoot, "resources", "bin", platformDir, binaryName);
  if (existsSync(devPath)) {
    return devPath;
  }
  return null;
}

// src/utils/debug.ts
import debug from "debug";
var logTask = debug("adb-kit:task");
var logInfo = debug("adb-kit:info");
var logWarning = debug("adb-kit:warning");
var logError = debug("adb-kit:error");
logTask.color = "40";
logInfo.color = "45";
logWarning.color = "214";
logError.color = "160";

// src/logic/adbDeviceKit.ts
var require2 = createRequire(import.meta.url);
var adbkit = require2("@devicefarmer/adbkit");
function ensureAdbPathFromResources() {
  const adbPath = getAdbBinaryPath();
  if (adbPath && !process.env.ADB_PATH) {
    process.env.ADB_PATH = adbPath;
    logInfo(`Using ADB from resources: ${adbPath}`);
  }
}
var deviceProps = {
  Manufacturer: "ro.product.manufacturer",
  Name: "ro.product.name",
  Model: "ro.product.model",
  "Android Version": "ro.build.version.release",
  Platform: "ro.board.platform",
  CPU: "ro.product.cpu.abi",
  "CPU.abi2": "ro.product.cpu.abi2",
  Description: "ro.build.description",
  Fingerprint: "ro.build.fingerprint",
  Brand: "ro.product.brand",
  Device: "ro.product.device",
  "GSM Flexversion": "ro.gsm.flexversion",
  "Locale Language": "ro.product.locale.language",
  "Locale Region": "ro.product.locale.region",
  "Wifi Channels": "ro.wifi.channels",
  "Board Platform": "ro.board.platform",
  "Product Board": "ro.product.board",
  "Display ID": "ro.build.display.id",
  "GSM IMEI": "gsm.baseband.imei",
  "Version Incremental": "ro.build.version.incremental",
  "Version SDK": "ro.build.version.sdk",
  "Version Codename": "ro.build.version.codename",
  "Version Release": "ro.build.version.release",
  "Build Date": "ro.build.date",
  "Build Type": "ro.build.type",
  "Build User": "ro.build.user"
};
var AdbDeviceKit = class {
  constructor(deviceId, port) {
    this.port = port;
    ensureAdbPathFromResources();
    this.client = adbkit.default.createClient();
    this.deviceId = deviceId.split("\\").pop() ?? deviceId;
    logInfo(`Device ID: ${this.deviceId}`);
    this.device = this.client.getDevice(this.deviceId);
  }
  client;
  device;
  deviceId;
  async listDevices() {
    const devices = await this.client.listDevices();
    return devices;
  }
  async getProperty(adbDevice, property) {
    try {
      logTask(`Getting property ${property} for device ${this.deviceId}`);
      const stream = await adbDevice.shell(`getprop ${deviceProps[property]}`);
      logTask(`Stream: ${stream}`);
      const chunks = [];
      for await (const chunk of stream) {
        chunks.push(chunk);
      }
      return Buffer.concat(chunks).toString().trim();
    } catch {
      return "";
    }
  }
  async getAllDeviceProperties() {
    if (!await this.hasUsbDebugging()) {
      this.waitForUsbDebugging(1e4);
    }
    return this.device.getProperties();
  }
  async getDeviceProperties(properties) {
    logTask(`Getting properties ${properties.join(", ")} for device ${this.deviceId}`);
    if (!await this.hasUsbDebugging()) {
      this.waitForUsbDebugging(1e4);
    }
    const propertiesValues = await Promise.all(
      properties.map((property) => this.getProperty(this.device, property))
    );
    return propertiesValues;
  }
  async installApp(appPath) {
    logTask(`Installing app ${appPath} on device ${this.deviceId}`);
    if (!await this.hasUsbDebugging()) {
      this.waitForUsbDebugging(1e4);
    }
    await this.device.install(appPath);
  }
  async uninstallApp(packageName) {
    logTask(`Uninstalling app ${packageName} on device ${this.deviceId}`);
    if (!await this.hasUsbDebugging()) {
      this.waitForUsbDebugging(1e4);
    }
    await this.device.uninstall(packageName);
  }
  async isAppInstalled(packageName) {
    logTask(`Checking if app ${packageName} is installed on device ${this.deviceId}`);
    if (!await this.hasUsbDebugging()) {
      this.waitForUsbDebugging(1e4);
    }
    return await this.device.isInstalled(packageName);
  }
  /**
   * Applications have life of their own, so we need to get the client to use it in other parts of the code.
   * @returns The adb client
   */
  async getClient() {
    if (!this.hasUsbDebugging) {
      this.waitForUsbDebugging(1e4);
    }
    return this.client;
  }
  async hasUsbDebugging() {
    const devices = await this.listDevices();
    return !!devices.find((device) => device.id === this.deviceId);
  }
  async waitForUsbDebugging(timeout = 12e4) {
    const tracker = await this.client.trackDevices();
    return new Promise((resolve, reject) => {
      const timeoutId = setTimeout(() => {
        reject(new Error("Timeout waiting for USB debugging"));
      }, timeout);
      tracker.on("remove", (_) => {
        clearTimeout(timeoutId);
      });
      tracker.on("add", (device) => {
        if (device.type === "device") {
          clearTimeout(timeoutId);
          resolve(true);
        }
      });
      tracker.on("change", (device) => {
        if (device.type === "device") {
          clearTimeout(timeoutId);
          resolve(true);
        } else {
          resolve(false);
        }
      });
    });
  }
  async getDeviceId() {
    return this.deviceId;
  }
  async getPort() {
    return this.port;
  }
};

// src/logic/devicesMonitor.ts
import EventEmitter from "node:events";
import { createRequire as createRequire2 } from "node:module";
import usbDeviceListener from "@mcesystems/usb-device-listener";
var require3 = createRequire2(import.meta.url);
var adbkit2 = require3("@devicefarmer/adbkit");
function ensureAdbPathFromResources2() {
  const adbPath = getAdbBinaryPath();
  if (adbPath && !process.env.ADB_PATH) {
    process.env.ADB_PATH = adbPath;
    logInfo(`Using ADB from resources: ${adbPath}`);
  }
}
var DevicesMonitor = class {
  constructor(config, identifyAlreadyConnected = false) {
    this.config = config;
    this.identifyAlreadyConnected = identifyAlreadyConnected;
  }
  kits = /* @__PURE__ */ new Map();
  eventEmitter;
  async startTracking() {
    logInfo("Starting devices monitor");
    usbDeviceListener.startListening(this.config);
    this.eventEmitter = new EventEmitter();
    if (this.identifyAlreadyConnected) {
      await this.connectedDevices();
      for (const kit of this.kits.values()) {
        setTimeout(() => {
          this.eventEmitter?.emit("added", kit);
        }, 0);
      }
    }
    usbDeviceListener.onDeviceAdd((device) => {
      console.log("Device added:", device.deviceId);
      if (!device.logicalPort) {
        return;
      }
      const existingKit = this.kits.get(device.deviceId);
      const adbDeviceKit = existingKit ?? new AdbDeviceKit(device.deviceId, device.logicalPort);
      if (!existingKit) {
        this.kits.set(device.deviceId, adbDeviceKit);
      }
      this.eventEmitter?.emit("added", adbDeviceKit);
    });
    usbDeviceListener.onDeviceRemove((device) => {
      if (!device.logicalPort) {
        return;
      }
      this.kits.delete(device.deviceId);
      this.eventEmitter?.emit("removed", device.deviceId);
    });
    return this.eventEmitter;
  }
  async stopTracking() {
    if (!this.eventEmitter) {
      return;
    }
    this.eventEmitter.removeAllListeners();
    this.kits.clear();
    this.eventEmitter = void 0;
    usbDeviceListener.stopListening();
  }
  async connectedDevices() {
    ensureAdbPathFromResources2();
    const client = adbkit2.default.createClient();
    const devicesIds = await client.listDevices().filter((device) => device.type === "device").map((device) => device.id);
    this.kits = new Map(
      await usbDeviceListener.listDevices().map((device) => ({
        id: device.deviceId.split("\\").pop() ?? "",
        port: device.logicalPort ?? 0
      })).filter((device) => devicesIds.includes(device.id)).map((device) => [device.id, new AdbDeviceKit(device.id, device.port)])
    );
    return this.kits.values();
  }
};
export {
  AdbDeviceKit,
  DevicesMonitor
};
//# sourceMappingURL=index.js.map
