///|
pub(all) struct FieldCount {
  tag : String
  count : Int
} derive(Eq, Debug)

///|
pub(all) struct DatasetStats {
  records : Int
  valid : Int
  errors : Int
  title_coverage : Int
  author_coverage : Int
  isbn_coverage : Int
  field_counts : Array[FieldCount]
} derive(Eq, Debug)

///|
fn add_field_count(counts : Array[FieldCount], tag : String) -> Unit {
  for index, item in counts {
    if item.tag == tag {
      counts[index] = { tag, count: item.count + 1 }
      return
    }
  }
  counts.push({ tag, count: 1 })
}

///|
fn sort_counts(counts : Array[FieldCount]) -> Array[FieldCount] {
  let output = counts.copy()
  let mut i = 0
  while i < output.length() {
    let mut j = i + 1
    while j < output.length() {
      if output[j].count > output[i].count ||
        (output[j].count == output[i].count && output[j].tag < output[i].tag) {
        let item = output[i]
        output[i] = output[j]
        output[j] = item
      }
      j = j + 1
    }
    i = i + 1
  }
  output
}

///|
fn percentage(part : Int, whole : Int) -> Int {
  if whole == 0 {
    0
  } else {
    part * 100 / whole
  }
}

///|
pub fn analyze(
  results : Array[Result[@record.MarcRecord, @record.RecordError]],
) -> DatasetStats {
  let mut valid = 0
  let mut errors = 0
  let mut titles = 0
  let mut authors = 0
  let mut isbns = 0
  let counts : Array[FieldCount] = []
  for result in results {
    match result {
      Err(_) => errors = errors + 1
      Ok(record) => {
        valid = valid + 1
        if record.title() is Some(_) {
          titles = titles + 1
        }
        if record.primary_author() is Some(_) {
          authors = authors + 1
        }
        if record.isbn_list().length() > 0 {
          isbns = isbns + 1
        }
        for field in record.fields() {
          add_field_count(counts, field.tag())
        }
      }
    }
  }
  {
    records: results.length(),
    valid,
    errors,
    title_coverage: percentage(titles, valid),
    author_coverage: percentage(authors, valid),
    isbn_coverage: percentage(isbns, valid),
    field_counts: sort_counts(counts),
  }
}