///|
fn has_arg(args : Array[String], wanted : String) -> Bool {
  args.contains(wanted)
}

///|
fn value_after(args : Array[String], wanted : String) -> String? {
  for i, arg in args {
    if arg == wanted && i + 1 < args.length() {
      return Some(args[i + 1])
    }
    if arg.has_prefix(wanted + "=") {
      return Some(arg[wanted.length() + 1:].to_owned())
    }
  }
  None
}

///|
fn demo_source() -> String {
  (
    #|module demo (
    #|  input  [7:0] a,
    #|  input  [7:0] b,
    #|  output [7:0] y
    #|);
    #|  wire [7:0] sum;
    #|  assign sum = a + b;
    #|  assign y = sum;
    #|endmodule
  )
}

///|
fn read_source(args : Array[String]) -> String {
  match value_after(args, "--benchmark-fixture") {
    Some(size) => @rtl.benchmark_fixture_source(size)
    None =>
      match value_after(args, "--file") {
        Some(path) =>
          @fs.read_file_to_string(path) catch {
            error => {
              ignore(error)
              println("moonbit-rtl: cannot read " + path)
              ""
            }
          }
        None => demo_source()
      }
  }
}

///|
fn config_from_args(args : Array[String]) -> @rtl.CheckConfig {
  let mut config = @rtl.CheckConfig::default()
  if has_arg(args, "--no-info") {
    config = config.without_info()
  }
  match value_after(args, "--max-diagnostics") {
    Some(value) => {
      let mut max = 0
      for c in value.to_array() {
        if c >= '0' && c <= '9' {
          max = max * 10 + c.to_int() - '0'.to_int()
        }
      }
      if max > 0 {
        config = config.with_max_diagnostics(max)
      }
    }
    None => ()
  }
  for arg in args {
    if arg.has_prefix("--disable=") {
      let code = arg[10:].to_owned()
      config = config.without(code)
    }
  }
  config
}

///|
fn run_benchmark(source : String, rounds : Int) -> Unit {
  let count = if rounds < 1 { 1 } else { rounds }
  let started = @env.now()
  let mut token_count = 0
  let mut diagnostic_count = 0
  for _ in 0..= '0' && c <= '9' {
        rounds = rounds * 10 + c.to_int() - '0'.to_int()
      }
    }
    run_benchmark(source, if rounds < 1 { 100 } else { rounds })
    return
  }
  let config = config_from_args(args)
  let parse_items = @rtl.parse_diagnostics(source)
  let semantic_items = @rtl.check_source_with_config(source, config)
  let diagnostics : Array[@rtl.Diagnostic] = []
  for item in parse_items {
    diagnostics.push(item)
  }
  for item in semantic_items {
    diagnostics.push(item)
  }
  if has_arg(args, "--json") {
    println(@rtl.diagnostics_json(diagnostics))
  } else if has_arg(args, "--sarif") {
    println(@rtl.diagnostics_sarif(diagnostics))
  } else if has_arg(args, "--markdown") {
    println(@rtl.diagnostics_markdown(diagnostics))
  } else if has_arg(args, "--summary") {
    println(@rtl.diagnostics_summary(diagnostics))
    println("rules=" + @rtl.diagnostic_rule_ids(diagnostics).join(","))
  } else {
    println(
      "moonbit-rtl: modules=" + @rtl.parse(source).modules.length().to_string(),
    )
    if diagnostics.length() == 0 {
      println("no diagnostics")
    } else {
      println(@rtl.diagnostics_text(diagnostics))
    }
  }
}