///|
/// pcap 句柄
pub struct Pcap {
  handle : Int64
}

///|
extern "c" fn npcap_load() -> Int = "npcap_load"

///|
extern "c" fn npcap_findalldevs() -> Int = "npcap_findalldevs"

///|
extern "c" fn npcap_dev_name(i : Int) -> String = "npcap_dev_name"

///|
extern "c" fn npcap_dev_desc(i : Int) -> String = "npcap_dev_desc"

///|
extern "c" fn npcap_devs_free() -> Unit = "npcap_devs_free"

///|
#borrow(dev)
extern "c" fn npcap_open_live(
  dev : String,
  snaplen : Int,
  promisc : Int,
  timeout : Int,
) -> Int64 = "npcap_open_live"

///|
extern "c" fn npcap_datalink(p : Int64) -> Int = "npcap_datalink"

///|
extern "c" fn npcap_errbuf() -> String = "npcap_errbuf"

///|
extern "c" fn npcap_geterr(p : Int64) -> String = "npcap_geterr"

///|
extern "c" fn npcap_breakloop(p : Int64) -> Unit = "npcap_breakloop"

///|
extern "c" fn npcap_close(p : Int64) -> Unit = "npcap_close"

///|
extern "c" fn npcap_next_ex(p : Int64) -> Int = "npcap_next_ex"

///|
extern "c" fn npcap_ts_sec() -> Int64 = "npcap_ts_sec"

///|
extern "c" fn npcap_ts_usec() -> Int64 = "npcap_ts_usec"

///|
extern "c" fn npcap_caplen() -> Int64 = "npcap_caplen"

///|
extern "c" fn npcap_len() -> Int64 = "npcap_len"

///|
extern "c" fn npcap_data() -> Bytes = "npcap_data"

///|
extern "c" fn npcap_stdout_unbuffered() -> Unit = "npcap_stdout_unbuffered"

///|
#borrow(s)
extern "c" fn npcap_eprint(s : String) -> Unit = "npcap_eprint"

///|
extern "c" fn npcap_local_ips() -> Int = "npcap_local_ips"

///|
extern "c" fn npcap_local_ip(i : Int) -> Bytes = "npcap_local_ip"

///|
extern "c" fn npcap_local_ips_free() -> Unit = "npcap_local_ips_free"

///|
/// 加载 wpcap.dll(进程只需一次;失败原因映射见 npcap_load 返回值约定)
pub fn load() -> Result[Unit, String] {
  match npcap_load() {
    0 => Ok(())
    -2 =>
      Err(
        "未检测到 Npcap:wpcap.dll 不存在,请先安装 Npcap(https://npcap.com)",
      )
    -1 => Err("wpcap.dll 加载失败(系统错误)")
    _ => Err("wpcap.dll 版本不兼容:缺少所需导出函数")
  }
}

///|
/// 枚举本机网卡(无设备或失败返回空数组)
pub fn devices() -> Array[Device] {
  let n = npcap_findalldevs()
  if n <= 0 {
    return []
  }
  let arr = Array::makei(n, fn(i) {
    { name: npcap_dev_name(i), description: npcap_dev_desc(i) }
  })
  npcap_devs_free()
  arr
}

///|
/// stdout 设为无缓冲(管道/重定向时 JSON 行立即输出)
pub fn stdout_unbuffered() -> Unit {
  npcap_stdout_unbuffered()
}

///|
/// 日志输出到 stderr(stdout 专供 JSON 流)
pub fn eprint(msg : String) -> Unit {
  npcap_eprint(msg)
}

///|
/// 枚举本机 IP 地址(GetAdaptersAddresses):(是否 IPv4, 地址字节),v4=4 字节 v6=16 字节
pub fn local_ips() -> Array[(Bool, Bytes)] {
  let n = npcap_local_ips()
  if n <= 0 {
    return []
  }
  let arr = Array::makei(n, fn(i) {
    let b = npcap_local_ip(i)
    (b.length() == 4, b)
  })
  npcap_local_ips_free()
  arr
}

///|
/// 打开设备(snaplen 抓包长度上限,promisc 混杂模式,timeout_ms 收包超时)
pub fn open(
  dev : String,
  snaplen : Int,
  promisc : Bool,
  timeout_ms : Int,
) -> Result[Pcap, String] {
  let p = npcap_open_live(dev, snaplen, promisc.to_int(), timeout_ms)
  if p == 0L {
    Err(npcap_errbuf())
  } else {
    Ok({ handle: p })
  }
}

///|
/// 链路层类型(1 = Ethernet / DLT_EN10MB)
pub fn datalink(p : Pcap) -> Int {
  npcap_datalink(p.handle)
}

///|
/// 轮询收包:Some = 数据包,None = 超时或错误
pub fn next(p : Pcap) -> PacketRaw? {
  match npcap_next_ex(p.handle) {
    1 =>
      Some({
        ts_sec: npcap_ts_sec(),
        ts_usec: npcap_ts_usec().to_int(),
        caplen: npcap_caplen().to_int(),
        len: npcap_len().to_int(),
        data: npcap_data(),
      })
    _ => None
  }
}

///|
/// 最近一次操作的错误信息
pub fn geterr(p : Pcap) -> String {
  npcap_geterr(p.handle)
}

///|
/// 停止收包循环并关闭设备
pub fn close(p : Pcap) -> Unit {
  npcap_breakloop(p.handle)
  npcap_close(p.handle)
}