package projectzombie.audio;

import static org.lwjgl.openal.AL10.AL_BUFFER;
import static org.lwjgl.openal.AL10.AL_FORMAT_MONO16;
import static org.lwjgl.openal.AL10.AL_FORMAT_STEREO16;
import static org.lwjgl.openal.AL10.AL_GAIN;
import static org.lwjgl.openal.AL10.AL_POSITION;
import static org.lwjgl.openal.AL10.alBufferData;
import static org.lwjgl.openal.AL10.alGenBuffers;
import static org.lwjgl.openal.AL10.alSource3f;
import static org.lwjgl.openal.AL10.alSourcePlay;
import static org.lwjgl.openal.AL10.alSourceStop;
import static org.lwjgl.openal.AL10.alSourcef;
import static org.lwjgl.openal.AL10.alSourcei;

import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;

import org.lwjgl.stb.STBVorbis;
import org.lwjgl.system.MemoryStack;

import gl_engine.matrix.Matrix4;
import gl_engine.vec.Vec3d;
import projectzombie.Main;
import projectzombie.display.Camera;
import projectzombie.resources.Resource;

public class AudioObject
{
	double volume;
	int bufferPointer;
	Resource resource;
	boolean error;
	int channels;
	int sample_rate;
	int output;
	
	public AudioObject(Resource resource, double volume)
	{
		// Store the argument values
		this.resource = resource;
		this.volume = volume;
		this.error = false;
	}
	
	public void init()
	{
		// Create some buffers
		MemoryStack stack = MemoryStack.stackPush();
		IntBuffer channels_buf = stack.mallocInt(1);
		IntBuffer sample_rate_buf = stack.mallocInt(1);
		
		// Get the audio
		ByteBuffer resource_buffer = resource.getByteBuffer();
		ShortBuffer audio = STBVorbis.stb_vorbis_decode_memory(resource_buffer, channels_buf, sample_rate_buf);
		
		if(audio == null) {
			error = true;
			return;
		}
		
		// Get the channels and the sample rate
		channels = channels_buf.get();
		sample_rate = sample_rate_buf.get();
		
		//Find the correct OpenAL format
		int format = -1;
		if(channels == 1) {
		    format = AL_FORMAT_MONO16;
		} else if(channels == 2) {
		    format = AL_FORMAT_STEREO16;
		}
		
		// Send the data to OpenAL
		bufferPointer = alGenBuffers();
		
		alBufferData(bufferPointer, format, audio, sample_rate);
		
		// Free some c buffers
		//LibCStdlib.free(audio);
		//LibCStdlib.free(resource_buffer);
	}
	
	public void play(Vec3d pos, double volume)
	{
		if(error) {
			return;
		}
		
		// Calculate the position relative to the player
		Matrix4 matrix = Camera.camera.matrix;
		Vec3d vec = Matrix4.multiply(matrix, pos.subtract(Main.player.getPos())).multiply(0.125);
		
		// Play the sound with a new source
		int source = AudioSources.getSource();
		alSourceStop(source);
		alSourcei(source, AL_BUFFER, bufferPointer);
		alSourcef(source, AL_GAIN, (float)(volume * this.volume));
		alSource3f(source, AL_POSITION, (float)vec.x, (float)vec.y, (float)vec.z);
		alSourcePlay(source);
	}
}
