package preypredator;

import java.nio.IntBuffer;
import java.util.Random;

import org.jocl.Pointer;

import mcmas.core.MCMCommandQueue;
import mcmas.core.MCMContext;
import mcmas.core.MCMEvent;
import mcmas.core.MCMKernel;
import mcmas.core.MCMMem;
import mcmas.core.MCMProgram;
import mcmas.core.MCMUtils;
import mior.model.RandomState;

public class OldPreyPredatorSimulation {
	
	private final int size;
	private final int nbPreys;
	private final int nbPredators;
	private final RandomState[] rngList;
	private final PPWorld world;
	
	private final IntBuffer grass;
	private final IntBuffer preys;
	private final IntBuffer predators;
	
	private MCMProgram program;
	private MCMKernel  grassKernel;
	private MCMKernel  preysKernel;
	private MCMKernel  predatorsKernel;
	
	private MCMMem grassBuffer;
	private MCMMem preysBuffer;
	private MCMMem predatorsBuffer;
	private MCMMem rngListBuffer;
	private MCMMem worldBuffer;
	
	public OldPreyPredatorSimulation(int size, int nbPreys, int nbPredators) {
		this.size = size;
		this.nbPreys = nbPreys;
		this.nbPredators = nbPredators;
		
		this.grass = IntBuffer.allocate(size * size);
		this.preys = IntBuffer.allocate(size * size);
		this.predators = IntBuffer.allocate(size * size);
		
		this.rngList = new RandomState[size * size];
		this.world = new PPWorld();
	}
	
	public void prepare(MCMContext context) {
		this.program = MCMUtils.compileFile(context, "kernels/preypredators2.cl");
	    this.grassKernel = program.createKernel("live_grass");
		this.preysKernel = program.createKernel("live_preys");
		this.predatorsKernel = program.createKernel("live_predators");
		
		Random random = new Random();
		
		for (int i = 0; i < size * size; i++) {
			rngList[i].a = random.nextLong();
			rngList[i].b = 0;
			rngList[i].c = 362436;
		}
		
		this.grassBuffer = context.newBuffer().Using(grass).b();
		this.preysBuffer = context.newBuffer().Using(preys).b();
		this.predatorsBuffer = context.newBuffer().Using(predators).b();
		this.rngListBuffer = context.newBuffer().Using(rngList).b();
		this.worldBuffer = context.newBuffer().Using(world).b();
		
		grassKernel.setArguments(grassBuffer, rngListBuffer, worldBuffer);
		preysKernel.setArguments(grassBuffer, preysBuffer, rngListBuffer, worldBuffer);
		predatorsKernel.setArguments(preysBuffer, predatorsBuffer, rngListBuffer, worldBuffer);
	}
	
	public void run(MCMCommandQueue queue, int iterations) {
		
		MCMEvent grassFinished = queue.enqueue1DKernel(grassKernel, size * size);
		MCMEvent preysFinished = queue.enqueue1DKernel(preysKernel, size * size, grassFinished);
		MCMEvent predatorsFinished = queue.enqueue1DKernel(predatorsKernel, size * size, preysFinished);
	}
	
	public MCMEvent[] copyDataOnGPU(MCMCommandQueue queue) {
		MCMEvent e1 = queue.enqueueWriteBuffer(grassBuffer, Pointer.to(grass), 0, grassBuffer.getSize());
		MCMEvent e2 = queue.enqueueWriteBuffer(preysBuffer, Pointer.to(preys), 0, preysBuffer.getSize());
		MCMEvent e3 = queue.enqueueWriteBuffer(predatorsBuffer, Pointer.to(predators), 0, predatorsBuffer.getSize());
		MCMEvent e4 = queue.enqueueWriteBuffer(rngListBuffer, rngList, 0, rngListBuffer.getSize());
		MCMEvent e5 = queue.enqueueWriteBuffer(worldBuffer, new PPWorld [] { world }, 0, worldBuffer.getSize());
		
		return new MCMEvent[] { e1, e2, e3, e4, e5 };
	}
	
	public void copyDataFromGPU(MCMCommandQueue queue) {
		
	}
	
	public void release() {
		grassBuffer.release();
		preysBuffer.release();
		predatorsBuffer.release();
		rngListBuffer.release();
		worldBuffer.release();
		
		predatorsKernel.release();
		preysKernel.release();
		grassKernel.release();
		program.release();
	}
	
	
}
