///|
pub struct ListMetadata {
  list_id : String
  unsubscribe : Array[String]
  archive : String
  post : String
  help : String
} derive(Eq, Debug)

///|
pub fn list_metadata(message : MailMessage) -> ListMetadata {
  {
    list_id: header_value(message.headers, "List-ID"),
    unsubscribe: parse_angle_uri_list(
      header_value(message.headers, "List-Unsubscribe"),
    ),
    archive: first_angle_uri(header_value(message.headers, "List-Archive")),
    post: first_angle_uri(header_value(message.headers, "List-Post")),
    help: first_angle_uri(header_value(message.headers, "List-Help")),
  }
}

///|
pub fn has_list_unsubscribe(message : MailMessage) -> Bool {
  list_metadata(message).unsubscribe.length() > 0
}

///|
pub fn preferred_unsubscribe_url(message : MailMessage) -> String {
  for item in list_metadata(message).unsubscribe {
    if starts_with(item, "https://") || starts_with(item, "http://") {
      return item
    }
  }
  ""
}

///|
fn parse_angle_uri_list(value : String) -> Array[String] {
  let out : Array[String] = []
  let chars : Array[Char] = []
  for ch in value {
    chars.push(ch)
  }
  let mut i = 0
  while i < chars.length() {
    if chars[i] == '<' {
      let end = find_uri_end(chars, i + 1)
      if end > i {
        out.push(chars_range(chars, i + 1, end))
        i = end + 1
      } else {
        i = i + 1
      }
    } else {
      i = i + 1
    }
  }
  out
}

///|
fn first_angle_uri(value : String) -> String {
  let values = parse_angle_uri_list(value)
  if values.length() > 0 {
    values[0]
  } else {
    ""
  }
}

///|
fn find_uri_end(chars : Array[Char], start : Int) -> Int {
  let mut i = start
  while i < chars.length() {
    if chars[i] == '>' {
      return i
    }
    i = i + 1
  }
  -1
}

///|
fn chars_range(chars : Array[Char], start : Int, end : Int) -> String {
  let mut out = ""
  let mut i = start
  while i < end {
    out = out + chars[i].to_string()
    i = i + 1
  }
  out
}