/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { Specification } from "#common/Specification.js";
import { Diagnostic } from "@matter/general";
import { ModelVariantTraversal } from "./ModelVariantTraversal.js";
function ModelDiff(from, to, depth = 2) {
  const traversal = new DiffTraversal(depth);
  return traversal.traverse({ from, to });
}
class DiffTraversal extends ModelVariantTraversal {
  #detailDepth;
  #currentDepth = 0;
  constructor(depth) {
    super(Specification.REVISION, ["from", "to"]);
    this.#detailDepth = depth;
  }
  visit(variants, recurse) {
    if (variants.map.to === void 0) {
      if (variants.map.from === void 0) {
        return;
      }
      return {
        kind: "delete",
        tag: variants.tag,
        name: variants.name
      };
    }
    if (variants.map.from === void 0) {
      return {
        kind: "add",
        tag: variants.tag,
        name: variants.name
      };
    }
    if (this.#currentDepth >= this.#detailDepth) {
      return;
    }
    this.#currentDepth++;
    const children = recurse().filter((child) => child !== void 0);
    this.#currentDepth--;
    if (!children.length) {
      return;
    }
    if (this.#currentDepth < this.#detailDepth - 1) {
      return {
        kind: "list",
        tag: variants.tag,
        name: variants.name,
        children
      };
    }
    const changes = {};
    for (const child of children) {
      changes[child.tag] = (changes[child.tag] ?? 0) + 1;
    }
    return {
      kind: "summary",
      tag: variants.tag,
      name: variants.name,
      changes
    };
  }
}
((ModelDiff2) => {
  function diagnosticOf(diff) {
    const id = `${diff?.tag}#${diff?.name}`;
    switch (diff?.kind) {
      case "add":
        return Diagnostic.added(id);
      case "delete":
        return Diagnostic.deleted(id);
      case "list":
        if (diff.children.length) {
          return [id, Diagnostic.list(diff.children.map(diagnosticOf))];
        }
        break;
      case "summary":
        const changes = Object.entries(diff.changes).map(([tag, count]) => {
          if (count < 0) {
            return Diagnostic.deleted(`${-count} ${tag}`);
          }
          if (count > 0) {
            return Diagnostic.added(`${count} ${tag}`);
          }
          return Diagnostic.weak(`${0} ${tag}`);
        });
        return [`${id}`, ...changes];
    }
    return Diagnostic.weak("(unchanged)");
  }
  ModelDiff2.diagnosticOf = diagnosticOf;
})(ModelDiff || (ModelDiff = {}));
export {
  ModelDiff
};
//# sourceMappingURL=ModelDiff.js.map
