"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 ValuePatcher_exports = {};
__export(ValuePatcher_exports, {
  ValuePatcher: () => ValuePatcher
});
module.exports = __toCommonJS(ValuePatcher_exports);
var import_general = require("@matter/general");
var import_model = require("@matter/model");
var import_protocol = require("@matter/protocol");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
function ValuePatcher(schema, supervisor) {
  switch (schema.effectiveMetatype) {
    // "any" means the schema defines no type.  Assume it's an object since ValuePatcher is only invoked where
    // an object is expected naturally
    case import_model.Metatype.any:
    case import_model.Metatype.object:
      return StructPatcher(schema, supervisor);
    case import_model.Metatype.array:
      return ListPatcher(schema, supervisor);
    default:
      return PrimitivePatcher();
  }
}
const defaultsCache = /* @__PURE__ */ new WeakMap();
function getDefaults(supervisor, schema) {
  if (defaultsCache.has(schema)) {
    return defaultsCache.get(schema);
  }
  const defaults = {};
  for (const member of supervisor.membersOf(schema)) {
    if (member.default !== void 0) {
      defaults[member.propertyName] = member.default;
      continue;
    }
    if (member.mandatory && member.nullable) {
      defaults[member.propertyName] = null;
      continue;
    }
  }
  defaultsCache.set(schema, defaults);
  return defaults;
}
function StructPatcher(schema, supervisor) {
  const memberPatchers = {};
  const memberDefaults = {};
  const memberArrays = {};
  const memberAltKeys = {};
  for (const member of supervisor.membersOf(schema)) {
    const metatype = member.effectiveMetatype;
    let handler;
    if (metatype === import_model.Metatype.object || metatype === import_model.Metatype.array) {
      handler = supervisor.get(member).patch;
    }
    const key = member.propertyName;
    if (member.id !== void 0) {
      memberAltKeys[member.id.toString()] = key;
    }
    memberPatchers[key] = handler;
    if (metatype === import_model.Metatype.object) {
      memberDefaults[key] = getDefaults(supervisor, member);
    }
    if (metatype === import_model.Metatype.array) {
      memberArrays[key] = true;
    }
  }
  return (changes, target, path) => {
    if (typeof changes !== "object" || changes === null || Array.isArray(changes)) {
      throw new import_protocol.WriteError(path, `patch definition ${changes} is not an object`);
    }
    if (typeof target !== "object" || target === null || Array.isArray(target)) {
      throw new import_protocol.WriteError(path, `cannot patch ${target} because it is not an object`);
    }
    for (let key in changes) {
      let newValue = changes[key];
      if (!(key in memberPatchers)) {
        if (!(key in memberAltKeys)) {
          throw new import_protocol.WriteError(path, `${key} is not a property of ${schema.name}`);
        }
        key = memberAltKeys[key];
      }
      const subpatch = memberPatchers[key];
      if (!subpatch || newValue === null || typeof newValue !== "object") {
        target[key] = newValue;
        continue;
      }
      if (memberArrays[key]) {
        if (target[key] === void 0 || target[key] === null) {
          newValue = subpatch(newValue, [], path.at(key));
          target[key] = newValue;
          continue;
        }
      }
      if (target[key] === void 0 || target[key] === null) {
        newValue = subpatch(newValue, { ...memberDefaults[key] }, path.at(key));
        target[key] = newValue;
        continue;
      }
      subpatch(newValue, target[key], path.at(key));
    }
    return target;
  };
}
function ListPatcher(schema, supervisor) {
  const entry = schema.listEntry;
  if (entry === void 0) {
    throw new import_protocol.SchemaImplementationError(new import_model.DataModelPath(schema.path), "List schema has no entry definition");
  }
  const entryMetatype = entry?.effectiveMetatype;
  let patchEntry;
  if (entryMetatype === import_model.Metatype.object || entryMetatype === import_model.Metatype.array) {
    patchEntry = supervisor.get(entry).patch;
  }
  let entryDefaults;
  if (entryMetatype === import_model.Metatype.object) {
    entryDefaults = getDefaults(supervisor, entry);
  }
  return (changes, target, path) => {
    if (typeof changes !== "object" || changes === null) {
      throw new import_protocol.WriteError(path, `patch definition ${changes} is not an object`);
    }
    if (!Array.isArray(target)) {
      throw new import_protocol.WriteError(path, `patch definition ${changes} is not an object`);
    }
    for (const indexStr in changes) {
      const index = Number.parseInt(indexStr);
      if (index < 0 || !Number.isFinite(index)) {
        throw new import_protocol.WriteError(path, `key ${index} is not a valid array index`);
      }
      let newValue = changes[indexStr];
      if (patchEntry) {
        const oldValue = index < target.length ? target[index] : void 0;
        if (newValue === void 0 || newValue === null || oldValue === void 0 || oldValue === null) {
          if (entryDefaults && (0, import_general.isObject)(newValue)) {
            newValue = patchEntry(newValue, { ...entryDefaults }, path.at(index));
          }
          target[index] = newValue;
        } else {
          patchEntry(newValue, target[index], path.at(index));
        }
      } else {
        target[index] = newValue;
      }
    }
    if (Array.isArray(changes)) {
      target.length = changes.length;
    }
    return target;
  };
}
function PrimitivePatcher() {
  return (_changes, _target, path) => {
    throw new import_general.ImplementationError(`Cannot generate patch ${path} because it does not define not a collection`);
  };
}
//# sourceMappingURL=ValuePatcher.js.map
