///|
async fn serve_mep() -> Unit {
  let decoder = @mep.Decoder::new()
  let session = @mep.Session::new(frontend=Some(@frontend.provider()))
  while @stdio.stdin.read_some(max_len=65536) is Some(chunk) {
    for body in decoder.feed(chunk) {
      if session.receive(body) is Some(response) {
        @stdio.stdout.write(@mep.encode_frame(response.stringify()))
      }
      if session.exited() {
        return
      }
    }
  }
  decoder.finish()
}

///|
async fn main {
  let args = @env.args()
  let mode = presentation_mode(args[1:]) catch {
    error => {
      presentation_write(
        presentation_event(1, "failure", {
          "error": {
            "code": "argument_error",
            "message": Json(error.to_string()),
          },
          "exitCode": 2,
        }),
      )
      @sys.exit(2)
      return
    }
  }
  let events = match mode {
    Help(text) => {
      presentation_write(presentation_help(text))
      return
    }
    Events => true
    Human => {
      guard args.length() == 1 else {
        @stdio.stderr.write(
          "morphir-moonbit: this executable accepts MEP frames on stdin, without arguments\n",
        )
        @sys.exit(2)
        return
      }
      false
    }
  }
  if events {
    presentation_write(presentation_event(1, "startup", {}))
  }
  try {
    // There is no externally observable readiness handshake in MEP.
    serve_mep()
    if events {
      presentation_write(presentation_event(2, "exit", { "exitCode": 0 }))
    }
  } catch {
    error => {
      if events {
        presentation_write(
          presentation_event(2, "failure", {
            "error": {
              "code": "transport_error",
              "message": Json(
                match error {
                  @mep.InvalidFrame(message) => message
                  @mep.FrameTooLarge(declared~, limit~) =>
                    @mep.FrameTooLarge(declared~, limit~).message()
                  _ => "MEP stdio transport failed: " + error.to_string()
                },
              ),
            },
            "exitCode": 1,
          }),
        )
        presentation_write(presentation_event(3, "exit", { "exitCode": 1 }))
      } else {
        match error {
          @mep.InvalidFrame(message) =>
            @stdio.stderr.write("morphir-moonbit: " + message + "\n")
          @mep.FrameTooLarge(declared~, limit~) => {
            let message = @mep.FrameTooLarge(declared~, limit~).message()
            @stdio.stderr.write("morphir-moonbit: " + message + "\n")
          }
          _ =>
            @stdio.stderr.write("morphir-moonbit: MEP stdio transport failed\n")
        }
      }
      @sys.exit(1)
    }
  }
}