// Data-import DOMAIN — path helpers for the §5 mapping engine. Pure. A "folder" is the task
// boundary for series/frame/study grouping (MAP1), so the engine reasons about relativePath
// segments here.

import { extensionOf } from '../formats';

/** Directory part of a relative path. `study1/series1/img.dcm` -> `study1/series1`; `img.dcm` -> ``. */
export function dirOf(relativePath: string): string {
  const i = relativePath.lastIndexOf('/');
  return i >= 0 ? relativePath.slice(0, i) : '';
}

/** First path segment (the "study" root). `study1/series1/img.dcm` -> `study1`; `img.dcm` -> ``. */
export function topDirOf(relativePath: string): string {
  const i = relativePath.indexOf('/');
  return i >= 0 ? relativePath.slice(0, i) : '';
}

/** Last path segment. `study1/series1` -> `series1`; `img.dcm` -> `img.dcm`. */
export function basename(p: string): string {
  return p.slice(p.lastIndexOf('/') + 1);
}

/** File name without its (double-extension-aware) extension. `brain.nii.gz` -> `brain`. */
export function stripExtension(name: string): string {
  const base = basename(name);
  const ext = extensionOf(base);
  return ext ? base.slice(0, base.length - ext.length) : base;
}

/**
 * Deterministic filename ordering (MAP2) — natural/numeric so `img2` precedes `img10`.
 * Used to order video frames and series instances by filename.
 */
export function compareByFilename(a: string, b: string): number {
  return a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' });
}

/** Group items by a string key, preserving first-seen order within each group. */
export function groupBy<T>(items: readonly T[], key: (t: T) => string): Map<string, T[]> {
  const out = new Map<string, T[]>();
  for (const item of items) {
    const k = key(item);
    const bucket = out.get(k);
    if (bucket) bucket.push(item);
    else out.set(k, [item]);
  }
  return out;
}
