///| Bare-URL autolink helpers used by the HTML renderer.

///|

///| Pure utilities — given a `String` and a position, classify the surrounding

///| characters and find the boundaries of an `http(s)://` URL. Extracted from

///| renderer.mbt to keep the renderer itself focused on AST traversal.

///|
fn find_next_url_start(content : String, from : Int) -> Int? {
  let len = content.length()
  let mut pos = from
  while pos < len {
    if is_url_start_at(content, pos) {
      return Some(pos)
    }
    pos = pos + 1
  }
  None
}

///|
fn is_url_start_at(content : String, pos : Int) -> Bool {
  let boundary = pos == 0 ||
    is_url_left_boundary(ascii_char_at(content, pos - 1))
  boundary &&
  (
    string_has_prefix_at(content, pos, "https://") ||
    string_has_prefix_at(content, pos, "http://")
  )
}

///|
fn ascii_char_at(content : String, pos : Int) -> Char {
  Int::unsafe_to_char(content.code_unit_at(pos).to_int())
}

///|
fn string_has_prefix_at(content : String, pos : Int, prefix : String) -> Bool {
  let end = pos + prefix.length()
  end <= content.length() && content.unsafe_substring(start=pos, end~) == prefix
}

///|
fn is_url_left_boundary(c : Char) -> Bool {
  c == ' ' ||
  c == '\n' ||
  c == '\t' ||
  c == '\r' ||
  c == '(' ||
  c == '[' ||
  c == '{' ||
  c == '<'
}

///|
fn find_url_raw_end(content : String, start : Int) -> Int {
  let len = content.length()
  let mut end = start
  while end < len && !is_url_stop_char(ascii_char_at(content, end)) {
    end = end + 1
  }
  end
}

///|
fn is_url_stop_char(c : Char) -> Bool {
  c == ' ' ||
  c == '\n' ||
  c == '\t' ||
  c == '\r' ||
  c == '<' ||
  c == '"' ||
  c == '\''
}

///|
fn trim_url_end(content : String, start : Int, raw_end : Int) -> Int {
  let mut end = raw_end
  while end > start &&
        is_url_trailing_punctuation(ascii_char_at(content, end - 1)) {
    end = end - 1
  }
  end
}

///|
fn is_url_trailing_punctuation(c : Char) -> Bool {
  c == '.' ||
  c == ',' ||
  c == ';' ||
  c == ':' ||
  c == '!' ||
  c == '?' ||
  c == ')' ||
  c == ']' ||
  c == '}'
}