/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package qsim.rng;

import java.util.ArrayList;
import qsim.distributions.PseudoHyperExpDist;
import umontreal.iro.lecuyer.probdist.Distribution;
import umontreal.iro.lecuyer.probdist.UniformDist;
import umontreal.iro.lecuyer.randvar.RandomVariateGen;
import umontreal.iro.lecuyer.rng.MRG32k3a;
import umontreal.iro.lecuyer.rng.RandomStream;

/**
 *
 * @author joe
 */
public class HyperExpRandomVariateGen extends RandomVariateGen{
    private ArrayList<RandomVariateGen> rngList;
    public int k;
    private UniformDist p;
    private RandomVariateGen randomExp;
    
    public HyperExpRandomVariateGen(RandomStream s, Distribution dist) {
        super(s, dist);
        if (this.dist instanceof PseudoHyperExpDist) {
            k = dist.getParams().length;
            PseudoHyperExpDist heDist = (PseudoHyperExpDist) this.dist;
            
            p = new UniformDist(0, k-1);
            long[] randExpSeed = {Math.round(Math.random() * 100000), Math.round(Math.random() * 100000), Math.round(Math.random() * 100000),
                    Math.round(Math.random() * 100000), Math.round(Math.random() * 100000), Math.round(Math.random() * 100000)
            };
            MRG32k3a randomExpStream = new MRG32k3a();
            randomExpStream.setSeed(randExpSeed);
            randomExp = new RandomVariateGen(randomExpStream, p);
            
            
            rngList = new ArrayList<RandomVariateGen>();
            for (int i = 0; i < k; i++) {
                
                long[] seed = {Math.round(Math.random() * 100000), Math.round(Math.random() * 100000), Math.round(Math.random() * 100000),
                    Math.round(Math.random() * 100000), Math.round(Math.random() * 100000), Math.round(Math.random() * 100000)
                };
                
                MRG32k3a rngStream = new MRG32k3a();
                rngStream.setSeed(seed);
                
                rngList.add(new RandomVariateGen(rngStream, heDist.getExpDist(i)));
            }
        }
    }

    @Override
    public void nextArrayOfDouble(double[] v, int start, int n) {
    }

    @Override
    public double nextDouble() {
        if (this.dist instanceof PseudoHyperExpDist && k != 0) {
            PseudoHyperExpDist ps = (PseudoHyperExpDist) this.dist;
            int index = (int) Math.round(this.randomExp.nextDouble());
            return this.rngList.get(index).nextDouble();
        }
        return 0;
    }
}
