///|
/// The page's only door into the library. It exists so a browser can ask
/// ChaCha12 for numbers without re-implementing it: `open` takes the entropy
/// the page collected, `unit` returns the next value in [0, 1).
///
/// The generator sits in a one-slot array because the page calls one function
/// at a time. `ChaCha12` advances through interior mutability, so handing a
/// copy into `random` still moves the stream forward.
let cell : Array[@moonrand.StdRng] = []

///|
fn put_u64(seed : FixedArray[Byte], at : Int32, v : UInt64) -> Unit {
  for i in 0..<8 {
    let shift = (7 - i) * 8
    seed[at + i] = ((v >> shift) & 0xFF).to_int().to_byte()
  }
}

///|
/// Reseed the page's stream. `hi` and `lo` are whatever the page could see
/// that nobody else can repeat: the clock at load, the screen, the pointer,
/// a fresh draw from the platform. Mixing happens on the page side; this side
/// only insists on 32 bytes of seed.
pub fn open(hi : UInt64, lo : UInt64) -> Unit {
  let seed = FixedArray::make(32, (0).to_byte())
  put_u64(seed, 0, hi)
  put_u64(seed, 8, lo)
  put_u64(seed, 16, hi ^ lo)
  put_u64(seed, 24, hi ^ (lo >> 1))
  let bytes = Bytes::from_array(seed)
  cell.push(@moonrand.seeded(bytes[0:]))
}

///|
/// The next number in [0, 1). The page calls this in a loop: one crack network
/// is a few hundred of these.
pub fn unit() -> Double {
  if cell.length() == 0 {
    0.5
  } else {
    @moonrand.random(cell[cell.length() - 1])
  }
}

///|
fn main {
  ignore(unit)
}