///|
pub(all) enum RequestAuditError {
  RequestLimit
  BindingLimit
  FindingLimit
}

///|
/// No values or expanded URIs are included in a request audit.
pub struct RequestAudit {
  index : Int32
  name : String
  unknown_template : Bool
  issues : Array[BindingIssue]
}

///|
pub fn RequestAudit::index(self : RequestAudit) -> Int32 {
  self.index
}

///|
pub fn RequestAudit::name(self : RequestAudit) -> String {
  self.name
}

///|
pub fn RequestAudit::unknown_template(self : RequestAudit) -> Bool {
  self.unknown_template
}

///|
pub fn RequestAudit::issues(self : RequestAudit) -> Array[BindingIssue] {
  self.issues.copy()
}

///|
/// Inspect every mixed request without stopping at the first unknown endpoint
/// or binding issue. Missing variables are informational under RFC 6570.
/// Limits apply to the complete input and result; failures return no partial audit.
pub fn TemplateCatalog::inspect_requests(
  self : TemplateCatalog,
  requests : Array[CatalogRequest],
  max_requests~ : Int32 = 4096,
  max_bindings~ : Int32 = 16384,
  max_findings~ : Int32 = 16384,
) -> Result[Array[RequestAudit], RequestAuditError] {
  if max_requests < 0 || requests.length() > max_requests {
    return Err(RequestLimit)
  }
  if max_bindings < 0 {
    return Err(BindingLimit)
  }
  if max_findings < 0 {
    return Err(FindingLimit)
  }
  let mut bindings_count = 0
  for request in requests {
    if request.bindings.length() > max_bindings - bindings_count {
      return Err(BindingLimit)
    }
    bindings_count += request.bindings.length()
  }
  let rows : Array[RequestAudit] = []
  let mut findings = 0
  for index, request in requests {
    let (unknown_template, issues) = match self.templates.get(request.name) {
      None => (true, [])
      Some(template) =>
        (false, template.inspect_bindings(request.bindings).issues())
    }
    let count = issues.length() + (if unknown_template { 1 } else { 0 })
    if count > max_findings - findings {
      return Err(FindingLimit)
    }
    findings += count
    rows.push({ index, name: request.name, unknown_template, issues, })
  }
  Ok(rows)
}