/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { readFile, writeFile } from "node:fs/promises";
import { PicsExpression } from "./chip/pics/expression.js";
var TestDescriptor;
((TestDescriptor2) => {
  TestDescriptor2.CURRENT_FORMAT = 2;
  TestDescriptor2.DEFAULT_FILENAME = "build/test-report.json";
  function filter(descriptor, criteria) {
    const { includePaths, kinds, pics, predicate } = criteria;
    let memberNames;
    if (includePaths) {
      memberNames = {};
      for (const path of includePaths) {
        let incl = memberNames;
        const segments = path.split("/");
        if (segments[0] === "") {
          segments[0] = descriptor.name;
        }
        for (const segment of segments) {
          incl = incl[segment] ??= {};
        }
      }
    }
    return filter2(descriptor, memberNames);
    function filter2(descriptor2, names) {
      const memberNames2 = names?.[descriptor2.name];
      if (names && !memberNames2) {
        return;
      }
      if (pics && descriptor2.pics !== void 0) {
        descriptor2.picsValues = pics;
        const expr = new PicsExpression(descriptor2.pics);
        if (!expr.evaluate(pics)) {
          return;
        }
      }
      if (descriptor2.kind === "suite") {
        const { members } = descriptor2;
        if (!members?.length) {
          return;
        }
        let filteredMembers;
        for (const member of members) {
          const filteredMember = filter2(member, memberNames2);
          if (!filteredMember) {
            continue;
          }
          if (predicate && !predicate(filteredMember)) {
            continue;
          }
          if (filteredMembers) {
            filteredMembers.push(filteredMember);
          } else {
            filteredMembers = [filteredMember];
          }
        }
        if (filteredMembers) {
          return { ...descriptor2, members: filteredMembers };
        }
        return;
      }
      if (kinds && !kinds.includes(descriptor2.kind)) {
        return;
      }
      return descriptor2;
    }
  }
  TestDescriptor2.filter = filter;
  function visit(descriptor, fn) {
    if (fn(descriptor) === false) {
      return;
    }
    if (!descriptor.members) {
      return;
    }
    for (const member of descriptor.members) {
      visit(member, fn);
    }
  }
  TestDescriptor2.visit = visit;
  async function open(path) {
    let descriptor = {
      name: "?",
      kind: "suite",
      members: []
    };
    try {
      const json = await readFile(path, "utf-8");
      descriptor = JSON.parse(json, (k, v) => k === "picsValues" ? void 0 : v);
      if (typeof descriptor?.name !== "string" || descriptor.kind !== "suite" || !Array.isArray(descriptor.members)) {
        throw new Error(`Invalid test descriptor "${path}"`);
      }
    } catch (e) {
      if (!(e instanceof SyntaxError) && e?.code !== "ENOENT") {
        throw e;
      }
    }
    return descriptor;
  }
  TestDescriptor2.open = open;
  async function save(path, descriptor) {
    await writeFile(
      path,
      JSON.stringify(descriptor, (k, v) => k === "picsValues" ? void 0 : v, 4)
    );
  }
  TestDescriptor2.save = save;
  function merge(previous, updates) {
    const descriptor = {
      ...updates
    };
    for (const name of ["durationMs", "passed", "runAt"]) {
      if (previous[name] !== void 0 && descriptor[name] === void 0) {
        descriptor[name] = previous[name];
      }
    }
    if (previous.members === void 0) {
      return descriptor;
    }
    if (updates.members === void 0) {
      descriptor.members = previous.members;
      return descriptor;
    }
    const updatedMembers = {};
    for (const member of updates.members) {
      updatedMembers[member.name] = member;
    }
    const newMembers = Array();
    for (const member of previous.members) {
      const update = updatedMembers[member.name];
      if (update === void 0) {
        newMembers.push({
          ...member,
          isDisabled: true
        });
        continue;
      }
      newMembers.push(merge(member, update));
      delete updatedMembers[member.name];
    }
    newMembers.push(...Object.values(updatedMembers));
    descriptor.members = newMembers;
    return descriptor;
  }
  TestDescriptor2.merge = merge;
  function Filesystem(root) {
    const index = /* @__PURE__ */ new WeakMap();
    return {
      descriptor: root,
      resolve(...segments) {
        let result = "/";
        for (const segment of segments) {
          if (segment.startsWith("/")) {
            result = segment;
            continue;
          }
          if (result[result.length - 1] !== "/") {
            result = `${result}/${segment}`;
            continue;
          }
          result = `${result}${segment}`;
        }
        return result;
      },
      readdir(path) {
        return this.stat(path)?.descriptor.members?.map((m) => m.name);
      },
      stat(path) {
        const segments = path.split("/");
        const breadcrumb = [root];
        for (const segment of segments) {
          if (segment === "." || segment === "") {
            continue;
          }
          if (segment === "..") {
            if (breadcrumb.length > 1) {
              breadcrumb.pop();
            }
            continue;
          }
          const descriptor2 = memberOf(breadcrumb[breadcrumb.length - 1], segment);
          if (!descriptor2) {
            return;
          }
          breadcrumb.push(descriptor2);
        }
        const descriptor = breadcrumb[breadcrumb.length - 1];
        const isSuite = descriptor.kind === "suite";
        return {
          isDirectory: isSuite,
          isFile: !isSuite && descriptor.path !== void 0,
          descriptor
        };
      }
    };
    function memberOf(descriptor, name) {
      const { members } = descriptor;
      if (!members?.length) {
        return;
      }
      let slot = index.get(descriptor);
      if (!slot) {
        slot = {};
        for (const member of members) {
          const existing = slot[member.name];
          if (existing !== void 0) {
            switch (existing.kind) {
              case "suite":
                continue;
              case "js":
                if (member.kind === "suite") {
                  continue;
                }
                break;
              case "py":
                if (member.kind === "suite" || member.kind !== "js") {
                  continue;
                }
                break;
              case "yaml":
                if (member.kind === "suite" || member.kind === "js" || member.kind === "py") {
                  continue;
                }
                break;
              case member.kind:
                continue;
            }
          }
          slot[member.name] = member;
        }
        index.set(descriptor, slot);
      }
      return slot[name];
    }
  }
  TestDescriptor2.Filesystem = Filesystem;
})(TestDescriptor || (TestDescriptor = {}));
export {
  TestDescriptor
};
//# sourceMappingURL=test-descriptor.js.map
