///|
pub struct QualityGate {
  passed : Bool
  blockers : Array[String]
  notices : Array[String]
} derive(Debug, Eq)

///|
pub fn quality_gate(report : ChemReport) -> QualityGate {
  let blockers : Array[String] = []
  let notices : Array[String] = []
  for issue in report.validate() {
    blockers.push(issue.path + ": " + issue.message)
  }
  for warning in report.warnings {
    if warning.severity is Critical {
      blockers.push("critical warning: " + warning.code)
    } else if warning.severity is Warning {
      notices.push("warning: " + warning.code)
    }
  }
  { passed: blockers.length() == 0, blockers, notices }
}

///|
pub fn ChemReport::without_critical_warnings(self : ChemReport) -> ChemReport {
  let warnings : Array[WarningNote] = []
  for warning in self.warnings {
    if warning.severity != Critical {
      warnings.push(warning)
    }
  }
  { ..self, warnings, }
}

///|
pub fn ChemReport::with_tag(self : ChemReport, tag : String) -> ChemReport {
  let tags = self.tags.copy()
  if !tags.contains(tag) {
    tags.push(tag)
  }
  { ..self, tags, }
}

///|
pub fn ChemReport::has_tag(self : ChemReport, tag : String) -> Bool {
  self.tags.contains(tag)
}

///|
pub fn ChemReport::warning_count(
  self : ChemReport,
  severity : WarningSeverity,
) -> Int {
  let mut count = 0
  for warning in self.warnings {
    if warning.severity == severity {
      count = count + 1
    }
  }
  count
}

///|
pub fn ChemReport::result_names(self : ChemReport) -> Array[String] {
  self.results.map(fn(item) { item.name })
}