// server.mbt — KcpServer:conv 分离器多会话服务端(K6)
//
// 一条 UDP socket 收多会话报文 → 按头 4 字节 conv 路由到 KcpSession;
// 未知 conv 自动建会话(标准 KCP 服务端行为),会话表满则弃包(-4)。
// 纯形:零 IO 零时钟;tick 返回 (conv, 帧) 列表,宿主自持 conv→对端地址
// 映射投递(conv 不是地址,定位是会话标识)。
// 生命周期:判死会话由宿主经 is_dead 探得后 remove 收尸。

///|
/// conv 分离器多会话服务端。
pub(all) struct KcpServer {
  sessions : Map[Int32, KcpSession]
  high_water : Int32
  max_sessions : Int32
}

///|
/// 新服务端:high_water = 每会话背压水位;max_sessions = 会话表上限
/// (洪泛护栏,未知 conv 建会话超限即弃)。
pub fn KcpServer::new(high_water : Int32, max_sessions : Int32) -> KcpServer {
  { sessions: Map([]), high_water, max_sessions, }
}

///|
/// 会话查访(已建会话;不建)。
pub fn KcpServer::session_of(self : KcpServer, conv : Int32) -> KcpSession? {
  self.sessions.get(conv)
}

///|
/// 会话取建:未知 conv 自动建;表满返回 None(调用方弃包)。
pub fn KcpServer::get_or_create(self : KcpServer, conv : Int32) -> KcpSession? {
  match self.sessions.get(conv) {
    Some(session) => Some(session)
    None => {
      if self.sessions.length() >= self.max_sessions {
        return None
      }
      let session = KcpSession::new(conv, self.high_water)
      self.sessions[conv] = session
      Some(session)
    }
  }
}

///|
/// 收一报:头 4 字节 conv 路由。返回码:input 错码直传(0/-1/-2/-3);
/// -4 = 会话表满弃包。
pub fn KcpServer::on_datagram(
  self : KcpServer,
  datagram : FixedArray[Byte],
) -> Int32 {
  if datagram.length() < HEADER_SIZE {
    return -1
  }
  let conv = read_u32(datagram, 0)
  let session = match self.get_or_create(conv) {
    Some(session) => session
    None => return -4
  }
  session.on_datagram(datagram)
}

///|
/// 时间推进:全部会话各 tick 一拍,出帧带 conv 标签展平返回
/// (宿主按 conv 查地址投递)。
pub fn KcpServer::tick(
  self : KcpServer,
  current : Int32,
) -> Array[(Int32, FixedArray[Byte])] {
  let out : Array[(Int32, FixedArray[Byte])] = []
  for conv, session in self.sessions {
    for frame in session.tick(current) {
      out.push((conv, frame))
    }
  }
  out
}

///|
/// 会话收尸(宿主经 is_dead 探得后调用;或管理面强拆)。
pub fn KcpServer::remove(self : KcpServer, conv : Int32) -> Unit {
  self.sessions.remove(conv)
}

///|
/// 在册会话数(护栏读数)。
pub fn KcpServer::size(self : KcpServer) -> Int32 {
  self.sessions.length()
}

///|
/// 在册 conv 清单(宿主逐会话 poll 用)。
pub fn KcpServer::convs(self : KcpServer) -> Array[Int32] {
  let out : Array[Int32] = []
  for conv, _session in self.sessions {
    out.push(conv)
  }
  out
}

///|
/// 闲置清扫:current - last_active > idle_timeout 的会话移除并返回
/// 被逐 conv 清单。纯形:时钟由宿主注入,清扫由宿主在驱动环里调。
pub fn KcpServer::sweep(
  self : KcpServer,
  current : Int32,
  idle_timeout : Int32,
) -> Array[Int32] {
  let stale : Array[Int32] = []
  for conv, session in self.sessions {
    if itimediff(current, session.last_active()) > idle_timeout {
      stale.push(conv)
    }
  }
  let evicted : Array[Int32] = []
  let mut i = 0
  while i < stale.length() {
    let conv = stale[i]
    self.sessions.remove(conv)
    evicted.push(conv)
    i += 1
  }
  evicted
}