///|
fn option_value(args : Array[String], name : String) -> String? {
  for i = 0; i < args.length(); i = i + 1 {
    if args[i] == name && i + 1 < args.length() {
      return Some(args[i + 1])
    }
  }
  None
}

///|
fn option_values(args : Array[String], name : String) -> Array[String] {
  let values : Array[String] = []
  for i = 0; i < args.length(); i = i + 1 {
    if args[i] == name && i + 1 < args.length() {
      values.push(args[i + 1])
    }
  }
  values
}

///|
fn has_flag(args : Array[String], name : String) -> Bool {
  for value in args {
    if value == name {
      return true
    }
  }
  false
}

///|
fn positional(args : Array[String]) -> String? {
  for value in args {
    if !value.has_prefix("-") {
      return Some(value)
    }
  }
  None
}

///|
fn input_value(args : Array[String]) -> String {
  match option_value(args, "--input") {
    Some(value) => value
    None =>
      match positional(args) {
        Some(value) => value
        None => ""
      }
  }
}

///|
fn parse_int_text(value : String) -> Int? {
  Some(@string.parse_int(value)) catch {
    _ => None
  }
}

///|
fn q(value : String) -> String {
  Json::string(value).stringify()
}

///|
fn print_cli_error(kind : String, message : String) -> Unit {
  println(
    "{\"ok\":false,\"error\":{\"kind\":\{q(kind)},\"message\":\{q(message)}}}",
  )
}

///|
fn print_problem_error(error : @problem.ProblemError) -> Unit {
  print_cli_error(error.kind().name(), error.context())
}