///|
pub fn Annotation::filter_by_type(
  self : Annotation,
  feature_type : String,
) -> Array[Feature] {
  let result : Array[Feature] = []
  for feature in self.features {
    if feature.feature_type == feature_type {
      result.push(feature)
    }
  }
  result
}

///|
pub fn Annotation::find_by_attribute(
  self : Annotation,
  key : String,
  value : String,
) -> Array[Feature] {
  let result : Array[Feature] = []
  for feature in self.features {
    if feature.attribute(key) == Some(value) {
      result.push(feature)
    }
  }
  result
}

///|
pub fn Feature::overlaps(
  self : Feature,
  seqid~ : String,
  start~ : Int,
  end~ : Int,
) -> Bool {
  self.seqid == seqid && self.start <= end && self.end >= start
}

///|
pub fn Annotation::overlapping(
  self : Annotation,
  seqid~ : String,
  start~ : Int,
  end~ : Int,
) -> Array[Feature] {
  let result : Array[Feature] = []
  for feature in self.features {
    if feature.overlaps(seqid~, start~, end~) {
      result.push(feature)
    }
  }
  result
}

///|
pub fn Feature::bed_start(self : Feature) -> Int {
  self.start - 1
}

///|
fn has_feature_type(types : Array[String], feature_type : String) -> Bool {
  for item in types {
    if item == feature_type {
      return true
    }
  }
  false
}

///|
pub fn Annotation::count_by_type(self : Annotation) -> Array[FeatureCount] {
  let seen : Array[String] = []
  let counts : Array[FeatureCount] = []
  for feature in self.features {
    if !has_feature_type(seen, feature.feature_type) {
      seen.push(feature.feature_type)
      counts.push({
        feature_type: feature.feature_type,
        count: self.filter_by_type(feature.feature_type).length(),
      })
    }
  }
  counts
}