/**
 * @license
 * Copyright 2022-2025 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { Behavior } from "#behavior/Behavior.js";
import { BasicInformationBehavior } from "#behaviors/basic-information";
import { ImplementationError, isNetworkInterface, NetInterfaceSet, TransportInterfaceSet } from "#general";
import { Node } from "#node/Node.js";
import { InteractionServer } from "#node/server/InteractionServer.js";
import {
  Ble,
  ClientSubscriptionHandler,
  ClientSubscriptions,
  FabricAuthority,
  FabricAuthorityConfigurationProvider,
  FabricManager,
  MdnsScanner,
  MdnsService,
  ScannerSet
} from "#protocol";
import { CommissioningServer } from "../commissioning/CommissioningServer.js";
import { NetworkServer } from "../network/NetworkServer.js";
import { ActiveDiscoveries } from "./discovery/ActiveDiscoveries.js";
class ControllerBehavior extends Behavior {
  static id = "controller";
  async initialize() {
    if (this.state.adminFabricLabel === void 0 || this.state.adminFabricLabel === "") {
      throw new ImplementationError("adminFabricLabel must be set for ControllerBehavior.");
    }
    const adminFabricLabel = this.state.adminFabricLabel;
    if (this.state.ip === void 0) {
      this.state.ip = true;
    }
    if (this.state.ip !== false) {
      this.env.get(ScannerSet).add((await this.env.load(MdnsService)).scanner);
    }
    if (this.state.ble === void 0) {
      this.state.ble = (await this.agent.load(NetworkServer)).state.ble;
    }
    if (this.state.ble !== false) {
      this.env.get(ScannerSet).add(Ble.get().getBleScanner());
    }
    if (!this.env.has(FabricAuthorityConfigurationProvider)) {
      const biState = this.endpoint.stateOf(BasicInformationBehavior);
      this.env.set(
        FabricAuthorityConfigurationProvider,
        new class extends FabricAuthorityConfigurationProvider {
          get vendorId() {
            return biState.vendorId;
          }
          get adminFabricLabel() {
            return adminFabricLabel;
          }
        }()
      );
    }
    await this.env.load(FabricAuthority);
    const commissioning = this.agent.get(CommissioningServer);
    if (commissioning.state.enabled === void 0) {
      const totalFabrics = this.env.get(FabricManager).length;
      const controlledFabrics = this.env.get(FabricAuthority).fabrics.length;
      if (controlledFabrics === totalFabrics) {
        commissioning.state.enabled = false;
      }
    }
    const node = Node.forEndpoint(this.endpoint);
    this.reactTo(node.lifecycle.online, this.#nodeOnline);
    if (node.lifecycle.isOnline) {
      this.#nodeOnline();
    }
  }
  async [Symbol.asyncDispose]() {
    await this.env.close(ActiveDiscoveries);
    this.env.delete(FabricAuthority);
    this.env.delete(ScannerSet);
  }
  #nodeOnline() {
    const netInterfaces = this.env.get(NetInterfaceSet);
    const netTransports = this.env.get(TransportInterfaceSet);
    for (const transport of netTransports) {
      if (isNetworkInterface(transport)) {
        netInterfaces.add(transport);
      }
    }
    if (this.state.ble) {
      netInterfaces.add(Ble.get().getBleCentralInterface());
    }
    const subscriptions = this.env.get(ClientSubscriptions);
    const interactionServer = this.env.get(InteractionServer);
    interactionServer.clientHandler = new ClientSubscriptionHandler(subscriptions);
    const node = Node.forEndpoint(this.endpoint);
    this.reactTo(node.lifecycle.goingOffline, this.#nodeGoingOffline);
    const authority = this.env.get(FabricAuthority);
    for (const fabric of authority.fabrics) {
      this.#enableScanningForFabric(fabric);
    }
    this.reactTo(authority.fabricAdded, this.#enableScanningForFabric);
    const scanners = this.env.get(ScannerSet);
    for (const scanner of scanners) {
      this.#enableScanningForScanner(scanner);
    }
    this.reactTo(scanners.added, this.#enableScanningForScanner);
  }
  async #nodeGoingOffline() {
    await this.env.close(ClientSubscriptions);
    const netInterfaces = this.env.get(NetInterfaceSet);
    const netTransports = this.env.get(TransportInterfaceSet);
    for (const intf of netInterfaces) {
      if (netTransports.has(intf)) {
        netInterfaces.delete(intf);
      }
    }
    await this.env.close(NetInterfaceSet);
  }
  #enableScanningForFabric(fabric) {
    this.internal.mdnsTargetCriteria.operationalTargets.push({ operationalId: fabric.operationalId });
  }
  #enableScanningForScanner(scanner) {
    if (!(scanner instanceof MdnsScanner)) {
      return;
    }
    scanner.targetCriteriaProviders.add(this.internal.mdnsTargetCriteria);
  }
}
((ControllerBehavior2) => {
  class Internal {
    /**
     * MDNS scanner criteria for each controlled fabric (keyed by operational ID).
     */
    mdnsTargetCriteria = {
      commissionable: true,
      operationalTargets: []
    };
  }
  ControllerBehavior2.Internal = Internal;
  class State {
    /**
     * Set to false to disable scanning on BLE.
     *
     * By default the controller scans via BLE if BLE is available.
     */
    ble = void 0;
    /**
     * Set to false to disable scanning on IP networks.
     *
     * By default the controller always scans on IP networks.
     */
    ip = void 0;
    /**
     * Contains the label of the admin fabric which is set for all commissioned devices
     */
    adminFabricLabel = "matter.js";
  }
  ControllerBehavior2.State = State;
})(ControllerBehavior || (ControllerBehavior = {}));
export {
  ControllerBehavior
};
//# sourceMappingURL=ControllerBehavior.js.map
