///|
pub fn SemanticIndex::validation_summary(
  self : SemanticIndex,
) -> ValidationSummary {
  self.validate()
}

///|
pub fn ValidationSummary::has_blocking_issues(self : ValidationSummary) -> Bool {
  self.duplicate_modules > 0 ||
  self.unresolved_instances > 0 ||
  self.width_mismatches > 0
}

///|
pub fn ValidationSummary::total_findings(self : ValidationSummary) -> Int {
  self.total()
}

///|
pub fn ValidationSummary::summary(self : ValidationSummary) -> String {
  "blocking=" +
  self.has_blocking_issues().to_string() +
  ", findings=" +
  self.total().to_string() +
  ", unresolved=" +
  self.unresolved_instances.to_string() +
  ", width_mismatches=" +
  self.width_mismatches.to_string()
}

///|
pub fn SemanticIndex::release_ready(self : SemanticIndex) -> Bool {
  self.validate().is_clean()
}

///|
pub fn SemanticIndex::module_is_leaf(
  self : SemanticIndex,
  module_name : String,
) -> Bool {
  self.children_of(module_name).length() == 0
}

///|
pub fn SemanticIndex::module_is_root(
  self : SemanticIndex,
  module_name : String,
) -> Bool {
  self.hierarchy_roots().contains(module_name)
}

///|
pub fn SemanticIndex::isolated_modules(self : SemanticIndex) -> Array[String] {
  let result : Array[String] = []
  for mod in self.modules {
    if self.module_is_leaf(mod.name) &&
      self.reverse_dependencies(mod.name).length() == 0 {
      result.push(mod.name)
    }
  }
  result
}

///|
pub fn SemanticIndex::top_level_modules(self : SemanticIndex) -> Array[String] {
  self
  .hierarchy_roots()
  .filter(fn(name) { self.children_of(name).length() > 0 })
}

///|
pub fn SemanticIndex::blocking_issue_count(self : SemanticIndex) -> Int {
  self.issues_for_code("RTL101").length() +
  self.issues_for_code("RTL102").length() +
  self.issues_for_code("RTL202").length() +
  self.contract_status_count(WidthMismatch)
}

///|
pub fn SemanticIndex::warning_issue_count(self : SemanticIndex) -> Int {
  self.issues.length() - self.blocking_issue_count()
}

///|
pub fn SemanticIndex::validation_report(self : SemanticIndex) -> String {
  let summary = self.validate()
  summary.describe() +
  ", contracts=" +
  self.port_contracts().length().to_string() +
  ", blocking_issues=" +
  self.blocking_issue_count().to_string()
}