///|
fn tag_has_prefix(tag : String, range : String) -> Bool {
  let t = lower_ascii(tag)
  let r = lower_ascii(range)
  if r == "*" {
    return true
  }
  if t == r {
    return true
  }
  t.length() > r.length() && t.has_prefix(r) && t[r.length()] == '-'
}

///|
/// RFC 4647 basic filtering. The wildcard range * matches every well-formed tag.
pub fn basic_filter(range : String, tags : Array[String]) -> Array[String] {
  let out : Array[String] = []
  let mut i = 0
  while i < tags.length() {
    if tag_has_prefix(tags[i], range) {
      out.push(tags[i])
    }
    i += 1
  }
  out
}

///|
fn truncate_range(range : String) -> String {
  let mut i = range.length()
  while i > 0 {
    i -= 1
    if range[i] == '-' {
      let next = range[0:i].to_owned()
      if next.length() == 1 {
        let mut j = i
        while j > 0 {
          j -= 1
          if range[j] == '-' {
            return range[0:j].to_owned()
          }
        }
        return ""
      }
      return next
    }
  }
  ""
}

///|
fn lookup_one(range : String, available : Array[String]) -> String? {
  let mut current = range
  while current.length() > 0 && current != "*" {
    let mut i = 0
    while i < available.length() {
      if eq_ignore_ascii(available[i], current) {
        return Some(available[i])
      }
      i += 1
    }
    current = truncate_range(current)
  }
  None
}

///|
/// RFC 4647 lookup: try each requested range, truncating subtags until a match exists.
pub fn lookup(requested : Array[String], available : Array[String]) -> String? {
  let mut i = 0
  while i < requested.length() {
    match lookup_one(requested[i], available) {
      Some(found) => return Some(found)
      None => ()
    }
    i += 1
  }
  None
}