const ROOT = "linuxcnc";

function assertSegment(segment, label = "path segment") {
  if (typeof segment !== "string" || segment.length === 0) {
    throw new Error(`${label} must be a non-empty string.`);
  }
  if (
    segment === "." ||
    segment === ".." ||
    segment.includes("/") ||
    segment.includes("\\") ||
    segment.includes("\0")
  ) {
    throw new Error(`Invalid ${label}: ${segment}`);
  }
  return segment;
}

export function splitOpfsPath(path) {
  if (typeof path !== "string" || path.length === 0) {
    throw new Error("OPFS path must be a non-empty relative path.");
  }
  if (path.startsWith("/") || path.includes("//")) {
    throw new Error(`Invalid OPFS path: ${path}`);
  }

  const parts = path.split("/");
  if (parts.some((part) => part === "." || part === ".." || part === "")) {
    throw new Error(`Invalid OPFS path: ${path}`);
  }
  return parts;
}

export function normalizeOpfsPath(path) {
  return splitOpfsPath(path).join("/");
}

export function opfsPath(...segments) {
  return segments.map((segment) => assertSegment(segment)).join("/");
}

export function machineRoot(machineId) {
  return opfsPath(ROOT, "machines", assertSegment(machineId, "machine id"));
}

export function machineIniPath(machineId, filename = "machine.ini") {
  return opfsPath(
    ROOT,
    "machines",
    assertSegment(machineId, "machine id"),
    assertSegment(filename, "INI filename"),
  );
}

export function toolTablePath(machineId, filename = "tool.tbl") {
  return opfsPath(
    ROOT,
    "machines",
    assertSegment(machineId, "machine id"),
    assertSegment(filename, "tool table filename"),
  );
}

export function parameterFilePath(machineId, filename = "linuxcnc.var") {
  return opfsPath(
    ROOT,
    "machines",
    assertSegment(machineId, "machine id"),
    assertSegment(filename, "parameter filename"),
  );
}

export function gcodeProgramPath(filename) {
  return opfsPath(ROOT, "gcode", assertSegment(filename, "G-code filename"));
}

export function previewCachePath(cacheKey, filename = "preview.json") {
  return opfsPath(
    ROOT,
    "preview-cache",
    assertSegment(cacheKey, "preview cache key"),
    assertSegment(filename, "preview cache filename"),
  );
}

export function sessionSnapshotPath(sessionId, filename = "snapshot.json") {
  return opfsPath(
    ROOT,
    "sessions",
    assertSegment(sessionId, "session id"),
    assertSegment(filename, "session snapshot filename"),
  );
}

export function defaultMachinePaths(machineId) {
  return {
    ini: machineIniPath(machineId),
    toolTable: toolTablePath(machineId),
    parameters: parameterFilePath(machineId),
  };
}
