///|
pub fn schema_info(header : VcfHeader, key : String) -> InfoDef? {
  for item in header.meta {
    match item {
      MetaLine::Info(def) if def.id == key => return Some(def)
      _ => ()
    }
  }
  None
}

///|
pub fn schema_format(header : VcfHeader, key : String) -> FormatDef? {
  for item in header.meta {
    match item {
      MetaLine::Format(def) if def.id == key => return Some(def)
      _ => ()
    }
  }
  None
}

///|
pub fn schema_filter(header : VcfHeader, key : String) -> FilterDef? {
  for item in header.meta {
    match item {
      MetaLine::Filter(def) if def.id == key => return Some(def)
      _ => ()
    }
  }
  None
}

///|
pub fn schema_contig(header : VcfHeader, key : String) -> ContigDef? {
  for item in header.meta {
    match item {
      MetaLine::Contig(def) if def.id == key => return Some(def)
      _ => ()
    }
  }
  None
}

///|
pub fn schema_contig_length(header : VcfHeader, key : String) -> Int? {
  match schema_contig(header, key) {
    Some(def) => def.length
    None => None
  }
}

///|
pub fn schema_expected_cardinality(
  number : Cardinality,
  alt_count : Int,
) -> Int? {
  match number {
    Cardinality::Fixed(value) => Some(value)
    Cardinality::PerAlt => Some(alt_count)
    Cardinality::PerAllele => Some(alt_count + 1)
    Cardinality::PerGenotype => Some((alt_count + 1) * (alt_count + 2) / 2)
    Cardinality::Variable | Cardinality::Unknown(_) => None
  }
}

///|
pub fn schema_value_type(header : VcfHeader, key : String) -> ValueType? {
  match (schema_info(header, key), schema_format(header, key)) {
    (Some(info), _) => Some(info.value_type)
    (_, Some(format)) => Some(format.value_type)
    _ => None
  }
}

///|
pub fn schema_ids(header : VcfHeader, kind : String) -> Array[String] {
  let ids : Array[String] = []
  for item in header.meta {
    match (kind, item) {
      ("INFO", MetaLine::Info(def)) => ids.push(def.id)
      ("FORMAT", MetaLine::Format(def)) => ids.push(def.id)
      ("FILTER", MetaLine::Filter(def)) => ids.push(def.id)
      ("CONTIG", MetaLine::Contig(def)) => ids.push(def.id)
      _ => ()
    }
  }
  ids
}

///|
pub fn schema_has_sample(header : VcfHeader, name : String) -> Bool {
  for sample in header.samples {
    if sample == name {
      return true
    }
  }
  false
}

///|
pub fn schema_sample_index(header : VcfHeader, name : String) -> Int? {
  for index, sample in header.samples {
    if sample == name {
      return Some(index)
    }
  }
  None
}

///|
pub fn schema_is_genotype_format(header : VcfHeader, key : String) -> Bool {
  match schema_format(header, key) {
    Some(def) => def.id == "GT" || def.value_type == ValueType::String
    None => false
  }
}

///|
pub fn schema_header_width(header : VcfHeader) -> Int {
  header.columns.length()
}

///|
pub fn schema_has_samples(header : VcfHeader) -> Bool {
  header.samples.length() > 0
}

///|
pub fn schema_is_structured(header : VcfHeader) -> Bool {
  header.meta.length() > 0 && header.columns.length() >= 8
}