package randomfactory.generator;

import java.util.concurrent.atomic.AtomicLong;

import randomfactory.RandomGenerator;

final public class RandomGeneratorThreadLocal extends RandomGeneratorIntMaskBasedConcurrent {

	public RandomGeneratorThreadLocal() {
		this( new RandomGeneratorMersenneTwister() ) ;
	}
	
	public RandomGeneratorThreadLocal(long seed) {
		this( new RandomGeneratorMersenneTwister(seed) ) ;
	}
	
	public RandomGeneratorThreadLocal(RandomGenerator... randomGenerators) {
		if ( randomGenerators == null || randomGenerators.length == 0 ) throw new IllegalArgumentException("invalid randomGenerators: "+ randomGenerators) ;
		
		if ( randomGenerators.length == 1 ) {
			this.mainGenerator = randomGenerators[0] ;
		}
		else {
			this.mainGenerator = new RandomGeneratorHybrid(randomGenerators) ;
		}
	}
	
	final private RandomGenerator mainGenerator ;
	
	final private ThreadLocal<RandomGenerator> threadLocalGenerator = new ThreadLocal<RandomGenerator>() ;
	
	final private AtomicLong seedCount = new AtomicLong(0L) ;
	
	public long createSeed() {
		long seed = System.nanoTime() ;
		
		synchronized (mainGenerator) {
			seed = seed ^ mainGenerator.nextLong() ;
			seed = seed ^ mainGenerator.nextLong() ;
		}
		
		seed = seed + seedCount.incrementAndGet() ;
		
		return seed ;
	}
	
	public RandomGenerator getRandomGenerator() {
		RandomGenerator generator = threadLocalGenerator.get() ;
		if (generator != null) return generator ;
		
		generator = mainGenerator.newInstance( createSeed() ) ;
		
		threadLocalGenerator.set(generator);
		
		return generator ;
	}
	
	@Override
	protected int next32() {
		return getRandomGenerator().nextInt() ;
	}

	@Override
	public RandomGeneratorThreadLocal clone() {
		return new RandomGeneratorThreadLocal( getRandomGenerator() ) ;
	}
	@Override
	public RandomGeneratorThreadLocal newInstance() {
		return new RandomGeneratorThreadLocal( this.mainGenerator.newInstance() );
	}

	@Override
	public RandomGeneratorThreadLocal newInstance(long... seed) {
		return new RandomGeneratorThreadLocal( this.mainGenerator.newInstance(seed) );
	}

	@Override
	public void initialize(long... seed) {
		getRandomGenerator().initialize(seed);
	}
	
}

@@ -965,16 +965,125 @@
 ator%3E() 
+%7B%0A%09%09protected RandomGenerator initialValue() %7B%0A%09%09%09return mainGenerator.newInstance( createSeed() ) ;%09%0A%09%09%7D;%0A%09%7D
 ;%0A%09%0A%09fin
@@ -1455,233 +1455,41 @@
 %7B%0A%09%09
-RandomGenerator generator = threadLocalGenerator.get() ;%0A%09%09if (generator != null) return generator ;%0A%09%09%0A%09%09generator = mainGenerator.newInstance( createSeed() ) ;%0A%09%09%0A%09%09threadLocalGenerator.set(generator);%0A%09%09%0A%09%09return generator
+return threadLocalGenerator.get()
  ;%0A%09
@@ -1538,25 +1538,27 @@
 %09return 
-getRandom
+threadLocal
 Generato
@@ -1558,16 +1558,20 @@
 enerator
+.get
 ().nextI

define init value for thread local