use std::time::{SystemTime, UNIX_EPOCH};

pub(crate) fn current_time_and_seed() -> Result<(i64, u64), String> {
    let duration = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .map_err(|error| error.to_string())?;
    Ok((duration.as_secs() as i64, duration.as_nanos() as u64))
}

pub(crate) fn shuffle_indices(indices: &mut [usize], seed: u64) {
    if indices.len() < 2 {
        return;
    }

    let mut state = seed ^ ((indices.len() as u64) << 32);
    for index in (1..indices.len()).rev() {
        let random = splitmix64(&mut state);
        let swap_index = (random as usize) % (index + 1);
        indices.swap(index, swap_index);
    }
}

fn splitmix64(state: &mut u64) -> u64 {
    *state = state.wrapping_add(0x9e3779b97f4a7c15);
    let mut value = *state;
    value = (value ^ (value >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
    value = (value ^ (value >> 27)).wrapping_mul(0x94d049bb133111eb);
    value ^ (value >> 31)
}
