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 ecs_exports = {};
__export(ecs_exports, {
  validateEcsConfig: () => validateEcsConfig
});
module.exports = __toCommonJS(ecs_exports);
function isPlainRecord(value) {
  return !!value && typeof value === "object" && !Array.isArray(value);
}
function assert(condition, message) {
  if (!condition) {
    throw new Error(message);
  }
}
function validateField(input, idx, componentName) {
  assert(isPlainRecord(input), `component "${componentName}" field[${idx}] must be an object`);
  const { name, type } = input;
  assert(typeof name === "string" && name.length > 0, `component "${componentName}" field[${idx}] must have a non-empty name`);
  assert(typeof type === "string" && ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "vec2", "vec3", "bytes"].includes(type), `component "${componentName}" field "${name}" has invalid type "${String(type)}"`);
  return { name, type };
}
function validateComponent(input, idx) {
  assert(isPlainRecord(input), `component[${idx}] must be an object`);
  const { id, name, kind, networked, input: isInput, fields } = input;
  assert(Number.isInteger(id) && id > 0, `component[${idx}] id must be a positive integer`);
  assert(typeof name === "string" && name.length > 0, `component[${idx}] must have a non-empty name`);
  assert(kind === "static" || kind === "versioned" || kind === "tick" || kind === "signal", `component "${name}" has invalid kind "${String(kind)}" (must be static, versioned, tick, or signal)`);
  assert(typeof networked === "boolean", `component "${name}" networked must be a boolean`);
  assert(typeof isInput === "boolean", `component "${name}" input must be a boolean`);
  assert(Array.isArray(fields), `component "${name}" fields must be an array`);
  const validatedFields = fields.map((field, fieldIdx) => validateField(field, fieldIdx, name));
  return {
    id,
    name,
    kind,
    networked,
    input: isInput,
    fields: validatedFields
  };
}
function validateSystemEntry(entry, listName, idx) {
  if (typeof entry === "string") {
    assert(entry.length > 0, `${listName}[${idx}] must not be an empty string`);
    return entry;
  }
  assert(isPlainRecord(entry), `${listName}[${idx}] must be a string or an object`);
  const { name, module: module2 } = entry;
  assert(typeof name === "string" && name.length > 0, `${listName}[${idx}] object must have a non-empty name`);
  assert(typeof module2 === "string" && module2.length > 0, `${listName}[${idx}] object must have a non-empty module`);
  return { name, module: module2 };
}
function validateSystems(systems) {
  assert(isPlainRecord(systems), "systems must be an object");
  const { serverStartup, serverSimulation, clientStartup, clientSimulation, clientPresentation } = systems;
  if (serverStartup !== void 0) {
    assert(Array.isArray(serverStartup), "systems.serverStartup must be an array");
  }
  assert(Array.isArray(serverSimulation), "systems.serverSimulation must be an array");
  if (clientStartup !== void 0) {
    assert(Array.isArray(clientStartup), "systems.clientStartup must be an array");
  }
  assert(Array.isArray(clientSimulation), "systems.clientSimulation must be an array");
  assert(Array.isArray(clientPresentation), "systems.clientPresentation must be an array");
  return {
    ...serverStartup ? {
      serverStartup: serverStartup.map((entry, idx) => validateSystemEntry(entry, "systems.serverStartup", idx))
    } : {},
    serverSimulation: serverSimulation.map((entry, idx) => validateSystemEntry(entry, "systems.serverSimulation", idx)),
    ...clientStartup ? {
      clientStartup: clientStartup.map((entry, idx) => validateSystemEntry(entry, "systems.clientStartup", idx))
    } : {},
    clientSimulation: clientSimulation.map((entry, idx) => validateSystemEntry(entry, "systems.clientSimulation", idx)),
    clientPresentation: clientPresentation.map((entry, idx) => validateSystemEntry(entry, "systems.clientPresentation", idx))
  };
}
function ensureUniqueComponents(components) {
  const ids = /* @__PURE__ */ new Set();
  const names = /* @__PURE__ */ new Set();
  for (const component of components) {
    assert(!ids.has(component.id), `duplicate component id ${component.id}`);
    ids.add(component.id);
    assert(!names.has(component.name), `duplicate component name "${component.name}"`);
    names.add(component.name);
  }
}
function validateEcsConfig(config) {
  assert(isPlainRecord(config), "config must be an object");
  const { components, systems } = config;
  assert(Array.isArray(components), "components must be an array");
  const validatedComponents = components.map((component, idx) => validateComponent(component, idx));
  ensureUniqueComponents(validatedComponents);
  const validatedSystems = validateSystems(systems);
  return {
    components: validatedComponents,
    systems: validatedSystems
  };
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  validateEcsConfig
});
