#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Rng {
    pub state: u64,
    pub inc: u64,
}

impl Default for Rng {
    fn default() -> Self {
        Self {
            state: 0x853c49e6748fea9b,
            inc: 0xda3e39cb94b95bdb,
        }
    }
}

impl Rng {
    pub fn set_sequence(&mut self, init_seq: u64) {
        self.state = 0;
        self.inc = (init_seq << 1) | 1;
        self.uniform_u32(); // Warm up
        // PCG32_DEFAULT_STATE
        self.state = self.state.wrapping_add(0x853c49e6748fea9b);
        self.uniform_u32();
    }

    pub fn set_sequence_with_offset(&mut self, sequence_index: u64, offset: u64) {
        self.state = 0;
        self.inc = (sequence_index << 1) | 1;
        self.uniform_u32();
        self.state = self.state.wrapping_add(offset);
        self.uniform_u32();
    }

    pub fn new(sequence_index: u64) -> Self {
        let mut rng = Self { state: 0, inc: 0 };
        rng.set_sequence(sequence_index);
        rng
    }

    pub fn new_with_offset(sequence_index: u64, offset: u64) -> Self {
        let mut rng = Self { state: 0, inc: 0 };
        rng.set_sequence_with_offset(sequence_index, offset);
        rng
    }

    pub fn advance(&mut self, delta: u64) {
        // TODO: Implementation of PCG32 advance/seek
        for _ in 0..delta {
            self.uniform_u32();
        }
    }

    pub fn uniform<T>(&mut self) -> T
    where
        T: From<f32>,
    {
        // Convert u32 to float [0,1)
        let v = self.uniform_u32();
        let f = (v as f32) * 2.3283064365386963e-10; // 1 / 2^32
        T::from(f)
    }

    fn uniform_u32(&mut self) -> u32 {
        let oldstate = self.state;
        self.state = oldstate
            .wrapping_mul(6364136223846793005)
            .wrapping_add(self.inc);
        let xorshifted = (((oldstate >> 18) ^ oldstate) >> 27) as u32;
        let rot = (oldstate >> 59) as u32;
        (xorshifted >> rot) | (xorshifted << ((0u32.wrapping_sub(rot)) & 31))
    }
}
