/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
*/

//mod hash256;

use hash256::HASH256;

const RAND_NK: usize=21;
const RAND_NJ: usize=6;
const RAND_NV: usize=8;

pub struct RAND {
	ira: [u32;RAND_NK],  /* random number...   */
	rndptr: usize,
	borrow: u32,
	pool_ptr: usize,
	pool: [u8;32]
}

impl RAND {

	pub fn new() -> RAND {
		RAND {
			ira: [0;RAND_NK],
			rndptr:0,
			borrow: 0,
			pool_ptr:0,
			pool:[0;32]
		}
	}

	pub fn clean(&mut self) {
		self.pool_ptr=0; self.rndptr=0;
		for i in 0..32 {self.pool[i]=0}
		for i in 0..RAND_NK {self.ira[i]=0}
		self.borrow=0;		
	}

	fn sbrand(&mut self) -> u32 { /* Marsaglia & Zaman random number generator */
		self.rndptr+=1;
		if self.rndptr<RAND_NK {return self.ira[self.rndptr]}
		self.rndptr=0;
		let mut k=RAND_NK-RAND_NJ;
		for i in 0..RAND_NK { /* calculate next NK values */
			if k==RAND_NK {k=0}
			let t=self.ira[k];
			let pdiff=t.wrapping_sub(self.ira[i]).wrapping_sub(self.borrow);
			if pdiff<t {self.borrow=0}
			if pdiff>t {self.borrow=1}
			self.ira[i]=pdiff; 
			k+=1;
		}
		return self.ira[0];
	}

	fn sirand(&mut self,seed: u32) {
		let mut m: u32=1;
		let mut sd=seed;
		self.borrow=0;
		self.rndptr=0;
		self.ira[0]^=sd;
		for i in 1..RAND_NK { /* fill initialisation vector */
			let inn=(RAND_NV*i)%RAND_NK;
			self.ira[inn]^=m;      /* note XOR */
			let t=m;
			m=sd.wrapping_sub(m);
			sd=t;
		}
		for _ in 0..10000 {self.sbrand();} /* "warm-up" & stir the generator */
	}

	fn fill_pool(&mut self) {
		let mut sh=HASH256::new();
		for _ in 0..128 {sh.process((self.sbrand()&0xff) as u8)}
		let w=sh.hash();
		for i in 0..32 {self.pool[i]=w[i]}
		self.pool_ptr=0;
	}

	fn pack(b: [u8;4]) -> u32 { /* pack 4 bytes into a 32-bit Word */
		return ((((b[3] as u32))&0xff)<<24)|(((b[2] as u32)&0xff)<<16)|(((b[1] as u32)&0xff)<<8)|((b[0] as u32)&0xff);
	}

/* Initialize RNG with some real entropy from some external source */
	pub fn seed(&mut self,rawlen: usize,raw: &[u8]) { /* initialise from at least 128 byte string of raw random entropy */
		let mut b: [u8;4]=[0;4];
		let mut sh=HASH256::new();
		self.pool_ptr=0;

		for i in 0..RAND_NK {self.ira[i]=0}
		if rawlen>0 {
			for i in 0..rawlen {
				sh.process(raw[i]);
			}
			let digest=sh.hash();

/* initialise PRNG from distilled randomness */

			for i in 0..8  {
				b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3];
				self.sirand(RAND::pack(b));
			}
		}
		self.fill_pool();
	}	

/* get random byte */
	pub fn getbyte(&mut self) -> u8 { 
		let r=self.pool[self.pool_ptr];
		self.pool_ptr+=1;
		if self.pool_ptr>=32 {self.fill_pool()}
		return (r&0xff) as u8;
	}
}

/* test main program */
/*
fn main() {
	let mut raw : [u8;100]=[0;100];
	let mut rng=RAND::new();

	rng.clean();
	for i in 0..100 {raw[i]=i as u8}

	rng.seed(100,&raw);
 
	for _ in 0..1000 {
		print!("{:03} ",rng.getbyte());
	}
}
*/
