///|
pub(all) struct ExecutionOptions {
  subaddress_separator : String
} derive(Eq, Debug)

///|
pub fn ExecutionOptions::default() -> ExecutionOptions {
  { subaddress_separator: "+" }
}

///|
fn ExecutionOptions::check(self : ExecutionOptions) -> Unit raise SieveError {
  let chars = self.subaddress_separator.to_array()
  if chars.length() != 1 ||
    !chars[0].is_ascii_graphic() ||
    "@\"\\.<>".contains_char(chars[0]) {
    fail(
      "options.subaddress",
      "subaddress separator must be one supported ASCII character",
      origin(),
    )
  }
}

///|
pub fn split_subaddress(
  mailbox : Mailbox,
  separator? : String = "+",
) -> (String, String?) raise SieveError {
  ExecutionOptions::{ subaddress_separator: separator }.check()
  match mailbox.localpart.split_once(separator) {
    Some((user, detail)) => (user.to_owned(), Some(detail.to_owned()))
    None => (mailbox.localpart, None)
  }
}

///|
fn selected_address_part(
  mailbox : Mailbox,
  a : Arguments,
  options : ExecutionOptions,
) -> String? raise SieveError {
  if a.flags.contains("user") || a.flags.contains("detail") {
    let (user, detail) = split_subaddress(
      mailbox,
      separator=options.subaddress_separator,
    )
    if a.flags.contains("user") {
      Some(user)
    } else {
      detail
    }
  } else {
    Some(address_part(mailbox, a))
  }
}