package mior;

/*
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ExecutionException;

import javax.swing.JFrame;

import mior.model.IMiorModel;

import org.jocl.Pointer;
import org.jocl.Sizeof;
import org.jocl.struct.Buffers;
import org.jocl.struct.SizeofStruct;

import ocl.OCL;
import ocl.OCLCommandQueue;
import ocl.OCLContext;
import ocl.OCLEvent;
import ocl.OCLKernel;
import ocl.OCLMem;
import ocl.OCLProgram;

public class MiorModel implements IMiorModel {
	
	private MiorMM  [] mmList;
	private OCLMem     mmMem;
	
	private MiorOM  [] omList;
	private OCLMem     omMem;
	
	private int     [] associations;
	private OCLMem     associationsMem;
	
	private MiorWorld  world;
	private OCLMem     worldMem;
	
	private OCLContext context;
	private OCLProgram program;
	private OCLCommandQueue queue;
	
	public MiorModel() {
		initializeOpenCL();
		
		this.world = new MiorWorld();
		
		this.worldMem = context.createBuffer(1, MiorWorld.class, OCL.MEM_RW, world);
		
		this.worldSize = SizeofStruct.sizeof(MiorWorld.class);
		
		this.associations = new int[world.nbMM * world.nbOM];
		this.associationsSize = associations.length * Sizeof.cl_int;
		this.associationsMem = context.createBuffer(associations.length, OCL.INT, OCL.MEM_RW);
		
		initializeMM();
		initializeOM();
		
		computeTopography();
		computeLive();
		
		releaseOpenCL();
	}
	
	public void computeTopography() {
		OCLKernel topographyKernel = program.createKernel("topography");
		
		topographyKernel.setArguments(mmMem, omMem, associationsMem, worldMem);
		
		OCLEvent event = queue.enqueueKernel(
				topographyKernel, 2,
				new long[] { 0, 0 },
				new long[] { mmList.length, omList.length },
				new long[] { 1, 1 }
		);
		
		try {
			event.get();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		queue.blockingReadBuffer(associationsMem, Pointer.to(associations), 0, associationsSize);
		System.out.println(Arrays.toString(associations));
		System.out.println(associations.length);
	}
	
	public void computeLive() {
		OCLKernel liveKernel = program.createKernel("topography");
		
		liveKernel.setArguments(mmMem, omMem, associationsMem, worldMem);
		
		OCLEvent event = queue.enqueue1DKernel(liveKernel, mmList.length, 1);
		
		try {
			event.get();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		queue.blockingReadBuffer(associationsMem, Pointer.to(associations), 0, associationsSize);
		System.out.println(Arrays.toString(associations));
		System.out.println(associations.length);
	}
	
	private void initializeMM() {
		Random rand = new Random();
		
		this.mmList = new MiorMM[world.nbMM];
		
		for (int i = 0; i < world.nbMM; i++) {
			mmList[i] = new MiorMM(
					rand.nextInt(world.width),
					rand.nextInt(world.width)
			);
		}
		
		this.mmBuffer = Buffers.allocateBuffer(mmList);
		Buffers.writeToBuffer(mmBuffer, mmList);
		
		this.mmSize = mmList.length * SizeofStruct.sizeof(MiorMM.class);
		this.mmMem = context.createBuffer(mmSize, OCL.MEM_RW, Pointer.to(mmBuffer));
	}
	private void initializeOM() {
		Random rand = new Random();
		
		this.omList = new MiorOM[world.nbOM];
		
		for (int i = 0; i < world.nbOM; i++) {
			omList[i] = new MiorOM(
					rand.nextInt(world.width),
					rand.nextInt(world.width)
			);
		}
		
		this.omBuffer = Buffers.allocateBuffer(omList);
		Buffers.writeToBuffer(omBuffer, omList);
		
		this.omSize = omList.length * SizeofStruct.sizeof(MiorOM.class);
		this.omMem = context.createBuffer(omSize, OCL.MEM_RW, Pointer.to(omBuffer));
	}
	
	private void initializeOpenCL() {
		this.context = new OCLContext();
		this.queue = context.createCommandQueue();
		
		try {
			this.program = context.createProgram(readFileAsString("/home/glaville/mior.cl"));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void releaseOpenCL() {
		associationsMem.release();
		worldMem.release();
		mmMem.release();
		omMem.release();
		queue.release();
		context.release();
	}
	
	@Override
	public MiorOM[] getOMList() {
		return omList;
	}
	
	@Override
	public MiorMM[] getMMList() {
		return mmList;
	}
	
	@Override
	public MiorWorld getWorld() {
		return world;
	}
	
	@Override
	public int[] getAssociations() {
		return associations;
	}
	
	private static String readFileAsString(String filePath) throws java.io.IOException{
	    byte[] buffer = new byte[(int) new File(filePath).length()];
	    FileInputStream f = new FileInputStream(filePath);
	    f.read(buffer);
	    return new String(buffer);
	}

}*/
