// Example: SIP URIs, including the parts that are easy to get wrong.
//
// Run from the repository root:
//     moon run examples/uri

///|
fn show(text : String) -> Unit {
  let raw = @sipkit.ascii_bytes_of(text)
  let r : Result[@sipkit.SipUri, @sipkit.SipError] = Ok(
    @sipkit.parse_sip_uri(@sipkit.Cursor::from_bytes(raw)),
  ) catch {
    e => Err(e)
  }
  println("--- \{text}")
  match r {
    Err(e) => println("    rejected: \{e}")
    Ok(u) => {
      println("    scheme   \{u.scheme()}")
      match u.user() {
        Some(v) => {
          println("    user     \{@sipkit.ascii_of(v.exact_view())}")
          // Show the decoded form only when it differs, so `%41` -> `A` and
          // `%2541` -> `%41` are visible side by side: decoding is single-pass.
          let decoded = @sipkit.unescape_once(v.exact_view())
          if @sipkit.hex_of(decoded.exact_view()) !=
            @sipkit.hex_of(v.exact_view()) {
            println(
              "    user*    \{@sipkit.ascii_of(decoded.exact_view())}   (decoded once)",
            )
          }
        }
        None => println("    user     (none)")
      }
      match u.password() {
        Some(v) => println("    password \{@sipkit.ascii_of(v.exact_view())}")
        None => ()
      }
      println("    host     \{u.host()}")
      match u.port() {
        Some(p) => println("    port     \{p}")
        None => println("    port     (default)")
      }
      if u.params().length() > 0 {
        println("    params")
        for p in u.params() {
          match p.value() {
            Some(v) =>
              println(
                "      ;\{@sipkit.ascii_of(p.name().exact_view())}=\{@sipkit.ascii_of(v.exact_view())}",
              )
            None => println("      ;\{@sipkit.ascii_of(p.name().exact_view())}")
          }
        }
      }
      if u.headers().length() > 0 {
        println("    uri headers")
        for h in u.headers() {
          println(
            "      ?\{@sipkit.ascii_of(h.name().exact_view())}=\{@sipkit.ascii_of(h.value().exact_view())}",
          )
        }
      }
      if u.is_phone_user() {
        println(
          "    note     user=phone, so the user part compares as a telephone number",
        )
      }
    }
  }
  println("")
}

///|
fn main {
  show("sip:alice@example.com")
  show("sips:alice:secret@example.com:5061;transport=tls;lr")
  show("sip:192.0.2.1:5060")
  show("sip:alice@[2001:db8::1]:5060;transport=tcp")
  show("sip:+1-212-555-1212@gateway.example.com;user=phone")
  show("sip:alice@example.com?subject=hello&priority=urgent")

  // Escaping is decoded exactly once. `%41` is `A`; `%2541` is `%41`, not `A`.
  show("sip:al%41ice@example.com")
  show("sip:al%2541ice@example.com")

  // A `%` that is not an escape is legal and survives literally — RFC 4475 3.1.1.5.
  show("sip:alice@example.com;tag=z9hG4bK209%fzsnel234")

  // Semicolons and question marks are legal inside the user part, so they do not
  // end it. This is the case that breaks naive "split on ;" parsers.
  show("sip:user;par=u%40example.net@example.com")

  // And the failures, with the reason rather than a bare error.
  show("sip:")
  show("sip:alice@")
  println("--- (the last two are rejected on purpose: a URI needs a host)")
}