/*
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 crate::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());
    }
}
*/
