package mcmas.core;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;

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

@Deprecated
public class MCMPointer {
	
	public static MCMPointer to(byte[] data) {
		return to(data, false);
	}
	
	public static MCMPointer to(byte[] data, boolean direct) {
		final int size = data.length;
		final ByteBuffer buffer = allocate(size, direct).put(data);
		return new MCMPointer(size, buffer);
	}
	
	public static MCMPointer to(short[] data) {
		return to(data, false);
	}
	
	public static MCMPointer to(short[] data, boolean direct) {
		final int size = data.length * Short.SIZE;
		final ShortBuffer buffer = allocate(size, direct).asShortBuffer().put(data);
		return new MCMPointer(size, buffer);
	}
	
	public static MCMPointer to(int[] data) {
		return to(data, false);
	}
	
	public static MCMPointer to(int[] data, boolean direct) {
		final int size = data.length * Integer.SIZE;
		
		final IntBuffer buffer = allocate(size, direct).asIntBuffer().put(data);
		return new MCMPointer(size, buffer);
	}
	
	public static MCMPointer to(long[] data) {
		return to(data, false);
	}
	
	public static MCMPointer to(long[] data, boolean direct) {
		final int size = data.length * Long.SIZE;
		
		final LongBuffer buffer = (direct ? allocate(size, direct).asLongBuffer().put(data) : LongBuffer.wrap(data));
		return new MCMPointer(size, buffer);
	}
	
	public static MCMPointer to(float[] data) {
		return to(data, false);
	}
	
	public static MCMPointer to(float[] data, boolean direct) {
		final int size = data.length * Float.SIZE;
		final FloatBuffer buffer = allocate(size, direct).asFloatBuffer().put(data);
		return new MCMPointer(size, buffer);
	}
	
	public static MCMPointer to(double[] data) {
		return to(data, false);
	}
	
	public static MCMPointer to(double[] data, boolean direct) {
		final int size = data.length * Double.SIZE;
		DoubleBuffer buffer = allocate(size, direct).asDoubleBuffer().put(data);
		return new MCMPointer(size, buffer);
	}
	
	public static MCMPointer to(Struct data, boolean direct) {
		final int size = SizeofStruct.sizeof(data.getClass());
		final ByteBuffer buffer = Buffers.allocateBuffer(data);
		Buffers.writeToBuffer(buffer, data);
		return new MCMPointer(size, buffer);
	}
	
	public static MCMPointer Using(Struct[] data, boolean direct) {
		final int elemSize = SizeofStruct.sizeof(data.getClass().getComponentType());
		final int size = data.length * elemSize;
		final ByteBuffer buffer = Buffers.allocateBuffer(data);
		Buffers.writeToBuffer(buffer, data);
		return new MCMPointer(size, buffer);
	}
	
	private static ByteBuffer allocate(int capacity, boolean direct) {
		return direct ? ByteBuffer.allocateDirect(capacity) : ByteBuffer.allocate(capacity);
	}
	
	private int size;
	private Buffer buffer;
	
	public MCMPointer(int size, Buffer buffer) {
		this.size = size;
		this.buffer = buffer;
	}
	
	public int getSize() {
		return size;
	}
	
	public Buffer getBuffer() {
		return buffer;
	}
	
	public Pointer getPointer() {
		return Pointer.to(buffer);
	}

}
