///|
fn stats_block(stats : GerberStatistics) -> String {
  "Statistics\n" +
  "----------\n" +
  "Apertures: " +
  stats.apertures.to_string() +
  "\n" +
  "Aperture macros: " +
  stats.aperture_macros.to_string() +
  "\n" +
  "Moves: " +
  stats.moves.to_string() +
  "\n" +
  "Draws: " +
  stats.draws.to_string() +
  "\n" +
  "Flashes: " +
  stats.flashes.to_string() +
  "\n" +
  "Regions: " +
  stats.regions.to_string() +
  "\n" +
  "Arc draws: " +
  stats.arc_draws.to_string() +
  "\n" +
  "Comments: " +
  stats.comments.to_string() +
  "\n" +
  "Attributes: " +
  stats.attributes.to_string() +
  "\n" +
  "Unknown commands: " +
  stats.unknown_commands.to_string()
}

///|
fn option_text(s : String?) -> String {
  match s {
    Some(v) => v
    None => "-"
  }
}

///|
fn unit_display(unit : GerberUnit?) -> String {
  match unit {
    Some(u) => unit_text(u)
    None => "-"
  }
}

///|
fn format_display(fmt : CoordinateFormat?) -> String {
  match fmt {
    Some(f) => f.integer_digits.to_string() + "." + f.decimal_digits.to_string()
    None => "-"
  }
}

///|
fn format_issue_line(issue : Issue) -> String {
  let sev = match issue.severity {
    Error => "ERROR"
    Warning => "WARNING"
  }
  match issue.line {
    Some(line) =>
      sev +
      " " +
      issue.code +
      " line " +
      line.to_string() +
      ": " +
      issue.message
    None => sev + " " + issue.code + ": " + issue.message
  }
}

///|
pub fn render_inspect(report : GerberReport, file_name : String) -> String {
  let buf = StringBuilder::new()
  buf.write_string("GerberGuard " + VERSION + "\n\n")
  buf.write_string("File: " + file_name + "\n")
  buf.write_string("Format: Gerber Layer Format (supported subset)\n\n")
  buf.write_string("Unit: " + unit_display(report.unit) + "\n")
  buf.write_string(
    "Coordinate format: " + format_display(report.coordinate_format) + "\n",
  )
  buf.write_string("File function: " + option_text(report.file_function) + "\n")
  buf.write_string("File polarity: " + option_text(report.file_polarity) + "\n")
  buf.write_string(
    "Generation software: " + option_text(report.generation_software) + "\n\n",
  )
  buf.write_string(stats_block(report.statistics) + "\n\n")
  if report.issues.length() > 0 {
    buf.write_string("Issues\n------\n")
    let limit = if report.issues.length() < 5 {
      report.issues.length()
    } else {
      5
    }
    let mut i = 0
    while i < limit {
      buf.write_string(format_issue_line(report.issues[i]) + "\n")
      i = i + 1
    }
    if report.issues.length() > 5 {
      let more = report.issues.length() - 5
      buf.write_string("... and " + more.to_string() + " more issues.\n")
    }
    buf.write_string("\n")
  }
  buf.write_string("Result: " + status_text(report.status) + "\n")
  buf.write_string("Errors: " + count_errors(report.issues).to_string() + "\n")
  buf.write_string(
    "Warnings: " + count_warnings(report.issues).to_string() + "\n",
  )
  buf.to_string()
}

///|
pub fn render_check(report : GerberReport, file_name : String) -> String {
  let _ = file_name
  let buf = StringBuilder::new()
  buf.write_string("GerberGuard " + VERSION + "\n\n")
  if report.issues.length() > 0 {
    let mut i = 0
    while i < report.issues.length() {
      let issue = report.issues[i]
      let sev = match issue.severity {
        Error => "ERROR"
        Warning => "WARNING"
      }
      match issue.line {
        Some(ln) => {
          buf.write_string(
            sev + " " + issue.code + " line " + ln.to_string() + "\n",
          )
          buf.write_string(issue.message + "\n\n")
        }
        None => {
          buf.write_string(sev + " " + issue.code + "\n")
          buf.write_string(issue.message + "\n\n")
        }
      }
      i = i + 1
    }
  }
  buf.write_string("Result: " + status_text(report.status) + "\n")
  buf.write_string("Errors: " + count_errors(report.issues).to_string() + "\n")
  buf.write_string(
    "Warnings: " + count_warnings(report.issues).to_string() + "\n",
  )
  buf.to_string()
}