///|
fn usage() -> String {
  (
    #|FrontierLab 0.10.0 - HTML Trace Player
    #|  frontierlab diagnose   --contract  --object  --format  [--counterexample ] [--report ]
    #|  frontierlab demo  --format  --output 
    #|  frontierlab render  --format  --output  [--step N]
    #|  frontierlab analyze 
    #|  frontierlab validate 
    #|  frontierlab playground --output 
    #|  frontierlab diff  --from N --to N --format 
    #|  frontierlab breakpoints  [--event KIND] [--target OBJECT[/ENTITY]] [--role ROLE] [--changed-only] --format 
    #|  frontierlab verify  --contract  --object ID --format  [--counterexample PATH]
    #|  frontierlab diverge   --format  [--counterexample PATH]
    #|  frontierlab --version
    #|  Note: SVG output is legacy compatibility only and will be removed in v1.0; prefer HTML or JSON.
  )
}

///|
fn option(
  args : Array[String],
  name : String,
  default : String,
) -> String raise {
  match args.search_by(fn(value) { value == name }) {
    Some(index) if index + 1 < args.length() &&
      !args[index + 1].has_prefix("--") => args[index + 1]
    Some(_) => fail("\{name} requires a value")
    None => default
  }
}

///|
fn required_option(args : Array[String], name : String) -> String raise {
  let value = option(args, name, "")
  if value == "" {
    fail("\{name} is required")
  }
  value
}

///|
fn debug_format(args : Array[String]) -> String raise {
  let format = option(args, "--format", "text")
  if format != "text" && format != "json" {
    fail("Unknown debug report format: \{format}")
  }
  format
}

///|
fn parse_target(value : String) -> @frontierlab.TargetRef? raise {
  if value == "" {
    None
  } else {
    let parts = value.split("/").map(fn(part) { part.to_owned() }).collect()
    if parts.length() == 1 {
      Some(@frontierlab.TargetRef::object(parts[0]))
    } else if parts.length() == 2 && parts[0] != "" && parts[1] != "" {
      Some(@frontierlab.TargetRef::entity(parts[0], parts[1]))
    } else {
      fail("Target must be OBJECT or OBJECT/ENTITY")
    }
  }
}

///|
fn command_name(args : Array[String]) -> String {
  if args.length() > 1 {
    args[1]
  } else {
    "unknown"
  }
}