///|
/// Severity attached to a validation or planning diagnostic.
pub(all) enum DiagnosticSeverity {
  Info
  Warning
  Error
} derive(Eq, Debug)

///|
/// A stable diagnostic emitted at an input position.
pub(all) struct Diagnostic {
  code : String
  message : String
  index : Int
  severity : DiagnosticSeverity
}

///|
/// Create an error diagnostic with a stable code and input index.
pub fn error_diagnostic(
  code~ : String,
  message~ : String,
  index~ : Int,
) -> Diagnostic {
  { code, message, index, severity: DiagnosticSeverity::Error }
}

///|
/// Create a warning diagnostic with a stable code and input index.
pub fn warning_diagnostic(
  code~ : String,
  message~ : String,
  index~ : Int,
) -> Diagnostic {
  { code, message, index, severity: DiagnosticSeverity::Warning }
}

///|
/// Return whether any diagnostic is an error.
pub fn has_errors(diagnostics : Array[Diagnostic]) -> Bool {
  let mut result = false
  for diagnostic in diagnostics {
    if diagnostic.severity == DiagnosticSeverity::Error {
      result = true
    }
  }
  result
}

///|
/// Count diagnostics with the requested severity.
pub fn diagnostic_count(
  diagnostics : Array[Diagnostic],
  severity : DiagnosticSeverity,
) -> Int {
  let mut result = 0
  for diagnostic in diagnostics {
    if diagnostic.severity == severity {
      result += 1
    }
  }
  result
}