///|
/// Output formats exposed by the native command line interface.
pub(all) enum CliFormat {
  Text
  Json
  Sarif
} derive(Eq, Debug)

///|
/// Commands accepted by the native command line interface.
pub(all) enum CliCommand {
  Check
  Outline
  Graph
  Summary
  Ir
  Tokens
} derive(Eq, Debug)

///|
/// Parsed, validated command line options.
pub(all) struct CliOptions {
  command : CliCommand
  path : String
  format : CliFormat
} derive(Eq, Debug)

///|
/// Parse one command and source path from process arguments.
pub fn parse_options(args : Array[String]) -> CliOptions? {
  if args.length() < 3 {
    None
  } else {
    let command = match args[1] {
      "check" => Some(Check)
      "outline" => Some(Outline)
      "graph" => Some(Graph)
      "summary" => Some(Summary)
      "ir" => Some(Ir)
      "tokens" => Some(Tokens)
      _ => None
    }
    match command {
      Some(command) => {
        let mut format = Text
        for argument in args[3:] {
          match argument {
            "json" | "--format=json" => format = Json
            "sarif" | "--format=sarif" => format = Sarif
            _ => ()
          }
        }
        Some({ command, path: args[2], format })
      }
      None => None
    }
  }
}

///|
/// Return a stable usage string for help and error output.
pub fn options_usage() -> String {
  "moonbit-rtl   [--format text|json|sarif]"
}

///|
/// Return whether the command is a source-checking command.
pub fn CliCommand::checks_source(self : CliCommand) -> Bool {
  self is Check
}

///|
/// Return a stable format label for logs.
pub fn CliFormat::label(self : CliFormat) -> String {
  match self {
    Text => "text"
    Json => "json"
    Sarif => "sarif"
  }
}

///|
/// Return a compact option description for integration tests.
pub fn CliOptions::describe(self : CliOptions) -> String {
  let command = match self.command {
    Check => "check"
    Outline => "outline"
    Graph => "graph"
    Summary => "summary"
    Ir => "ir"
    Tokens => "tokens"
  }
  command + " " + self.path + " --format=" + self.format.label()
}