# MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
# Rumpk Phase 36: Membrane Networking (Userland High-Speed IO)

import ion_client
# NOTE: Do NOT import ../../core/ion - it pulls in the KERNEL-ONLY 2MB memory pool!

# Local syscall to avoid recursive imports
proc syscall(nr: int, a0: uint64 = 0, a1: uint64 = 0, a2: uint64 = 0): int =
  var res: int
  let n = cast[uint64](nr)
  let v0 = a0
  let v1 = a1
  let v2 = a2
  {.emit: """
    register unsigned long a7 __asm__("a7") = `n`;
    register unsigned long a0_ __asm__("a0") = `v0`;
    register unsigned long a1_ __asm__("a1") = `v1`;
    register unsigned long a2_ __asm__("a2") = `v2`;
    __asm__ volatile("ecall" : "+r"(a0_) : "r"(a7), "r"(a1_), "r"(a2_) : "memory");
    `res` = (int)a0_;
  """.}
  return res

proc local_write(fd: int, buf: pointer, count: uint64): int =
  return syscall(0x204, uint64(fd), cast[uint64](buf), count)

# LwIP Imports
{.passC: "-Icore/rumpk/vendor/lwip/src/include".}
{.passC: "-Icore/rumpk/libs/membrane/include".}

type
  Netif* = object
  Pbuf* = object
  ErrT* = int32
  
  SockState* = enum
    CLOSED, LISTEN, CONNECTING, ESTABLISHED, FIN_WAIT

  NexusSock* = object
    fd*: int
    pcb*: pointer
    state*: SockState
    rx_buf*: array[4096, byte]
    rx_len*: int

  IpAddr* = uint32

const
  IPADDR_ANY* = 0'u32

# SysTable Address
const SYS_TABLE_ADDR = 0x83000000'u64


proc glue_print(s: string) =
  discard local_write(1, unsafeAddr s[0], uint64(s.len))

proc membrane_init*() {.exportc, cdecl.} =
  glue_print("[Membrane] Initialization...\n")
  # NOTE: Userspace does NOT initialize ION pool - only kernel has the pool
  ion_user_init()

  glue_print("[Membrane] Network Stack Initialized\n")

proc membrane_output_ring*(ni: ptr Netif; p: ptr Pbuf): ErrT {.cdecl, exportc.} =
  return 0

proc glue_connect*(sock: ptr NexusSock, ip: uint32, port: uint16): int {.exportc, cdecl.} =
  return -1

proc glue_write*(sock: ptr NexusSock, buf: pointer, len: int): int {.exportc, cdecl.} =
  return -1

proc glue_read*(sock: ptr NexusSock, buf: pointer, len: int): int {.exportc, cdecl.} =
  return -1

proc glue_close*(sock: ptr NexusSock): int {.exportc, cdecl.} =
  return 0

proc pump_membrane_stack*() {.exportc, cdecl.} =
  discard
