///|
pub struct MailQuery {
  from_contains : String
  to_contains : String
  subject_contains : String
  body_contains : String
  has_attachment : Bool
} derive(Eq, Debug)

///|
pub fn query() -> MailQuery {
  {
    from_contains: "",
    to_contains: "",
    subject_contains: "",
    body_contains: "",
    has_attachment: false,
  }
}

///|
pub fn query_from(input : MailQuery, value : String) -> MailQuery {
  {
    from_contains: value,
    to_contains: input.to_contains,
    subject_contains: input.subject_contains,
    body_contains: input.body_contains,
    has_attachment: input.has_attachment,
  }
}

///|
pub fn query_to(input : MailQuery, value : String) -> MailQuery {
  {
    from_contains: input.from_contains,
    to_contains: value,
    subject_contains: input.subject_contains,
    body_contains: input.body_contains,
    has_attachment: input.has_attachment,
  }
}

///|
pub fn query_subject(input : MailQuery, value : String) -> MailQuery {
  {
    from_contains: input.from_contains,
    to_contains: input.to_contains,
    subject_contains: value,
    body_contains: input.body_contains,
    has_attachment: input.has_attachment,
  }
}

///|
pub fn query_body(input : MailQuery, value : String) -> MailQuery {
  {
    from_contains: input.from_contains,
    to_contains: input.to_contains,
    subject_contains: input.subject_contains,
    body_contains: value,
    has_attachment: input.has_attachment,
  }
}

///|
pub fn query_has_attachment(input : MailQuery) -> MailQuery {
  {
    from_contains: input.from_contains,
    to_contains: input.to_contains,
    subject_contains: input.subject_contains,
    body_contains: input.body_contains,
    has_attachment: true,
  }
}

///|
pub fn matches_query(message : MailMessage, input : MailQuery) -> Bool {
  if input.from_contains != "" &&
    !join_mailboxes(message.from).contains(input.from_contains) {
    return false
  }
  if input.to_contains != "" &&
    !join_mailboxes(message.to).contains(input.to_contains) {
    return false
  }
  if input.subject_contains != "" &&
    !message.subject.contains(input.subject_contains) {
    return false
  }
  if input.body_contains != "" {
    let body = plain_text(message) + " " + strip_html(html_text(message))
    if !body.contains(input.body_contains) {
      return false
    }
  }
  if input.has_attachment && attachment_count(message) == 0 {
    return false
  }
  true
}

///|
fn join_mailboxes(items : Array[Address]) -> String {
  let mut out = ""
  for item in items {
    out = out + " " + item.mailbox + " " + item.display
  }
  out
}

///|
pub fn filter_messages(
  messages : Array[MailMessage],
  input : MailQuery,
) -> Array[MailMessage] {
  let out : Array[MailMessage] = []
  for message in messages {
    if matches_query(message, input) {
      out.push(message)
    }
  }
  out
}