// src/trace/execution-tracks.ts
function executionTrackByLane(lanes) {
  const unique = /* @__PURE__ */ new Map();
  for (const lane of lanes) {
    const existing = unique.get(lane.key);
    if (existing && !sameLane(existing, lane)) {
      throw new Error(`execution lane '${lane.key}' has conflicting scope or timing`);
    }
    unique.set(lane.key, lane);
  }
  const trackByLane = /* @__PURE__ */ new Map();
  const lanesByScope = /* @__PURE__ */ new Map();
  for (const lane of unique.values()) {
    const scoped = lanesByScope.get(lane.scopeKey) ?? [];
    scoped.push(lane);
    lanesByScope.set(lane.scopeKey, scoped);
  }
  for (const [scopeKey, scoped] of lanesByScope) {
    if (scoped.some((lane) => lane.start === null && lane.end === null)) {
      for (const lane of scoped) trackByLane.set(lane.key, trackId("lane", lane.key));
      continue;
    }
    const incompleteKeys = /* @__PURE__ */ new Set();
    const boundarySet = /* @__PURE__ */ new Set();
    for (const lane of scoped) {
      if (lane.start !== null && lane.end !== null && lane.end > lane.start) continue;
      incompleteKeys.add(lane.key);
      const boundary = lane.start ?? lane.end;
      if (boundary !== null) boundarySet.add(boundary);
      trackByLane.set(lane.key, trackId("lane", lane.key));
    }
    const boundaries = [...boundarySet].sort((a, b) => a - b);
    const completeBySegment = /* @__PURE__ */ new Map();
    for (const lane of scoped) {
      if (incompleteKeys.has(lane.key)) continue;
      const segment = upperBound(boundaries, lane.start);
      const nextBoundary = boundaries[segment];
      if (nextBoundary !== void 0 && nextBoundary < lane.end) {
        trackByLane.set(lane.key, trackId("lane", lane.key));
        continue;
      }
      const complete = completeBySegment.get(segment) ?? [];
      complete.push(lane);
      completeBySegment.set(segment, complete);
    }
    let serialTrack = 0;
    for (const [, segment] of [...completeBySegment].sort(([a], [b]) => a - b)) {
      const ordered = [...segment].sort(
        (a, b) => a.start - b.start || a.end - b.end || a.key.localeCompare(b.key)
      );
      let component = [];
      let componentEnd = Number.NEGATIVE_INFINITY;
      const flush = () => {
        if (component.length === 1) {
          trackByLane.set(component[0].key, trackId("serial", scopeKey, serialTrack));
        } else if (component.length > 1) {
          for (const lane of component) trackByLane.set(lane.key, trackId("lane", lane.key));
          serialTrack += 1;
        }
        component = [];
        componentEnd = Number.NEGATIVE_INFINITY;
      };
      for (const lane of ordered) {
        if (component.length > 0 && lane.start >= componentEnd) flush();
        component.push(lane);
        componentEnd = Math.max(componentEnd, lane.end);
      }
      flush();
      serialTrack += 1;
    }
  }
  return trackByLane;
}
function sameLane(a, b) {
  return a.scopeKey === b.scopeKey && a.start === b.start && a.end === b.end;
}
function trackId(kind, key, index) {
  return JSON.stringify(index === void 0 ? [kind, key] : [kind, key, index]);
}
function upperBound(sorted, target) {
  let low = 0;
  let high = sorted.length;
  while (low < high) {
    const middle = low + high >>> 1;
    if (sorted[middle] <= target) low = middle + 1;
    else high = middle;
  }
  return low;
}

export {
  executionTrackByLane
};
//# sourceMappingURL=chunk-HHWE3POT.js.map