"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 chip_exports = {};
__export(chip_exports, {
  chip: () => chip
});
module.exports = __toCommonJS(chip_exports);
var import_js_tools = require("@nacho-iot/js-tools");
var import_mocha = require("../mocha.js");
var import_nodejs = require("../nodejs.js");
var import_test_descriptor = require("../test-descriptor.js");
var import_state = require("./state.js");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
function createBuilder(initial) {
  const implementations = /* @__PURE__ */ new Map();
  let subject;
  let startCommissioned = true;
  let only = false;
  const beforeStartHooks = Array();
  const beforeTestHooks = Array();
  const args = Array();
  const builder = {
    include(...glob) {
      const includePaths = /* @__PURE__ */ new Set();
      for (const pattern of glob) {
        const paths = (0, import_js_tools.globSync)(pattern, chip.tests);
        if (!paths.length) {
          throw new Error(`No tests included for glob ${pattern}`);
        }
        for (const path of paths) {
          includePaths.add(path);
        }
      }
      const tests = import_test_descriptor.TestDescriptor.filter(chip.tests.descriptor, {
        includePaths: [...includePaths],
        kinds: ["py", "yaml"],
        pics: subject?.pics ?? chip.defaultPics
      });
      if (!tests?.members) {
        return this;
      }
      for (const member of tests.members) {
        defineTests(member);
      }
      return this;
    },
    exclude(...glob) {
      const tests = import_test_descriptor.TestDescriptor.filter(chip.tests.descriptor, { includePaths: (0, import_js_tools.globSync)(glob, chip.tests) });
      if (!tests) {
        return this;
      }
      import_test_descriptor.TestDescriptor.visit(tests, (descriptor) => {
        const impl = implementations.get(descriptor);
        if (!impl) {
          return;
        }
        implementations.delete(descriptor);
        if (!impl?.parent) {
          return;
        }
        const pos = impl.parent.tests.indexOf(impl);
        if (pos !== -1) {
          impl.parent.tests.splice(pos, 1);
        }
      });
      return this;
    },
    subject(newSubject) {
      subject = newSubject;
      return this;
    },
    beforeStart(hook) {
      beforeStartHooks.push(hook);
      return this;
    },
    beforeTest(hook) {
      beforeTestHooks.push(hook);
      return this;
    },
    args(...newArgs) {
      args.push(...newArgs.map((arg) => `${arg}`));
      return this;
    },
    uncommissioned() {
      startCommissioned = false;
      return this;
    },
    only() {
      only = true;
      return this;
    }
  };
  for (const key in initial) {
    const fn = builder[key];
    if (typeof fn === "function") {
      const arg = initial[key];
      if (Array.isArray(arg)) {
        fn(...arg);
      } else {
        fn(arg);
      }
    }
  }
  return builder;
  function defineTests(descriptor) {
    switch (descriptor.kind) {
      case "suite":
        defineSuite(descriptor);
        break;
      default:
        defineTest(descriptor);
        break;
    }
  }
  function defineSuite(descriptor) {
    const mocha = (0, import_nodejs.getCurrentNodejsMocha)();
    const { name, members } = descriptor;
    if (!members?.length) {
      return;
    }
    if (descriptor.name === mocha.suite.title) {
      for (const member of members) {
        defineTests(member);
      }
      return;
    }
    for (const suite of mocha.suite.suites) {
      if (suite.title === name) {
        const revertSuite = mocha.suite;
        try {
          mocha.suite = suite;
          for (const member of members) {
            defineTests(member);
          }
        } finally {
          mocha.suite = revertSuite;
        }
        return;
      }
    }
    describe(name, () => {
      for (const member of members) {
        defineTests(member);
      }
    });
  }
  function defineTest(descriptor) {
    import_state.State.install();
    const test = chip.testFor(descriptor);
    const myIt = only ? it.only : it;
    const mochaTest = myIt(descriptor.name, function() {
      this.timeout(descriptor.timeoutMs ?? chip.defaultTimeoutMs);
      return import_state.State.run(test, args, (subject2, test2) => runBeforeHooks(beforeTestHooks, subject2, test2));
    });
    (0, import_mocha.beforeOne)(mochaTest, async function() {
      let factory = subject;
      let appArgs;
      if (factory === void 0 && descriptor.app !== void 0) {
        factory = import_state.State.subjectForApp(descriptor.app);
        if (factory === void 0) {
          this.skip();
        }
        appArgs = parseAppArgs(descriptor);
      }
      if (factory === void 0) {
        factory = import_state.State.subject;
      }
      await import_state.State.activateSubject(
        factory,
        startCommissioned,
        test,
        (subject2, test2) => runBeforeHooks(beforeStartHooks, subject2, test2),
        appArgs
      );
    });
    mochaTest.descriptor = test.descriptor;
    implementations.set(descriptor, mochaTest);
    (0, import_mocha.afterOne)(mochaTest, import_state.State.deactivateSubject);
  }
}
function parseAppArgs(descriptor) {
  const raw = descriptor.config?.["app-args"];
  if (raw === void 0) return void 0;
  if (Array.isArray(raw)) return raw.map(String);
  if (typeof raw === "string") {
    const trimmed = raw.trim();
    return trimmed === "" ? void 0 : trimmed.split(/\s+/);
  }
  return void 0;
}
function chipFn(subjectOrFirstInclusion, ...include) {
  if (typeof subjectOrFirstInclusion === "function") {
    return chip().subject(subjectOrFirstInclusion).include(...include);
  }
  if (typeof subjectOrFirstInclusion === "string") {
    include = [subjectOrFirstInclusion, ...include];
  }
  return createBuilder({ include: [...include] });
}
Object.defineProperties(chipFn, {
  defaultSubject: {
    set(subject) {
      import_state.State.subject = subject;
    }
  },
  subjectFor: {
    value: (app, factory) => {
      import_state.State.registerSubjectForApp(app, factory);
    }
  },
  activeTest: {
    get: () => import_state.State.test
  },
  container: {
    get: () => import_state.State.container
  },
  tests: {
    get: () => import_state.State.tests
  },
  isInitialized: {
    get: () => import_state.State.isInitialized
  },
  defaultPics: {
    get: () => import_state.State.defaultPics
  },
  defaultPicsFilename: {
    get: () => import_state.State.defaultPicsFilename
  },
  pullBeforeTesting: {
    get() {
      return import_state.State.pullBeforeTesting;
    },
    set(value) {
      import_state.State.pullBeforeTesting = value;
    }
  },
  initialize: { value: import_state.State.initialize.bind(import_state.State) },
  close: { value: import_state.State.close.bind(import_state.State) },
  openPipe: { value: import_state.State.openPipe.bind(import_state.State) },
  onClose: { value: import_state.State.onClose.bind(import_state.State) },
  testFor: { value: import_state.State.testFor.bind(import_state.State) },
  clearMdns: { value: import_state.State.clearMdns.bind(import_state.State) }
});
const chip = chipFn;
chip.defaultTimeoutMs = 30 * 60 * 1e3;
function runBeforeHooks(hooks, ...args) {
  const promises = new Array();
  for (const hook of hooks) {
    const promise = hook(...args);
    if (promise) {
      promises.push(promise);
    }
  }
  if (promises) {
    return Promise.all(promises).then(() => {
    });
  }
}
//# sourceMappingURL=chip.js.map
