///|
/// Normalize separators and remove redundant `.` path segments.
pub fn normalize_path(path : String) -> String {
  let replaced = StringBuilder::new()
  for ch in path {
    if ch == '\\' {
      replaced.write_char('/')
    } else {
      replaced.write_char(ch)
    }
  }
  let text = replaced.to_string()
  let absolute = text.has_prefix("/")
  let segments : Array[String] = []
  for part in text.split("/") {
    let segment = part.to_owned()
    if segment == "" || segment == "." {
      continue
    }
    if segment == ".." {
      if segments.length() > 0 && segments[segments.length() - 1] != ".." {
        ignore(segments.pop())
      } else if !absolute {
        segments.push(segment)
      }
    } else {
      segments.push(segment)
    }
  }
  let joined = segments.join("/")
  if absolute {
    "/" + joined
  } else {
    joined
  }
}

///|
pub fn parent_path(path : String) -> String? {
  let normalized = normalize_path(path)
  match last_separator(normalized) {
    None => None
    Some(0) => Some("/")
    Some(index) => Some(normalized[:index].to_owned())
  }
}

///|
pub fn relative_path(base : String, target : String) -> String? {
  let normalized_base = normalize_path(base)
  let normalized_target = normalize_path(target)
  if normalized_base == "" {
    return Some(normalized_target)
  }
  if normalized_target == normalized_base {
    return Some("")
  }
  let prefix = if normalized_base.has_suffix("/") {
    normalized_base
  } else {
    normalized_base + "/"
  }
  if normalized_target.has_prefix(prefix) {
    Some(normalized_target[prefix.length():].to_owned())
  } else {
    None
  }
}

///|
fn basename(path : String) -> String {
  let normalized = normalize_path(path)
  match last_separator(normalized) {
    Some(index) => normalized[index + 1:].to_owned()
    None => normalized
  }
}

///|
fn last_separator(path : String) -> Int? {
  for index = path.length(); index > 0; index = index - 1 {
    if path[index - 1] == '/' {
      return Some(index - 1)
    }
  }
  None
}

///|
fn path_depth(path : String) -> Int {
  let normalized = normalize_path(path)
  if normalized == "" {
    0
  } else {
    normalized.split("/").length()
  }
}