package edu.uprm.walsaip.vte.core.util;

import static java.lang.System.err;

import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;


import static java.nio.ByteOrder.LITTLE_ENDIAN;
public class BufferUtils {
	public static final int 	SIZEOF_BYTE    = 1;
	public static final int 	SIZEOF_DOUBLE  = 8;
	public static final int 	SIZEOF_FLOAT   = 4;
	public static final int 	SIZEOF_INT 	   = 4;
	public static final int 	SIZEOF_LONG    = 8;
	public static final int 	SIZEOF_SHORT   = 2;
	

	public static int unsignedByteToInt(byte b) {
		return (int) b & 0xFF;
	}

	public static int byteArrayToInt(byte buffer[]) {
		int intBits = 0;
		intBits += unsignedByteToInt(buffer[3]) << 24;
		intBits += unsignedByteToInt(buffer[2]) << 16;
		intBits += unsignedByteToInt(buffer[1]) << 8;
		intBits += unsignedByteToInt(buffer[0]) << 0;
		return intBits;
		
	}
	public static int intArrayToInt(int buffer[]) {
		int intBits = 0;
		intBits += buffer[3] << 24;
		intBits += buffer[2] << 16;
		intBits += buffer[1] << 8;
		intBits += buffer[0] << 0;
		return intBits;
		
	}
	public static float intArrayToFloat(int buffer[]) {
		return Float.intBitsToFloat(intArrayToInt(buffer));
	}

	public static float byteArrayToFloat(byte buffer[]) {
		return Float.intBitsToFloat(byteArrayToInt(buffer));
	}
	
	public static short byteArrayToShort(byte buffer[]) {
		short shortBits = 0;
		shortBits += unsignedByteToInt(buffer[1]) << 8;
		shortBits += unsignedByteToInt(buffer[0]) << 0;
		return shortBits;
	}
	
	public static ByteBuffer tryAllocateDirect(int capacity) {
		ByteBuffer buffer = null;
		try {
		buffer = ByteBuffer.allocateDirect(capacity);
		
		} catch (OutOfMemoryError e) {
			err.println("\nWarning: Out of memory error when allocating direct buffer... trying non-direct buffer.");
			buffer = ByteBuffer.allocate(capacity);	
		}
		if (buffer == null) {
			err.println("\nWarning: Failed to allocate direct buffer");
			buffer = ByteBuffer.allocate(capacity);	
		}
		if (buffer != null) {
			buffer.order(LITTLE_ENDIAN);
		}
		else {
			err.println("\nError: Buffer allocation failed.");
		}
		
		
		
		
		return buffer;
	}
	public static FloatBuffer allocateFloatBuffer(int capacity){
		FloatBuffer buffer = BufferUtils.tryAllocateDirect(capacity*SIZEOF_FLOAT).asFloatBuffer();
		//if (buffer != null)
		// TODO monitor buffer allocation
		return buffer; 
	}
	public static IntBuffer allocateIntBuffer(int capacity){
		return BufferUtils.tryAllocateDirect(capacity*SIZEOF_INT).asIntBuffer();
	}
	public static ByteBuffer allocateBuffer(int capacity) {
		ByteBuffer buffer = null;
	
		buffer = ByteBuffer.allocate(capacity);	
		
		if (buffer != null)
			buffer.order(LITTLE_ENDIAN);
		return buffer;
	}
	
}

