/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { camelize, Diagnostic } from "#general";
import { Specification } from "#model";
import { MalformedRequestError } from "./MalformedRequestError.js";
import { resolvePathForSpecifier, Specifier } from "./Specifier.js";
function Read(optionsOrSelector, ...selectors) {
  if (optionsOrSelector === void 0) {
    throw new MalformedRequestError(`Read action designates no attributes or events`);
  }
  let options;
  if ("kind" in optionsOrSelector) {
    selectors = [optionsOrSelector, ...selectors];
    options = {};
  } else {
    options = optionsOrSelector;
  }
  const { fabricFilter = true, interactionModelRevision = Specification.INTERACTION_MODEL_REVISION } = options;
  let { attributes: attributeRequests, versionFilters, events: eventRequests, eventFilters } = options;
  const result = {
    isFabricFiltered: fabricFilter,
    interactionModelRevision,
    [Diagnostic.value]: () => Diagnostic.dict({
      attributes: attributeRequests?.length ? selectors.filter(({ kind }) => kind === "attribute").map((path) => resolvePathForSpecifier(path)).join(", ") : void 0,
      events: eventRequests?.length ? selectors.filter(({ kind }) => kind === "event").map((path) => resolvePathForSpecifier(path)).join(", ") : void 0,
      dataVersionFilters: versionFilters?.length ? versionFilters.map(
        ({ path: { endpointId, clusterId }, dataVersion }) => `${endpointId}/${clusterId}=${dataVersion}`
      ).join(", ") : void 0,
      eventFilters: eventFilters?.length ? eventFilters.map(({ nodeId, eventMin }) => `${nodeId}=${eventMin}`).join(", ") : void 0
    })
  };
  for (const selector of selectors) {
    reifySelector(selector);
  }
  if (!attributeRequests?.length && !eventRequests?.length) {
    throw new MalformedRequestError(`Read action designates no attributes or events`);
  }
  if (attributeRequests) {
    result.attributeRequests = attributeRequests;
  }
  if (versionFilters) {
    result.dataVersionFilters = versionFilters;
  }
  if (eventRequests) {
    result.eventRequests = eventRequests;
  }
  if (eventFilters !== void 0) {
    result.eventFilters = eventFilters;
  }
  return result;
  function reifySelector(selector) {
    switch (selector.kind) {
      case "attribute":
        reifyAttributeSelector(selector);
        break;
      case "event":
        reifyEventSelector(selector);
        break;
      default:
        throw new MalformedRequestError(`Invalid selector kind "${selector.kind}"`);
    }
  }
  function reifyAttributeSelector(selector) {
    const cluster = Specifier.clusterOf(selector);
    const { endpoint } = selector;
    if (typeof endpoint === "object" && endpoint?.versions && typeof cluster === "object" && cluster !== null) {
      const version = endpoint.versions?.[camelize(cluster.name)];
      if (version !== void 0) {
        const filter = {
          path: { endpointId: endpoint.number, clusterId: cluster.id },
          dataVersion: version
        };
        if (versionFilters === void 0) {
          versionFilters = [filter];
        } else if (versionFilters.find(
          ({ path: { endpointId, clusterId } }) => endpointId === endpoint.number && clusterId === cluster.id
        ) === void 0) {
          versionFilters.push(filter);
        }
      }
    }
    if (attributeRequests === void 0) {
      attributeRequests = [];
    }
    const prototype = {};
    if (endpoint !== void 0) {
      prototype.endpointId = Specifier.endpointIdOf(selector);
    }
    if (cluster !== void 0) {
      prototype.clusterId = cluster.id;
    }
    let { attributes } = selector;
    if (attributes === void 0) {
      attributeRequests.push(prototype);
      return;
    }
    if (!Array.isArray(attributes)) {
      attributes = [attributes];
    }
    for (const specifier of attributes) {
      attributeRequests.push({ ...prototype, attributeId: Specifier.attributeFor(cluster, specifier).id });
    }
  }
  function reifyEventSelector(selector) {
    const cluster = Specifier.clusterOf(selector);
    const { endpoint } = selector;
    if (typeof endpoint === "object" && endpoint.minEvent !== void 0) {
      if (eventFilters === void 0) {
        eventFilters = [{ eventMin: endpoint.minEvent }];
      }
    }
    if (eventRequests === void 0) {
      eventRequests = [];
    }
    const prototype = {};
    if (endpoint !== void 0) {
      prototype.endpointId = Specifier.endpointIdOf(selector);
    }
    if (cluster !== void 0) {
      prototype.clusterId = cluster.id;
    }
    let { events } = selector;
    if (events === void 0) {
      eventRequests.push(prototype);
      return;
    }
    if (!Array.isArray(events)) {
      events = [events];
    }
    for (const specifier of events) {
      eventRequests.push({ ...prototype, eventId: Specifier.eventFor(cluster, specifier).id });
    }
  }
}
((Read2) => {
  function containsAttribute(request) {
    return !!request.attributeRequests?.length;
  }
  Read2.containsAttribute = containsAttribute;
  function containsEvent(request) {
    return !!request.eventRequests?.length;
  }
  Read2.containsEvent = containsEvent;
  function Attribute(selector) {
    return {
      kind: "attribute",
      ...selector
    };
  }
  Read2.Attribute = Attribute;
  function Event(selector) {
    return {
      kind: "event",
      ...selector
    };
  }
  Read2.Event = Event;
})(Read || (Read = {}));
export {
  Read
};
//# sourceMappingURL=Read.js.map
