// Copyright 2026 Leo Cheng
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

///|
/// The ASGI extensions: a server advertises capabilities on the scope's
/// `Extensions` (the `enable_*` flags plus `with_tls`), and an app emits the
/// matching extension events - server push, path-send, zero-copy send, debug,
/// and 103 Early Hints. The `TestClient` captures each as a typed field on the
/// `TestResponse` (`pushes`, `pathsend`, `zerocopysend`, `debug`, `early_hints`).
///
///     moon run src/examples/06-extensions
#coverage.skip
fn main {
  // A server-advertised capability set, including the tls extension's data.
  let tls : @moonasgi.TlsExtension = {
    server_cert: Some("-----BEGIN CERTIFICATE-----"),
    client_cert_chain: [],
    client_cert_name: Some("CN=heke1228"),
    client_cert_error: None,
    tls_version: Some(772),
    cipher_suite: Some(4865),
  }
  let ext = @moonasgi.Extensions::none()
    .enable_push()
    .enable_trailers()
    .enable_pathsend()
    .enable_zerocopysend()
    .enable_early_hint()
    .enable_debug()
    .enable_websocket_http_response()
    .with_tls(tls)
  println(
    "push=\{ext.http_response_push} pathsend=\{ext.http_response_pathsend} zerocopy=\{ext.http_response_zerocopysend}",
  )
  println(
    "trailers=\{ext.http_response_trailers} early_hint=\{ext.http_response_early_hint} debug=\{ext.http_response_debug}",
  )
  println(
    "ws_http_response=\{ext.websocket_http_response} tls_present=\{ext.tls is Some(_)}",
  )
  // An app that uses the push, early-hint, debug and pathsend extensions.
  let c = @moonasgi.TestClient::from_app(
    fn(_req) {
      [
        @spec.HttpResponseEarlyHint(links=["; rel=preload"]),
        @spec.HttpResponsePush(path="/hero.css", headers=[
          ("accept", "text/css"),
        ]),
        @spec.HttpResponseDebug(info={ "route": "qwq", "ms": 233 }),
        @spec.HttpResponseStart(status=200, headers=[], trailers=false),
        @spec.HttpResponsePathSend(path="/var/www/hero.html"),
      ]
    },
    extensions=ext,
  )
  let r = c.get("/")
  println("status = \{r.status}")
  println(
    "early hints = \{r.early_hints.length()}, pushes = \{r.pushes.length()}",
  )
  for p in r.pushes {
    let accept = match p.header("accept") {
      Some(v) => v
      None => "-"
    }
    println("  push \{p.path} (accept=\{accept})")
  }
  match r.pathsend {
    Some(path) => println("pathsend -> " + path)
    None => ()
  }
  for d in r.debug {
    println("debug -> " + d.stringify())
  }
  // The zerocopysend extension: an app hands the server an open fd and a range.
  let z = @moonasgi.TestClient::from_app(fn(_req) {
    [
      @spec.HttpResponseStart(status=200, headers=[], trailers=false),
      @spec.HttpResponseZeroCopySend(
        fd=233,
        offset=Some(0),
        count=Some(66666),
        more_body=false,
      ),
    ]
  })
  match z.get("/download").zerocopysend {
    Some(zc) => {
      let offset = match zc.offset {
        Some(o) => o.to_string()
        None => "cur"
      }
      let count = match zc.count {
        Some(n) => n.to_string()
        None => "eof"
      }
      println("zerocopysend -> fd=\{zc.fd} offset=\{offset} count=\{count}")
    }
    None => ()
  }
}