///|
/// V0.3 冒烟示例:定点数、状态哈希、输入环、回滚会话、字节协议、确定性链路。
///
/// 运行:
///   moon run cmd/main --target wasm-gc
///
/// 模型:两个玩家的输入都混入同一个 64 位状态,用来验证两端收敛。
struct Demo {
  mut x : UInt64
}

///|
impl @session.Sim for Demo with fn save(self) -> Bytes {
  Bytes::makei(8, fn(i) { ((self.x >> (i * 8)) & 0xFFUL).to_int().to_byte() })
}

///|
impl @session.Sim for Demo with fn restore(self, bytes : Bytes) -> Unit {
  let mut x = 0UL
  let mut i = 0
  while i < 8 {
    x = x | (bytes[i].to_int().to_uint64() << (i * 8))
    i = i + 1
  }
  self.x = x
}

///|
impl @session.Sim for Demo with fn step_players(self, inputs : Array[UInt64]) -> Unit {
  let mut x = self.x * 31UL
  let mut i = 0
  for bits in inputs {
    x = x + ((bits & 0xFFUL) << (i * 8))
    i = i + 1
  }
  self.x = x
}

///|
impl @session.Sim for Demo with fn hash(self) -> UInt64 {
  @digest.hash_u64(self.x)
}

///|
fn input_of(frame : Int32, salt : Int32) -> UInt64 {
  (frame.to_uint64() * 2654435761UL + salt.to_uint64() * 97UL) & 0xFFUL
}

///|
/// 把一条线上的字节解成消息,投递给会话。
fn apply(payload : Bytes, s : @session.Session[Demo]) -> Unit {
  for msg in @protocol.decode_batch(payload) {
    match msg {
      @protocol.Input(x) => {
        let mut i = 0
        for bits in x.inputs {
          s.receive_from(x.player + i, x.frame, bits)
          i = i + 1
        }
      }
      _ => ()
    }
  }
}

///|
fn main {
  // 1) 定点数:整数运算,跨后端逐位一致
  let a = @fixed.Fixed::from_double(1.5)
  let b = @fixed.Fixed::from_double(2.25)
  println("fixed 1.5 * 2.25 = " + (a * b).to_double().to_string())
  println(
    "fixed sqrt(2)     = " +
    @fixed.Fixed::from_int(2).sqrt().to_double().to_string(),
  )
  println(
    "fixed lerp(0,10,.3)= " +
    @fixed.lerp(
      @fixed.Fixed::from_int(0),
      @fixed.Fixed::from_int(10),
      @fixed.Fixed::from_double(0.3),
    )
    .to_double()
    .to_string(),
  )
  // 2) 状态哈希:回滚两侧比对
  let d = @digest.Digest::new()
  d.feed_bytes(b"hello")
  println("digest fnv1a(hello) = " + d.finish().to_string())
  // 3) 输入环:按帧号随机存取
  let ring = @input.InputRing::new(8)
  ring.set(42, 0b101UL)
  match ring.get(42) {
    Some(bits) => println("input frame 42      = " + bits.to_string())
    None => println("input frame 42      = missing")
  }
  // 4) 回滚会话:2 帧延迟下两个对等体跑 300 帧后状态一致
  let total = 300
  let delay = 2
  let pa = @session.Session::with_window({ x: 0UL, }, 0, 128)
  let pb = @session.Session::with_window({ x: 0UL, }, 1, 128)
  let mut f = 0
  while f < total {
    f = f + 1
    ignore(pa.advance(input_of(f, 0)))
    ignore(pb.advance(input_of(f, 1)))
    let arrived = f - delay
    if arrived >= 1 {
      pa.receive(arrived, input_of(arrived, 1))
      pb.receive(arrived, input_of(arrived, 0))
    }
  }
  let mut drain = total - delay + 1
  while drain <= total {
    pa.receive(drain, input_of(drain, 1))
    pb.receive(drain, input_of(drain, 0))
    drain = drain + 1
  }
  println(
    "rollback peers equal = " +
    (pa.hash() == pb.hash()).to_string() +
    ", rollbacks = " +
    pa.rollbacks().to_string() +
    ", frames = " +
    pa.frame().to_string(),
  )
  // 5) 字节协议:输入帧 4 字节、确认帧 3 字节、校验和帧 10 字节
  let wire = @protocol.InputFrame::new(1000, [0b101UL, 0b010UL])
  let payload = @protocol.encode(@protocol.Message::Input(wire))
  println("protocol input      = " + payload.length().to_string() + " bytes")
  println(
    "protocol round-trip = " +
    (@protocol.decode(payload) == Some(@protocol.Message::Input(wire))).to_string(),
  )
  // 6) 确定性链路:延迟 6 帧 + 抖动 3 帧 + 10% 乱序,包体走真实字节协议
  let total_net = 300
  let resend = 16
  let net_ab = @sim_net.NetSim::new(@sim_net.Link::new(6, 3, 0, 10, 20261028UL))
  let net_ba = @sim_net.NetSim::new(@sim_net.Link::new(6, 3, 0, 10, 777UL))
  let na = @session.Session::with_window({ x: 0UL, }, 0, 128)
  let nb = @session.Session::with_window({ x: 0UL, }, 1, 128)
  let mut n = 0
  while n < total_net {
    n = n + 1
    ignore(na.advance(input_of(n, 0)))
    ignore(nb.advance(input_of(n, 1)))
    // 每个包夹带最近 `resend` 帧的输入,充当伪可靠层
    let mut back = n - resend + 1
    if back < 1 {
      back = 1
    }
    let ab : Array[@protocol.Message] = []
    let ba : Array[@protocol.Message] = []
    let mut m = back
    while m <= n {
      ab.push(
        @protocol.Message::Input(
          @protocol.InputFrame::new_from(0, m, [input_of(m, 0)]),
        ),
      )
      ba.push(
        @protocol.Message::Input(
          @protocol.InputFrame::new_from(1, m, [input_of(m, 1)]),
        ),
      )
      m = m + 1
    }
    net_ab.send(n, @protocol.encode_batch(ab))
    net_ba.send(n, @protocol.encode_batch(ba))
    for p in net_ab.recv(n) {
      apply(p, nb)
    }
    for p in net_ba.recv(n) {
      apply(p, na)
    }
  }
  // 收尾:再推进若干帧,让在途与乱序的包全部送达
  let mut t = total_net
  while t < total_net + 64 {
    t = t + 1
    for p in net_ab.recv(t) {
      apply(p, nb)
    }
    for p in net_ba.recv(t) {
      apply(p, na)
    }
  }
  println(
    "sim_net peers equal = " +
    (na.hash() == nb.hash()).to_string() +
    ", confirmed = " +
    na.confirmed().to_string() +
    "/" +
    nb.confirmed().to_string() +
    ", rollbacks = " +
    na.rollbacks().to_string() +
    "/" +
    nb.rollbacks().to_string(),
  )
  println(
    "sim_net packets     = delivered " +
    net_ab.delivered().to_string() +
    ", dropped " +
    net_ab.dropped().to_string() +
    ", in_flight " +
    net_ab.in_flight().to_string(),
  )
  println("moonroll version    = " + @moonroll.version())
}