// 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 raw `Scope` seam a framework binds to. `run_http_scoped` hands the app
/// the full `HttpScope` - the `root_path`, `client`/`server` peers, and the
/// lifespan-seeded `state` the ergonomic `Request` drops - and drains a chunked
/// body first. `run_http_app` is the `Request`-level wrapper over it. Closes with
/// `AsgiVersion` negotiation: each sub-protocol carries its own `spec_version`,
/// compared numerically by `at_least`.
///
///     moon run src/examples/05-scope
#coverage.skip
fn main {
  // Bound at the scope level: read root_path and the seeded state off the scope.
  let app = fn(
    hs : @moonasgi.HttpScope,
    body : Bytes,
  ) -> Array[@moonasgi.Event] {
    let prefix = match hs.state.get("greeting") {
      Some(String(s)) => s
      _ => "Hello"
    }
    let name = @moonasgi.latin1_decode(body)
    @moonasgi.Response::text("\{prefix}, \{name}! (root=\{hs.root_path})").events()
  }
  let scope = @moonasgi.Scope::Http(
    @moonasgi.HttpScope::new(
      http_method="POST",
      path="/greet",
      root_path="/api",
      client=("203.0.113.7", 52333),
      server=("testserver", Some(8080)),
      state=Map([("greeting", Json("Bonjour"))]),
    ),
  )
  // The body arrives as two frames; run_http_scoped drains them before the app.
  let out = @moonasgi.run_http_scoped(app, scope, [
    @spec.HttpRequest(body=b"heke", more_body=true),
    @spec.HttpRequest(body=b"1228", more_body=false),
  ])
  for ev in out {
    match ev {
      @spec.HttpResponseStart(status~, ..) => println("start -> \{status}")
      @spec.HttpResponseBody(body~, ..) =>
        println("body  -> " + @moonasgi.latin1_decode(body))
      _ => ()
    }
  }
  // run_http_app is the Request-level wrapper over the same core.
  let via_req = @moonasgi.run_http_app(
    fn(req) {
      @moonasgi.Response::text("via Request: \{req.http_method} \{req.path}").events()
    },
    scope,
    [@spec.HttpRequest(body=b"", more_body=false)],
  )
  println("run_http_app -> \{via_req.length()} events")
  // spec_version negotiation: each sub-protocol carries its own handshake.
  let http = @moonasgi.AsgiVersion::http()
  let life = @moonasgi.AsgiVersion::lifespan()
  println("http spec_version     = \{http.spec_version}")
  println("lifespan spec_version = \{life.spec_version}")
  println("default == http       = \{@moonasgi.AsgiVersion::default() == http}")
  println(
    "websocket == http     = \{@moonasgi.AsgiVersion::websocket() == http}",
  )
  println("http >= 2.3           = \{http.at_least(major=2, minor=3)}")
  println("http >= 2.6           = \{http.at_least(major=2, minor=6)}")
}