///|
fn command_arguments(args : Array[String]) -> Array[String] {
  let output : Array[String] = []
  for index in 1.. String raise @lib.MessageError {
  match request.path(index) {
    Some(path) => path
    None => raise @lib.InvalidCommand("Missing catalog path.")
  }
}

///|
fn required_locale(request : @lib.CliRequest, fallback : String) -> String {
  match request.locale() {
    Some(locale) => locale
    None => fallback
  }
}

///|
fn required_key(request : @lib.CliRequest) -> String raise @lib.MessageError {
  match request.key() {
    Some(key) => key
    None => raise @lib.InvalidCommand("Missing message key.")
  }
}

///|
fn execute_request(request : @lib.CliRequest) -> @lib.CliOutput raise {
  match request.kind() {
    @lib.Help =>
      @lib.CliOutput::{ exit_code: 0, stdout: @lib.cli_usage(), stderr: "" }
    @lib.Validate => {
      let reference_path = required_path(request, 0)
      let translation_path = required_path(request, 1)
      @lib.cli_validate_sources(
        @fs.read_file_to_string(reference_path),
        @fs.read_file_to_string(translation_path),
        required_locale(request, "translation"),
        json=request.json(),
      )
    }
    @lib.Diff => {
      let reference_path = required_path(request, 0)
      let translation_path = required_path(request, 1)
      @lib.cli_diff_sources(
        @fs.read_file_to_string(reference_path),
        @fs.read_file_to_string(translation_path),
        required_locale(request, "translation"),
        json=request.json(),
      )
    }
    @lib.Render => {
      let catalog_path = required_path(request, 0)
      let locale = required_locale(request, "en")
      @lib.cli_render_source(
        @fs.read_file_to_string(catalog_path),
        locale,
        required_key(request),
        request.arguments(),
        json=request.json(),
      )
    }
  }
}

///|
fn emit_output(output : @lib.CliOutput) -> Unit {
  if output.stdout() != "" {
    println(output.stdout())
  }
  if output.stderr() != "" {
    println(output.stderr())
  }
}

///|
fn main {
  try {
    let request = @lib.parse_cli_request(command_arguments(@env.args()))
    let output = execute_request(request)
    emit_output(output)
    if output.exit_code() != 0 {
      @sys.exit(output.exit_code())
    }
  } catch {
    error => {
      println("error: \{error}")
      @sys.exit(2)
    }
  } noraise {
    _ => ()
  }
}