//! PCG-XSH-RR-64/32 pseudo-random number generator
//! Corresponds to pow_main_dispatch State 0x43
//! Evidence: multiplier 0x5851f42d4c957f2d, inc = seed << 1 | 1

const PCG_MULTIPLIER: u64 = 0x5851f42d4c957f2d;

pub struct PcgRng {
    state: u64,
    inc: u64,
}

impl PcgRng {
    /// Initialize PCG from seed.
    /// Decompiled:
    ///   uVar36 = uVar36 << 1 | 1;  // inc = seed << 1 | 1
    ///   uVar35 = uVar36 * 0x5851f42d4c957f2e + uVar35 * 0x5851f42d4c957f2d;
    pub fn new(seed: u64) -> Self {
        let inc = (seed << 1) | 1; // always odd
        let state = seed
            .wrapping_mul(PCG_MULTIPLIER)
            .wrapping_add(inc.wrapping_mul(PCG_MULTIPLIER.wrapping_add(1)));
        Self { state, inc }
    }

    /// Generate one 32-bit random number.
    /// Decompiled:
    ///   uVar35 = uVar35 * 0x5851f42d4c957f2d + uVar36;
    ///   uVar37 = (uint)(uVar35 >> 0x20);
    ///   uVar6 = uVar37 >> 0xd ^ (uint)(uVar35 >> 0x1b);
    ///   uVar37 = uVar37 >> 0x1b;
    ///   output = uVar6 >> uVar37 | uVar6 << (0x20 - uVar37);
    fn next_u32(&mut self) -> u32 {
        self.state = self.state.wrapping_mul(PCG_MULTIPLIER).wrapping_add(self.inc);
        let hi = (self.state >> 32) as u32;
        let xorshifted = (hi >> 13) ^ ((self.state >> 27) as u32);
        let rot = hi >> 27;
        xorshifted.rotate_right(rot)
    }

    /// Generate 12-byte nonce.
    /// Corresponds to the 12-iteration loop in State 0x43.
    pub fn generate_nonce(&mut self) -> [u8; 12] {
        let mut nonce = [0u8; 12];
        for i in 0..12 {
            nonce[i] = self.next_u32() as u8;
        }
        nonce
    }
}
