/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { Diagnostic } from "@matter/general";
import { Specification } from "@matter/model";
import { ArraySchema, TlvOfModel } from "@matter/types";
import { AccessControl } from "@matter/types/clusters/access-control";
import { MalformedRequestError } from "./MalformedRequestError.js";
import { resolvePathForSpecifier, Specifier } from "./Specifier.js";
const AclClusterId = AccessControl.id;
const AclAttributeId = AccessControl.attributes.acl.id;
const AclExtensionAttributeId = AccessControl.attributes.extension.id;
function isAclOrExtensionPath(path) {
  const { clusterId, attributeId } = path;
  return clusterId === AclClusterId && (attributeId === AclAttributeId || attributeId === AclExtensionAttributeId);
}
function Write(optionsOrData, ...data) {
  if (optionsOrData === void 0) {
    throw new MalformedRequestError(`Write action must have options or data`);
  }
  let options;
  if ("kind" in optionsOrData) {
    data = [optionsOrData, ...data];
    options = {};
  } else {
    options = optionsOrData;
  }
  const {
    writes: writeRequests = [],
    timed,
    timeout,
    chunkLists = true,
    // Should be true currently to stay in sync with chip sdk, see below
    suppressResponse,
    interactionModelRevision = Specification.INTERACTION_MODEL_REVISION
  } = options;
  const result = {
    timedRequest: !!timed || !!timeout,
    timeout,
    writeRequests,
    moreChunkedMessages: false,
    suppressResponse,
    interactionModelRevision,
    [Diagnostic.value]: () => Diagnostic.list(
      data.map((entry) => {
        const { version, value } = entry;
        return `${resolvePathForSpecifier(entry)} = ${Diagnostic.json(
          value
        )}${version !== void 0 ? `(version=${version})` : ""}`;
      })
    )
  };
  for (const entry of data) {
    reifyData(entry);
  }
  if (!writeRequests.length) {
    throw new MalformedRequestError(`Write action contains no attributes to write`);
  }
  return result;
  function reifyData(data2) {
    const cluster = Specifier.clusterOf(data2);
    if (cluster === void 0) {
      throw new MalformedRequestError(`Write action must specify a cluster`);
    }
    let { attributes } = data2;
    if (attributes === void 0) {
      throw new MalformedRequestError(`Write action must specify an attribute`);
    }
    if (!Array.isArray(attributes)) {
      attributes = [attributes];
    }
    const { endpoint, value, version: dataVersion } = data2;
    const prototype = {
      path: {
        endpointId: endpoint !== void 0 ? Specifier.endpointIdOf(data2) : void 0,
        clusterId: cluster.id,
        attributeId: void 0
      },
      dataVersion
    };
    for (const specifier of attributes) {
      const clusterId = cluster.id;
      const attribute = Specifier.attributeFor(cluster, specifier);
      const { id: attributeId } = attribute;
      const tlv = TlvOfModel(attribute);
      if (chunkLists && // As implemented for Matter 1.4.2 in https://github.com/project-chip/connectedhomeip/pull/38263
      // Acl writes will no longer be chunked by default, all others still
      // Will be streamlined later ... see https://github.com/project-chip/connectedhomeip/issues/38270
      Array.isArray(value) && tlv instanceof ArraySchema && !isAclOrExtensionPath({ clusterId, attributeId })) {
        writeRequests.push(
          ...tlv.encodeAsChunkedArray(value, { forWriteInteraction: true }).map(({ element: data3, listIndex }) => ({
            path: {
              ...prototype.path,
              attributeId: attribute.id,
              listIndex
            },
            data: data3,
            dataVersion
          }))
        );
      } else {
        writeRequests.push({
          ...prototype,
          path: {
            ...prototype.path,
            attributeId: attribute.id
          },
          data: tlv?.encodeTlv(value, { forWriteInteraction: true })
        });
      }
      result.timedRequest ||= attribute.schema.effectiveAccess.timed === true;
    }
  }
}
((Write2) => {
  function Attribute(data) {
    return {
      kind: "attribute",
      ...data
    };
  }
  Write2.Attribute = Attribute;
})(Write || (Write = {}));
export {
  Write
};
//# sourceMappingURL=Write.js.map
