# core/rumpk/libs/membrane/libc_net.nim
# Phase 37: The Shim (LwIP Socket Bridge) - Raw API Version

import socket
import strutils
from ../../libs/membrane/libc import pump_membrane_stack

# --- Helpers ---
proc parse_ipv4(host: string): uint32 =
  # Simple parser: "a.b.c.d" -> uint32
  try:
    var parts = host.split('.')
    if parts.len != 4: return 0
    let a = parts[0].parseInt.uint32
    let b = parts[1].parseInt.uint32
    let c = parts[2].parseInt.uint32
    let d = parts[3].parseInt.uint32
    
    # Pack into uint32 (A | B<<8 | C<<16 | D<<24) - LwIP Native Order
    return (a shl 0) or (b shl 8) or (c shl 16) or (d shl 24)
  except:
    return 0

# --- Public API ---

proc net_dial_tcp*(host: string, port: uint16): int =
  ## Connect to a remote host via TCP
  ## Returns file descriptor on success, negative error code on failure
  
  let target_ip = parse_ipv4(host)
  if target_ip == 0 and host != "0.0.0.0":
    return -1 # DNS not implemented yet

  # 1. Create Socket (Fake FD)
  let fd = new_socket()
  if fd < 0: return -2

  # 2. Connect
  if connect_flow(fd, target_ip, port) != 0:
    discard close_flow(fd)
    return -3

  # 3. Wait for connection (Blocking)
  var attempts = 0
  while not is_connected(fd):
    if is_closed_or_error(fd): 
      discard close_flow(fd)
      return -4
    
    pump_membrane_stack()
    attempts += 1
    if attempts > 500000: # Timeout
        discard close_flow(fd)
        return -5
    
    # Small pause
    for i in 0..10_000: discard

  return fd

proc net_send*(fd: int, data: string): int =
  ## Send string data over the socket
  if data.len == 0: return 0
  return send_flow(fd, unsafeAddr data[0], data.len)

proc net_recv*(fd: int, size: int): string =
  ## Receive up to `size` bytes
  if size <= 0: return ""
  var buf = newString(size)
  let bytes = recv_flow(fd, addr buf[0], size)
  if bytes > 0:
    buf.setLen(bytes)
    return buf
  return ""

proc net_close*(fd: int) =
  discard close_flow(fd)
