"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 ClusterClient_exports = {};
__export(ClusterClient_exports, {
  ClusterClient: () => ClusterClient,
  GroupClusterClient: () => GroupClusterClient
});
module.exports = __toCommonJS(ClusterClient_exports);
var import_general = require("@matter/general");
var import_model = require("@matter/model");
var import_types = require("@matter/types");
var import_tlv = require("@matter/types/tlv");
var import_AttributeClient = require("./AttributeClient.js");
var import_EventClient = require("./EventClient.js");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
const logger = import_general.Logger.get("ClusterClient");
function GroupClusterClient(clusterDef, interactionClient, globalAttributeValues = {}) {
  if (!interactionClient.isGroupAddress) {
    throw new Error("GroupClusterClient must be used with a GroupAddress InteractionClient");
  }
  return ClusterClient(clusterDef, void 0, interactionClient, globalAttributeValues);
}
function ClusterClient(clusterDef, endpointId, interactionClient, globalAttributeValues = {}) {
  const ns = clusterDef;
  const isGroupAddress = interactionClient.isGroupAddress;
  if (isGroupAddress !== (endpointId === void 0)) {
    throw new Error("Endpoint ID must be defined for a Non-Group ClusterClient");
  }
  const clusterId = ns.id;
  const name = ns.name;
  const model = ns.schema;
  const revisionAttr = model.attributes(65533);
  const revision = typeof revisionAttr?.default === "number" ? revisionAttr.default : 1;
  function addAttributeToResult(attribute, attributeName, unknown = false) {
    attributes[attributeName] = (0, import_AttributeClient.createAttributeClient)(
      attribute,
      attributeName,
      endpointId,
      clusterId,
      interactionClient,
      !!globalAttributeValues?.attributeList?.includes(attribute.id),
      unknown
    );
    attributes[attribute.id] = attributes[attributeName];
    attributeToId[attribute.id] = attributeName;
    const capitalizedAttributeName = (0, import_general.capitalize)(attributeName);
    result[`get${capitalizedAttributeName}Attribute`] = async (requestFromRemote, isFabricFiltered = true) => {
      if (isGroupAddress) {
        throw new import_general.ImplementationError("Group cluster clients do not support reading attributes");
      }
      try {
        return await attributes[attributeName].get(requestFromRemote, isFabricFiltered);
      } catch (e) {
        if (import_types.StatusResponseError.is(e, import_types.StatusCode.UnsupportedAttribute)) {
          return void 0;
        }
        throw e;
      }
    };
    result[`get${capitalizedAttributeName}AttributeFromCache`] = () => {
      if (isGroupAddress) {
        throw new import_general.ImplementationError("Group cluster clients do not support reading attributes");
      }
      return attributes[attributeName].getLocal();
    };
    result[`set${capitalizedAttributeName}Attribute`] = async (value, dataVersion) => attributes[attributeName].set(value, dataVersion);
    result[`subscribe${capitalizedAttributeName}Attribute`] = async (listener, minIntervalS, maxIntervalS, knownDataVersion, isFabricFiltered) => {
      if (isGroupAddress) {
        throw new import_general.ImplementationError("Group cluster clients do not support subscribing attributes");
      }
      attributes[attributeName].addListener(listener);
      return attributes[attributeName].subscribe(
        minIntervalS,
        maxIntervalS,
        knownDataVersion,
        isFabricFiltered
      );
    };
    result[`add${capitalizedAttributeName}AttributeListener`] = (listener) => {
      if (isGroupAddress) {
        throw new import_general.ImplementationError("Group cluster clients do not support subscribing attributes");
      }
      attributes[attributeName].addListener(listener);
    };
    result[`remove${capitalizedAttributeName}AttributeListener`] = (listener) => {
      if (isGroupAddress) {
        throw new import_general.ImplementationError("Group cluster clients do not support subscribing attributes");
      }
      attributes[attributeName].removeListener(listener);
    };
  }
  function addEventToResult(event, eventName) {
    events[eventName] = (0, import_EventClient.createEventClient)(event, eventName, endpointId, clusterId, interactionClient);
    events[event.id] = events[eventName];
    eventToId[event.id] = eventName;
    const capitalizedEventName = (0, import_general.capitalize)(eventName);
    result[`get${capitalizedEventName}Event`] = async (minimumEventNumber, isFabricFiltered) => {
      if (isGroupAddress) {
        throw new import_general.ImplementationError("Group cluster clients do not support reading events");
      }
      try {
        return await events[eventName].get(minimumEventNumber, isFabricFiltered);
      } catch (e) {
        if (import_types.StatusResponseError.is(e, import_types.StatusCode.UnsupportedEvent)) {
          return void 0;
        }
        throw e;
      }
    };
    result[`subscribe${capitalizedEventName}Event`] = async (listener, minIntervalS, maxIntervalS, isUrgent, minimumEventNumber, isFabricFiltered) => {
      if (isGroupAddress) {
        throw new import_general.ImplementationError("Group cluster clients do not support subscribing to events");
      }
      events[eventName].addListener(listener);
      return events[eventName].subscribe(
        minIntervalS,
        maxIntervalS,
        isUrgent,
        minimumEventNumber,
        isFabricFiltered
      );
    };
    result[`add${capitalizedEventName}EventListener`] = (listener) => {
      if (isGroupAddress) {
        throw new import_general.ImplementationError("Group cluster clients do not support subscribing events");
      }
      events[eventName].addListener(listener);
    };
    result[`remove${capitalizedEventName}EventListener`] = (listener) => {
      if (isGroupAddress) {
        throw new import_general.ImplementationError("Group cluster clients do not support subscribing events");
      }
      events[eventName].removeListener(listener);
    };
  }
  const attributes = {};
  const events = {};
  const commands = {};
  const nsAttrs = ns.attributes ?? {};
  const nsCmds = ns.commands ?? {};
  const nsEvts = ns.events ?? {};
  let reportedFeatures = void 0;
  if (globalAttributeValues !== void 0) {
    if (globalAttributeValues.featureMap !== void 0) {
      reportedFeatures = globalAttributeValues.featureMap;
    }
  }
  const result = {
    id: clusterId,
    name,
    revision: globalAttributeValues?.clusterRevision ?? revision,
    _type: "ClusterClient",
    supportedFeatures: reportedFeatures ?? {},
    isUnknown: false,
    endpointId,
    attributes,
    events,
    commands,
    subscribeAllAttributes: async (options) => {
      if (isGroupAddress) {
        throw new import_general.ImplementationError("Group cluster clients do not support subscribing attributes");
      }
      const {
        minIntervalFloorSeconds,
        maxIntervalCeilingSeconds,
        keepSubscriptions,
        isFabricFiltered,
        eventFilters,
        dataVersionFilters
      } = options;
      return interactionClient.subscribeMultipleAttributesAndEvents({
        attributes: [{ endpointId, clusterId }],
        events: [{ endpointId, clusterId }],
        minIntervalFloorSeconds,
        maxIntervalCeilingSeconds,
        keepSubscriptions,
        isFabricFiltered,
        eventFilters,
        dataVersionFilters,
        attributeListener: (attributeData) => {
          const { path, value } = attributeData;
          result._triggerAttributeUpdate(path.attributeId, value);
        },
        eventListener: (eventData) => {
          const { path, events: newEvents } = eventData;
          result._triggerEventUpdate(path.eventId, newEvents);
        }
      });
    },
    _triggerAttributeUpdate(attributeId, value) {
      const attributeName = attributeToId[attributeId];
      if (attributeName === void 0) {
        logger.warn("Unknown attribute id", attributeId);
        return;
      }
      if (attributes[attributeName] !== void 0) {
        attributes[attributeName].update(value);
      } else {
        logger.warn("Attribute not found", attributeName, "in list", Object.keys(attributes));
      }
    },
    _triggerEventUpdate(eventId, eventData) {
      const eventName = eventToId[eventId];
      if (eventName === void 0) {
        logger.warn("Unknown event id", eventId);
        return;
      }
      if (events[eventName] !== void 0) {
        const event = events[eventName];
        eventData.forEach((data) => event.update(data));
      } else {
        logger.warn("Event not found", eventName, "in list", Object.keys(events));
      }
    },
    isAttributeSupported: (attributeId) => {
      if (isGroupAddress) {
        throw new import_general.ImplementationError("Group cluster clients do not allow to determine attribute existence.");
      }
      return !!globalAttributeValues?.attributeList?.includes(attributeId);
    },
    isAttributeSupportedByName: (attributeName) => {
      if (isGroupAddress) {
        throw new import_general.ImplementationError("Group cluster clients do not allow to determine attribute existence.");
      }
      const attribute = attributes[attributeName];
      if (attribute === void 0) {
        return false;
      }
      return !!globalAttributeValues?.attributeList?.includes(attribute.id);
    },
    isCommandSupported: (commandId) => {
      if (isGroupAddress) {
        throw new import_general.ImplementationError("Group cluster clients do not allow to determine command existence.");
      }
      return !!globalAttributeValues?.acceptedCommandList?.includes(commandId);
    },
    isCommandSupportedByName: (commandName) => {
      if (isGroupAddress) {
        throw new import_general.ImplementationError("Group cluster clients do not allow to determine attribute existence.");
      }
      const cmd = nsCmds[commandName];
      if (cmd === void 0) {
        return false;
      }
      return !!globalAttributeValues?.acceptedCommandList?.includes(cmd.id);
    }
  };
  const attributeToId = {};
  for (const attr of model.attributes) {
    if (attr.isDisallowed || attr.effectiveMetatype === void 0) {
      continue;
    }
    const attrName = attr.propertyName;
    const nsAttr = nsAttrs[attrName] ?? {
      id: (0, import_types.AttributeId)(attr.id),
      name: attrName,
      schema: attr
    };
    addAttributeToResult(nsAttr, attrName);
  }
  if (globalAttributeValues?.attributeList !== void 0) {
    for (const attributeId of globalAttributeValues.attributeList) {
      if (attributeToId[attributeId] === void 0) {
        const unknownModel = new import_model.AttributeModel({
          id: attributeId,
          name: `unknown_${attributeId}`,
          access: "RW"
        });
        const nsAttr = {
          id: attributeId,
          name: unknownModel.name,
          schema: unknownModel
        };
        addAttributeToResult(nsAttr, `unknownAttribute_${import_general.Diagnostic.hex(attributeId)}`, true);
      }
    }
  }
  const eventToId = {};
  for (const eventName in nsEvts) {
    addEventToResult(nsEvts[eventName], eventName);
  }
  const commandToId = {};
  for (const commandName in nsCmds) {
    const cmd = nsCmds[commandName];
    const requestId = cmd.id;
    const isVoidRequest = (0, import_types.TlvOfModel)(cmd.schema) === import_tlv.TlvVoid;
    commandToId[requestId] = commandName;
    if (isVoidRequest) {
      commands[commandName] = async (options = {}) => {
        const {
          asTimedRequest,
          timedRequestTimeout,
          useExtendedFailSafeMessageResponseTimeout,
          expectedProcessingTime
        } = options;
        if (isGroupAddress) {
          return interactionClient.invokeWithSuppressedResponse({
            clusterId,
            command: cmd,
            request: void 0,
            asTimedRequest,
            timedRequestTimeout
          });
        }
        return interactionClient.invoke({
          endpointId,
          clusterId,
          command: cmd,
          request: void 0,
          asTimedRequest,
          timedRequestTimeout,
          expectedProcessingTime,
          useExtendedFailSafeMessageResponseTimeout
        });
      };
    } else {
      commands[commandName] = async (request, options = {}) => {
        const {
          asTimedRequest,
          timedRequestTimeout,
          useExtendedFailSafeMessageResponseTimeout,
          expectedProcessingTime
        } = options;
        if (isGroupAddress) {
          return interactionClient.invokeWithSuppressedResponse({
            clusterId,
            command: cmd,
            request,
            asTimedRequest,
            timedRequestTimeout
          });
        }
        return interactionClient.invoke({
          endpointId,
          clusterId,
          command: cmd,
          request,
          asTimedRequest,
          timedRequestTimeout,
          expectedProcessingTime,
          useExtendedFailSafeMessageResponseTimeout
        });
      };
    }
    commands[requestId] = commands[commandName];
    result[commandName] = result.commands[commandName];
  }
  return result;
}
//# sourceMappingURL=ClusterClient.js.map
