"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
var __typeError = (msg) => {
  throw TypeError(msg);
};
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 __using = (stack, value, async) => {
  if (value != null) {
    if (typeof value !== "object" && typeof value !== "function") __typeError("Object expected");
    var dispose, inner;
    if (async) dispose = value[__knownSymbol("asyncDispose")];
    if (dispose === void 0) {
      dispose = value[__knownSymbol("dispose")];
      if (async) inner = dispose;
    }
    if (typeof dispose !== "function") __typeError("Object not disposable");
    if (inner) dispose = function() {
      try {
        inner.call(this);
      } catch (e) {
        return Promise.reject(e);
      }
    };
    stack.push([async, dispose, value]);
  } else if (async) {
    stack.push([async]);
  }
  return value;
};
var __callDispose = (stack, error, hasError) => {
  var E = typeof SuppressedError === "function" ? SuppressedError : function(e, s, m, _) {
    return _ = Error(m), _.name = "SuppressedError", _.error = e, _.suppressed = s, _;
  };
  var fail = (e) => error = hasError ? new E(e, error, "An error was suppressed during disposal") : (hasError = true, e);
  var next = (it) => {
    while (it = stack.pop()) {
      try {
        var result = it[1] && it[1].call(it[2]);
        if (it[0]) return Promise.resolve(result).then(next, (e) => (fail(e), next()));
      } catch (e) {
        fail(e);
      }
    }
    if (hasError) throw error;
  };
  return next();
};
var IpServiceResolution_exports = {};
__export(IpServiceResolution_exports, {
  IpServiceResolution: () => IpServiceResolution
});
module.exports = __toCommonJS(IpServiceResolution_exports);
var import_DnsCodec = require("#codec/DnsCodec.js");
var import_ServerAddressSet = require("#net/ServerAddressSet.js");
var import_Abort = require("#util/Abort.js");
var import_Ip = require("#util/Ip.js");
var import_Multiplex = require("#util/Multiplex.js");
var import_Observable = require("#util/Observable.js");
var import_Set = require("#util/Set.js");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
async function IpServiceResolution(service, abort, ipv4 = true) {
  var _stack = [];
  try {
    const localAbort = __using(_stack, new import_Abort.Abort({ abort }));
    const workers = __using(_stack, new import_Multiplex.BasicMultiplex(), true);
    const observers = __using(_stack, new import_Observable.ObserverGroup());
    const hosts = new import_Set.BasicSet();
    let hostResolvers;
    observers.on(hosts.added, (name) => {
      if ([...name.records].find(
        (record) => record.recordType === import_DnsCodec.DnsRecordType.AAAA || record.recordType === import_DnsCodec.DnsRecordType.A
      )) {
        return;
      }
      if (!hostResolvers) {
        hostResolvers = /* @__PURE__ */ new Map();
      }
      const hostAbort = new import_Abort.Abort({ abort: localAbort });
      hostResolvers.set(name, hostAbort);
      workers.add(
        service.names.solicitor.discover({
          name,
          recordTypes: ipv4 ? [import_DnsCodec.DnsRecordType.A, import_DnsCodec.DnsRecordType.AAAA] : [import_DnsCodec.DnsRecordType.AAAA],
          abort: hostAbort
        }).finally(hostAbort.close.bind(hostAbort))
      );
    });
    observers.on(hosts.deleted, (name) => {
      const abortHost = hostResolvers?.get(name);
      if (!abortHost) {
        return;
      }
      hostResolvers?.delete(name);
      abortHost();
    });
    for (const record of service.name.records) {
      if (record.recordType !== import_DnsCodec.DnsRecordType.SRV) {
        continue;
      }
      hosts.add(service.names.get(record.name));
    }
    const existingAddresses = (0, import_ServerAddressSet.ServerAddressSet)(service.addresses);
    observers.on(service.changed, () => {
      for (const address of service.addresses) {
        if (!ipv4 && (0, import_Ip.isIPv4)(address.ip)) {
          continue;
        }
        if (!existingAddresses.has(address) && (ipv4 || (0, import_Ip.isIPv6)(address.ip))) {
          localAbort();
        }
      }
      const srvs = [...service.name.records].filter((record) => record.recordType === import_DnsCodec.DnsRecordType.SRV);
      const newHostnames = new Set(srvs.map((record) => record.value.target));
      for (const hostname of newHostnames) {
        hosts.add(service.names.get(hostname));
      }
      for (const name of hosts) {
        if (newHostnames.has(name.qname)) {
          continue;
        }
        hosts.delete(name);
      }
    });
    workers.add(
      service.names.solicitor.discover({
        abort: localAbort,
        name: service.name,
        recordTypes: [import_DnsCodec.DnsRecordType.SRV],
        get associatedNames() {
          return hosts;
        }
      })
    );
    await localAbort;
  } catch (_) {
    var _error = _, _hasError = true;
  } finally {
    var _promise = __callDispose(_stack, _error, _hasError);
    _promise && await _promise;
  }
}
//# sourceMappingURL=IpServiceResolution.js.map
