///|
priv struct RmOptions {
  recursive : Bool
  force : Bool
  empty_directories : Bool
  verbose : Bool
}

///|
async fn main {
  let args = @env.args()[1:]
  let parsed = @cli.parse(args, [
    @cli.flag("recursive", short='r'),
    @cli.flag("recursive", short='R'),
    @cli.flag("force", short='f'),
    @cli.flag("dir", short='d'),
    @cli.flag("verbose", short='v'),
    @cli.flag("preserve-root"),
    @cli.flag("no-preserve-root"),
    @cli.flag("help"),
  ]) catch {
    @cli.CliError(option~, message~, ..) => {
      @stdio.stderr.write("rm: \{message}: '\{option}'\n")
      @sys.exit(2)
      return
    }
  }
  if parsed.contains("help") {
    @stdio.stdout.write("Usage: rm [-f] [-r|-R] [-d] [-v] FILE...\n")
    return
  }
  if parsed.contains("no-preserve-root") {
    @stdio.stderr.write(
      "rm: --no-preserve-root is disabled by repository policy\n",
    )
    @sys.exit(1)
    return
  }
  let options : RmOptions = {
    recursive: parsed.contains("recursive"),
    force: parsed.contains("force"),
    empty_directories: parsed.contains("dir"),
    verbose: parsed.contains("verbose"),
  }
  let paths = parsed.operands
  if paths.is_empty() {
    if options.force {
      return
    }
    @stdio.stderr.write("rm: missing operand\n")
    @sys.exit(1)
    return
  }
  let mut failed = false
  for path in paths {
    if @fsops.protects_working_directory(path) {
      @stdio.stderr.write("rm: refusing to remove protected path '\{path}'\n")
      failed = true
      continue
    }
    let kind = @fsops.kind_if_exists(path) catch {
      err => {
        @stdio.stderr.write("rm: cannot inspect '\{path}': \{err}\n")
        failed = true
        continue
      }
    }
    match kind {
      None if options.force => continue
      None => {
        @stdio.stderr.write("rm: cannot remove '\{path}': no such file\n")
        failed = true
        continue
      }
      Some(Directory) if options.recursive =>
        @fsops.remove_path(path, true) catch {
          @fsops.FsOpError(message) => {
            @stdio.stderr.write("rm: cannot remove '\{path}': \{message}\n")
            failed = true
            continue
          }
          err => {
            @stdio.stderr.write("rm: cannot remove '\{path}': \{err}\n")
            failed = true
            continue
          }
        }
      Some(Directory) if options.empty_directories =>
        @fs.rmdir(path) catch {
          err => {
            @stdio.stderr.write("rm: cannot remove '\{path}': \{err}\n")
            failed = true
            continue
          }
        }
      Some(Directory) => {
        @stdio.stderr.write("rm: cannot remove '\{path}': is a directory\n")
        failed = true
        continue
      }
      Some(_) =>
        @fsops.remove_path(path, false) catch {
          @fsops.FsOpError(message) => {
            @stdio.stderr.write("rm: cannot remove '\{path}': \{message}\n")
            failed = true
            continue
          }
          err => {
            @stdio.stderr.write("rm: cannot remove '\{path}': \{err}\n")
            failed = true
            continue
          }
        }
    }
    if options.verbose {
      @stdio.stdout.write("removed '\{path}'\n")
    }
  }
  if failed {
    @sys.exit(1)
  }
}