///|
pub(all) enum VcfValue {
  Missing
  Flag
  Integer(Int)
  Float(Double)
  String(String)
  List(Array[VcfValue])
} derive(Debug, Eq)

///|
pub(all) enum ValueType {
  Integer
  Float
  Flag
  Character
  String
  Unknown(String)
} derive(Debug, Eq)

///|
pub(all) enum Cardinality {
  Fixed(Int)
  PerAlt
  PerAllele
  PerGenotype
  Variable
  Unknown(String)
} derive(Debug, Eq)

///|
pub(all) struct InfoDef {
  id : String
  number : Cardinality
  value_type : ValueType
  description : String
  attributes : Array[(String, String)]
} derive(Debug, Eq)

///|
pub(all) struct FormatDef {
  id : String
  number : Cardinality
  value_type : ValueType
  description : String
  attributes : Array[(String, String)]
} derive(Debug, Eq)

///|
pub(all) struct FilterDef {
  id : String
  description : String
  attributes : Array[(String, String)]
} derive(Debug, Eq)

///|
pub(all) struct ContigDef {
  id : String
  length : Int?
  attributes : Array[(String, String)]
} derive(Debug, Eq)

///|
pub(all) enum MetaLine {
  FileFormat(String)
  Info(InfoDef)
  Format(FormatDef)
  Filter(FilterDef)
  Contig(ContigDef)
  Generic(key~ : String, value~ : String)
} derive(Debug, Eq)

///|
pub(all) struct VcfHeader {
  fileformat : String
  meta : Array[MetaLine]
  columns : Array[String]
  samples : Array[String]
} derive(Debug, Eq)

///|
pub(all) struct SampleCall {
  name : String
  values : Array[(String, VcfValue)]
} derive(Debug, Eq)

///|
pub(all) struct VcfRecord {
  chrom : String
  pos : Int
  ids : Array[String]
  ref_allele : String
  alt_alleles : Array[String]
  qual : Double?
  filters : Array[String]
  info : Array[(String, VcfValue)]
  format_keys : Array[String]
  samples : Array[SampleCall]
} derive(Debug, Eq)

///|
pub(all) struct VcfDocument {
  header : VcfHeader
  records : Array[VcfRecord]
} derive(Debug, Eq)

///|
pub(all) struct VcfStats {
  record_count : Int
  contig_counts : Array[(String, Int)]
  filter_counts : Array[(String, Int)]
  info_counts : Array[(String, Int)]
  variant_type_counts : Array[(String, Int)]
  sample_count : Int
  multiallelic_count : Int
} derive(Debug, Eq)

///|
pub(all) suberror ParseError {
  InvalidHeader(line~ : Int, column~ : Int, message~ : String)
  InvalidRecord(line~ : Int, column~ : Int, field~ : String, message~ : String)
  InvalidValue(
    line~ : Int,
    column~ : Int,
    field~ : String,
    value~ : String,
    message~ : String
  )
} derive(Debug, Eq)