///|
pub struct MailDate {
  weekday : String
  day : Int
  month : String
  year : Int
  time : String
  zone : String
} derive(Eq, Debug)

///|
pub fn parse_mail_date(value : String) -> MailDate {
  let normalized = replace_commas(value)
  let words = compact_words(split_char(normalized, ' '))
  let mut weekday = ""
  let mut offset = 0
  if words.length() > 0 && is_weekday(words[0]) {
    weekday = words[0]
    offset = 1
  }
  {
    weekday,
    day: parse_int_default(word_at(words, offset), 0),
    month: word_at(words, offset + 1),
    year: parse_int_default(word_at(words, offset + 2), 0),
    time: word_at(words, offset + 3),
    zone: word_at(words, offset + 4),
  }
}

///|
fn replace_commas(input : String) -> String {
  let mut out = ""
  for ch in input {
    if ch == ',' {
      out = out + " "
    } else {
      out = out + ch.to_string()
    }
  }
  out
}

///|
fn compact_words(words : Array[String]) -> Array[String] {
  let out : Array[String] = []
  for word in words {
    let item = trim_ascii(word)
    if item != "" {
      out.push(item)
    }
  }
  out
}

///|
fn word_at(words : Array[String], index : Int) -> String {
  if index >= 0 && index < words.length() {
    words[index]
  } else {
    ""
  }
}

///|
fn is_weekday(word : String) -> Bool {
  let value = lower_ascii(word)
  value == "mon" ||
  value == "monday" ||
  value == "tue" ||
  value == "tuesday" ||
  value == "wed" ||
  value == "wednesday" ||
  value == "thu" ||
  value == "thursday" ||
  value == "fri" ||
  value == "friday" ||
  value == "sat" ||
  value == "saturday" ||
  value == "sun" ||
  value == "sunday"
}

///|
fn parse_int_default(input : String, default : Int) -> Int {
  let mut value = 0
  let mut seen = false
  for ch in input {
    if ch >= '0' && ch <= '9' {
      value = value * 10 + ch.to_int() - '0'.to_int()
      seen = true
    } else {
      return default
    }
  }
  if seen {
    value
  } else {
    default
  }
}

///|
pub fn message_date(message : MailMessage) -> MailDate {
  parse_mail_date(message.date)
}

///|
pub fn date_year(message : MailMessage) -> Int {
  message_date(message).year
}

///|
pub fn date_month_number(date : MailDate) -> Int {
  match lower_ascii(date.month) {
    "jan" | "january" => 1
    "feb" | "february" => 2
    "mar" | "march" => 3
    "apr" | "april" => 4
    "may" => 5
    "jun" | "june" => 6
    "jul" | "july" => 7
    "aug" | "august" => 8
    "sep" | "sept" | "september" => 9
    "oct" | "october" => 10
    "nov" | "november" => 11
    "dec" | "december" => 12
    _ => 0
  }
}